-
Notifications
You must be signed in to change notification settings - Fork 11.9k
feat(extensions): let extensions contribute always-on instructions #4259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
TheovanKraay
wants to merge
4
commits into
github:main
Choose a base branch
from
TheovanKraay:feat/extension-instructions
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
746678d
feat(extensions): let extensions contribute always-on instructions (#…
0e46935
address review: fail-closed on marker-colliding + non-UTF-8 instructi…
d7dc2e7
address re-review: validate instruction description type; cross-scrip…
9af864c
address review: forward configured markers to the emitter; warn when …
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| # Extension-contributed always-on instructions — prototype + evidence | ||
|
|
||
| Prototype for [github/spec-kit#4200](https://github.com/github/spec-kit/issues/4200): | ||
| let an extension contribute an always-on instruction block that reaches the agent | ||
| without any command/hook invocation. Ownership follows the maintainer's decision: | ||
| **core validates the metadata only; the opt-in `agent-context` extension composes and | ||
| owns the agent-file writes.** With `agent-context` not installed, installing an | ||
| extension does not touch agent files. | ||
|
|
||
| **Triggers / lifecycle.** The agent needs no command invocation to *receive* the rules — | ||
| they live in the always-on context file. Composition and refresh are performed by | ||
| `agent-context` itself: its `speckit.agent-context.update` command and its `after_specify` | ||
| / `after_plan` hooks, so the block is written during normal setup, before the agent runs, | ||
| and a disabled or removed extension's block is dropped on the next refresh. A fully | ||
| automatic trigger on `extension add`/`remove` would need an extension-lifecycle hook point | ||
| in core (none exists today — the event system covers agent-runtime events only), so that is | ||
| deliberately left as a follow-up owned by `agent-context`. | ||
|
|
||
| ## What changed | ||
|
|
||
| - **Core (`src/specify_cli/extensions/__init__.py`)** — accepts and validates a new | ||
| `provides: instructions:` capability (list of `{ file, description? }`), path-safe via | ||
| the existing `relative_extension_path_violation` guard, exposed as `.instructions`. | ||
| Core performs **no** agent-file writes. An instructions-only extension is valid. | ||
|
TheovanKraay marked this conversation as resolved.
|
||
| - **`agent-context` (`scripts/python/update_agent_context.py`)** — on update, discovers | ||
| installed **and enabled** extensions (reads `.specify/extensions/.registry` + | ||
| each `extension.yml` directly, no CLI dependency), reads each `provides.instructions` | ||
| file, and merges it into the routed agent context file inside a per-extension | ||
| namespaced block: | ||
|
|
||
| ``` | ||
| <!-- SPECKIT EXT:<id> START --> | ||
| …rule block… | ||
| <!-- SPECKIT EXT:<id> END --> | ||
| ``` | ||
|
|
||
| - **bash / PowerShell twins** — delegate to the Python twin's new | ||
| `--emit-extension-blocks` mode, so all three produce **byte-identical** output from a | ||
| single implementation. | ||
|
|
||
| ## Efficacy | ||
|
|
||
| The lift is about **delivery/reachability**, not content or instruction weighting: the | ||
| delivered payload is the same rule block whether it arrives always-on or via a command, so | ||
| when it is present the measured conformance gain carries over by construction. Two | ||
| measurements, same conformance metric, 2 models × 4 languages × 3 complexity (n=24): | ||
|
|
||
| - **This mechanism's exact output.** Bare vs the block this install path actually writes to | ||
| `.github/copilot-instructions.md`, captured byte-for-byte: **+0.123 mean best-practice | ||
| conformance, 22 wins / 0 ties / 2 losses** (both losses tiny, on a near-ceiling model). | ||
| This is the verified, install-path-accurate figure. | ||
| - **Earlier distilled-block pilot** (a shorter, hand-distilled rule block — a *distinct* | ||
| experiment with a *distinct* payload): **+0.142 mean** over bare, vs +0.10 for the same | ||
| content delivered as on-demand commands. Kept for context, not the headline number. | ||
|
|
||
| ## Verification (automated) | ||
|
|
||
| `tests/extensions/test_extension_instructions.py` (13 tests, all passing): | ||
|
|
||
| - **Core validation** — `provides: instructions:` accepted; instructions-only extension is | ||
| valid; non-list rejected; entry missing `file` rejected; path traversal (`/abs`, `..`, | ||
| `sub/../../..`) rejected. | ||
| - **Composition** — enabled extension's block is written into the routed context file with | ||
| namespaced markers and byte-exact payload; disabling an extension removes its block on | ||
| the next update while leaving the base managed section intact; multiple extensions | ||
| coexist in deterministic id order; a path-unsafe manifest entry is skipped; **no agent | ||
| file is written when `agent-context` is not configured**; `--emit-extension-blocks` | ||
| emits the shared block text. | ||
|
|
||
| Full suite (rebased on current `main`): `pytest` → **6916 passed, 415 skipped** | ||
| (the skips are the bash/pwsh cross-execution parity tests, which run on POSIX CI). | ||
|
|
||
| Manual end-to-end (copilot integration) also confirmed: `specify extension add` a | ||
| `provides: instructions:` extension + `agent-context` → the rules appear in | ||
| `.github/copilot-instructions.md`; `disable`/`enable` remove/restore the block; a project | ||
| without `agent-context` gets no agent-file writes. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.