Commit 3899dcc
authored
Stage 2: Copilot integration — proof of concept with shared template primitives (#2035)
* feat: Stage 2a — CopilotIntegration with shared template primitives
- base.py: added granular primitives (shared_commands_dir,
shared_templates_dir, list_command_templates, command_filename,
commands_dest, copy_command_to_directory, record_file_in_manifest,
write_file_and_record, process_template)
- CopilotIntegration: uses primitives to produce .agent.md commands,
companion .prompt.md files, and .vscode/settings.json
- Verified byte-for-byte parity with old release script output
- Copilot auto-registered in INTEGRATION_REGISTRY
- 70 tests (22 new: base primitives + copilot integration)
Part of #1924
* feat: Stage 2b — --integration flag, routing, agent.json, shared infra
- Added --integration flag to init() (mutually exclusive with --ai)
- --ai copilot auto-promotes to integration path with migration nudge
- Integration setup writes .specify/agent.json with integration key
- _install_shared_infra() copies scripts and templates to .specify/
- init-options.json records 'integration' key when used
- 4 new CLI tests: mutual exclusivity, unknown rejection, copilot
end-to-end, auto-promote (74 total integration tests)
Part of #1924
* feat: Stage 2 completion — integration scripts, integration.json, shared manifest
- Added copilot/scripts/update-context.sh and .ps1 (thin wrappers
that delegate to the shared update-agent-context script)
- CopilotIntegration.setup() installs integration scripts to
.specify/integrations/copilot/scripts/
- Renamed agent.json → integration.json with script paths
- _install_shared_infra() now tracks files in
integration-shared.manifest.json
- Updated tests: scripts installed, integration.json has script paths,
shared manifest recorded (74 tests)
Part of #1924
* refactor: rename shared manifest to speckit.manifest.json
Cleaner naming — the shared infrastructure (scripts, templates)
belongs to spec-kit itself, not to any specific integration.
* fix: copilot update-context scripts reflect target architecture
Scripts now source shared functions (via SPECKIT_SOURCE_ONLY=1) and
call update_agent_file directly with .github/copilot-instructions.md,
rather than delegating back to the shared case statement.
* fix: simplify copilot scripts — dispatcher sources common functions
Integration scripts now contain only copilot-specific logic (target
path + agent name). The dispatcher is responsible for sourcing shared
functions before calling the integration script.
* fix: copilot update-context scripts are self-contained implementations
These scripts ARE the implementation — the dispatcher calls them.
They source common.sh + update-agent-context functions, gather
feature/plan data, then call update_agent_file with the copilot
target path (.github/copilot-instructions.md).
* docs: add Stage 7 activation note to copilot update-context scripts
* test: add complete file inventory test for copilot integration
Validates every single file (37 total) produced by
specify init --integration copilot --script sh --no-git.
* test: add PowerShell file inventory test for copilot integration
Validates all 37 files produced by --script ps variant, including
.specify/scripts/powershell/ instead of bash.
* refactor: split test_integrations.py into tests/integrations/ directory
- test_base.py: IntegrationOption, IntegrationBase, MarkdownIntegration, primitives
- test_manifest.py: IntegrationManifest, path traversal, persistence, validation
- test_registry.py: INTEGRATION_REGISTRY
- test_copilot.py: CopilotIntegration unit tests
- test_cli.py: --integration flag, auto-promote, file inventories (sh + ps)
- conftest.py: shared StubIntegration helper
76 integration tests + 48 consistency tests = 124 total, all passing.
* refactor: move file inventory tests from test_cli to test_copilot
File inventories are copilot-specific. test_cli.py now only tests
CLI flag mechanics (mutual exclusivity, unknown rejection, auto-promote).
* fix: skip JSONC merge to preserve user settings, fix docstring
- _merge_vscode_settings() now returns early (skips merge) when
existing settings.json can't be parsed (e.g. JSONC with comments),
instead of overwriting with empty settings
- Updated _install_shared_infra() docstring to match implementation
(scripts + templates, speckit.manifest.json)
* fix: warn user when JSONC settings merge is skipped
* fix: show template content when JSONC merge is skipped
User now sees the exact settings they should add manually.
* fix: document process_template requirement, merge scripts without rmtree
- base.py setup() docstring now explicitly states raw copy behavior
and directs to CopilotIntegration for process_template example
- _install_shared_infra() uses merge/overwrite instead of rmtree to
preserve user-added files under .specify/scripts/
* fix: don't overwrite pre-existing shared scripts or templates
Only write files that don't already exist — preserves any user
modifications to shared scripts (common.sh etc.) and templates.
* fix: warn user about skipped pre-existing shared files
Lists all shared scripts and templates that were not copied because
they already existed in the project.
* test: add test for shared infra skip behavior on pre-existing files
Verifies that _install_shared_infra() preserves user-modified scripts
and templates while still installing missing ones.
* fix: address review — containment check, deterministic prompts, manifest accuracy
- CopilotIntegration.setup() adds dest containment check (relative_to)
- Companion prompts generated from templates list, not directory glob
- _install_shared_infra() only records files actually copied (not pre-existing)
- VS Code settings tests made unconditional (assert template exists)
- Inventory tests use .as_posix() for cross-platform paths
* fix: correct PS1 function names, document SPECKIT_SOURCE_ONLY prerequisite
- Fixed Get-FeaturePaths → Get-FeaturePathsEnv, Read-PlanData → Parse-PlanData
- Documented that shared scripts must guard Main with SPECKIT_SOURCE_ONLY
before these integration scripts can be activated (Stage 7)
* fix: add dict type check for settings merge, simplify PS1 to subprocess
- _merge_vscode_settings() skips merge with warning if parsed JSON
is not a dict (array, null, etc.)
- PS1 update-context.ps1 uses & invocation instead of dot-sourcing
since the shared script runs Main unconditionally
* fix: skip-write on no-op merge, bash subprocess, dynamic integration list
- _merge_vscode_settings() only writes when keys were actually added
- update-context.sh uses exec subprocess like PS1 version
- Unknown integration error lists available integrations dynamically
* fix: align path rewriting with release script, add .specify/.specify/ fix
Path rewrite regex matches the release script's rewrite_paths()
exactly (verified byte-identical output). Added .specify/.specify/
double-prefix fix for additional safety.1 parent b8335a5 commit 3899dcc
File tree
13 files changed
+1263
-254
lines changed- src/specify_cli
- integrations
- copilot
- scripts
- tests/integrations
13 files changed
+1263
-254
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1197 | 1197 | | |
1198 | 1198 | | |
1199 | 1199 | | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
1200 | 1278 | | |
1201 | 1279 | | |
1202 | 1280 | | |
| |||
1828 | 1906 | | |
1829 | 1907 | | |
1830 | 1908 | | |
| 1909 | + | |
1831 | 1910 | | |
1832 | 1911 | | |
1833 | 1912 | | |
| |||
1889 | 1968 | | |
1890 | 1969 | | |
1891 | 1970 | | |
| 1971 | + | |
| 1972 | + | |
| 1973 | + | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
| 1977 | + | |
| 1978 | + | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
| 1983 | + | |
| 1984 | + | |
| 1985 | + | |
| 1986 | + | |
| 1987 | + | |
| 1988 | + | |
| 1989 | + | |
| 1990 | + | |
| 1991 | + | |
| 1992 | + | |
| 1993 | + | |
| 1994 | + | |
| 1995 | + | |
| 1996 | + | |
| 1997 | + | |
| 1998 | + | |
| 1999 | + | |
1892 | 2000 | | |
1893 | 2001 | | |
1894 | 2002 | | |
| |||
2057 | 2165 | | |
2058 | 2166 | | |
2059 | 2167 | | |
2060 | | - | |
| 2168 | + | |
| 2169 | + | |
| 2170 | + | |
| 2171 | + | |
2061 | 2172 | | |
2062 | 2173 | | |
2063 | 2174 | | |
| |||
2092 | 2203 | | |
2093 | 2204 | | |
2094 | 2205 | | |
2095 | | - | |
| 2206 | + | |
| 2207 | + | |
| 2208 | + | |
| 2209 | + | |
| 2210 | + | |
| 2211 | + | |
| 2212 | + | |
| 2213 | + | |
| 2214 | + | |
| 2215 | + | |
| 2216 | + | |
| 2217 | + | |
| 2218 | + | |
| 2219 | + | |
| 2220 | + | |
| 2221 | + | |
| 2222 | + | |
| 2223 | + | |
| 2224 | + | |
| 2225 | + | |
| 2226 | + | |
| 2227 | + | |
| 2228 | + | |
| 2229 | + | |
| 2230 | + | |
| 2231 | + | |
| 2232 | + | |
| 2233 | + | |
| 2234 | + | |
| 2235 | + | |
| 2236 | + | |
| 2237 | + | |
| 2238 | + | |
2096 | 2239 | | |
2097 | 2240 | | |
2098 | 2241 | | |
| |||
2227 | 2370 | | |
2228 | 2371 | | |
2229 | 2372 | | |
2230 | | - | |
| 2373 | + | |
2231 | 2374 | | |
2232 | 2375 | | |
2233 | 2376 | | |
| |||
2237 | 2380 | | |
2238 | 2381 | | |
2239 | 2382 | | |
2240 | | - | |
| 2383 | + | |
| 2384 | + | |
| 2385 | + | |
| 2386 | + | |
2241 | 2387 | | |
2242 | 2388 | | |
2243 | 2389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
0 commit comments