Conversation
…n, resolution, and CLI commands - Create src/specify_cli/agent_pack.py with AgentBootstrap base class, AgentManifest schema/validation, pack resolution (user > project > catalog > embedded) - Generate all 25 official agent packs under src/specify_cli/core_pack/agents/ with speckit-agent.yml manifests and bootstrap.py modules - Add 'specify agent' CLI subcommands: list, info, validate, export, switch, search, add, remove - Update pyproject.toml to bundle agent packs in the wheel - Add comprehensive tests (39 tests): manifest validation, bootstrap API, resolution order, discovery, consistency with AGENT_CONFIG Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/ef8b4682-7f1a-4b04-a112-df0878236b6b
…est assertions - Copilot: only remove .github/agents/ (preserves workflows, templates) - Tabnine: only remove .tabnine/agent/ (preserves other config) - Amp/Codex: only remove respective subdirs (commands/skills) to avoid deleting each other's files in shared .agents/ dir - Tests: use flexible assertions instead of hardcoded >= 25 counts Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/ef8b4682-7f1a-4b04-a112-df0878236b6b
mnriem
left a comment
There was a problem hiding this comment.
@copilot The setup should store a list of installed files with their hash in the .specify directory so we can track what was installed by the agent. At teardown time that file needs to be used to determine if ANY of the installed files was updated and if so the remove should require a --force. Note you will NOT delete any directories but rather just the individual files.
Setup records installed files and their SHA-256 hashes in .specify/agent-manifest-<agent_id>.json. Teardown uses the manifest to remove only individual files (never directories). If any tracked file was modified since installation, teardown requires --force. - Add record_installed_files(), check_modified_files(), remove_tracked_files() and AgentFileModifiedError to agent_pack.py - Update all 25 bootstrap modules to use file-tracked setup/teardown - Add --force flag to 'specify agent switch' - Add 11 new tests for file tracking (record, check, remove, force, directory preservation, deleted-file handling, manifest structure) Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/779eabf6-21d5-428b-9f01-dd363df4c84a
…writes files Address code review: setup() now only creates directories, while finalize_setup() (on base class) scans the agent's commands_dir for all files and records them. This ensures files are tracked after the full init pipeline has written them, not before. - Add AgentBootstrap.finalize_setup() that scans commands_dir - Remove premature record_installed_files() from all 25 setup() methods - agent_switch calls finalize_setup() after setup() completes - Update test helper to match new pattern Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/779eabf6-21d5-428b-9f01-dd363df4c84a
Implemented in b5a5e3f (file tracking) and a63c248 (finalize_setup fix):
|
mnriem
left a comment
There was a problem hiding this comment.
@copilot the agent setup should report the files it installed as the cli needs to record both what was installed by the agent for the core commands / templates as well as what installed by any extensions. It should the record that. And then BEFORE agent teardown is called determine if any file was changed and ask for confirmation. And then feed those lists into the teardown of the agent and/or the installed extensions.
…wn, categorised manifest - setup() returns List[Path] of installed files so CLI can record them - finalize_setup() accepts agent_files + extension_files for combined tracking - Install manifest categorises files: agent_files and extension_files - get_tracked_files() returns (agent_files, extension_files) split - remove_tracked_files() accepts explicit files dict for CLI-driven teardown - agent_switch checks for modifications BEFORE teardown and prompts user - _reregister_extension_commands() returns List[Path] of created files - teardown() accepts files parameter to receive explicit file lists - All 25 bootstraps updated with new signatures - 5 new tests: categorised manifest, get_tracked_files, explicit file teardown, extension file modification detection Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/32e470fc-6bf5-453c-bf6c-79a8521efa56
| from specify_cli.agent_pack import ( | ||
| BOOTSTRAP_FILENAME, | ||
| MANIFEST_FILENAME, | ||
| MANIFEST_SCHEMA_VERSION, | ||
| AgentBootstrap, | ||
| AgentFileModifiedError, | ||
| AgentManifest, | ||
| AgentPackError, | ||
| ManifestValidationError, | ||
| PackResolutionError, | ||
| ResolvedPack, | ||
| _manifest_path, | ||
| _sha256, | ||
| check_modified_files, | ||
| export_pack, | ||
| get_tracked_files, | ||
| list_all_agents, | ||
| list_embedded_agents, | ||
| load_bootstrap, | ||
| record_installed_files, | ||
| remove_tracked_files, | ||
| resolve_agent_pack, | ||
| validate_pack, | ||
| ) |
| if not manifest_file.is_file(): | ||
| continue | ||
| # Should not raise | ||
| warnings = validate_pack(child) |
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/32e470fc-6bf5-453c-bf6c-79a8521efa56
Implemented in e190116:
|
mnriem
left a comment
There was a problem hiding this comment.
@copilot Are extensions hooked up for setup and teardown? Also are you testing that it similar to our --offline support? We must make sure the install between old (current way of installing) and new (our agent setup/teardown) deliver the exact same files. How do we trigger the new flow? I would suggest --agent
- `specify init --agent claude` resolves through the pack system and records all installed files in .specify/agent-manifest-<id>.json via finalize_setup() after the init pipeline finishes - --agent and --ai are mutually exclusive; --agent additionally enables tracked teardown/switch - init-options.json gains "agent_pack" key when --agent is used - 4 new parity tests verify: pack resolution matches AGENT_CONFIG, commands_dir parity, finalize_setup records pipeline-created files, pack metadata matches CommandRegistrar configuration Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/930d8c4d-ce42-41fb-a40f-561fb1468e81
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/930d8c4d-ce42-41fb-a40f-561fb1468e81
Implemented in c2227a7: Extensions: Yes — fully hooked up in Parity testing: 4 new tests verify that the pack-based flow produces the same results as the AGENT_CONFIG flow:
Triggering the new flow: Added
|
mnriem
left a comment
There was a problem hiding this comment.
You must include parity tests that use the init command for both cases and compare that the ACTUAL generated files and directory structure are identical between the --ai and the --agent flows All agents MUST be tested!
- AgentBootstrap._scaffold_project() calls scaffold_from_core_pack, snapshots before/after, returns all new files - finalize_setup() filters agent_files to only track files under the agent's own directory tree (shared .specify/ files not tracked) - All 25 bootstrap setup() methods call _scaffold_project() and return the actual file list instead of [] - --agent init flow routes through setup() for scaffolding instead of calling scaffold_from_core_pack directly - 100 new tests (TestSetupReturnsFiles): verify every agent's setup() returns non-empty, existing, absolute paths including agent-dir files - Parity tests use CliRunner to invoke the real init command - finalize_setup bug fix: skills-migrated agents (agy) now have their skills directory scanned correctly - 1262 tests pass (452 in test_agent_pack.py alone) Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/054690bb-c048-41e0-b553-377d5cb36b78
| try: | ||
| tracker.start(key) | ||
| tracker.complete(key, "mocked") | ||
| except Exception: |
| from specify_cli import AGENT_SKILLS_MIGRATIONS | ||
| if agent in AGENT_SKILLS_MIGRATIONS: | ||
| args.append("--ai-skills") | ||
| except (ImportError, AttributeError): |
| f"'{agent_dir.relative_to(project)}' missing " | ||
| f"(skills migration removes commands)") | ||
| return | ||
| except (ImportError, AttributeError): |
…mments Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/spec-kit/sessions/054690bb-c048-41e0-b553-377d5cb36b78
Implemented in 9b580a5 and 978addc: Extensions hooked up: Yes — setup() owns scaffolding and returns files: Each bootstrap's --agent triggers the new flow: |
Adding a new agent today requires changes to 10+ files across 5 languages. This PR introduces the foundational agent pack infrastructure that replaces the monolithic
AGENT_CONFIG+ case/switch architecture with self-contained, declarative agent packs — while preserving full backward compatibility during migration.Agent pack module (
src/specify_cli/agent_pack.py)AgentManifest— parsed/validatedspeckit-agent.ymlwith schema version enforcementAgentBootstrap— abstract base withsetup() → List[Path]/teardown(force, files)/finalize_setup(agent_files, extension_files)lifecycle contract~/.specify/agents/) → project (.specify/agents/) → catalog cache → embedded in wheelload_bootstrap()dynamically imports pack's bootstrap module and discovers theAgentBootstrapsubclassvalidate_pack(),export_pack(),list_embedded_agents(),list_all_agents()setup()owns scaffolding and returns actual installed filesEach bootstrap's
setup()calls_scaffold_project(), a base-class helper that invokesscaffold_from_core_pack, snapshots the project directory before and after, and returns every new file created. This meanssetup()is the single entry point for agent installation — it runs the shared scaffolding and reports what it created._scaffold_project(project_path, script_type)— callsscaffold_from_core_pack, diffs before/after snapshots, returnsList[Path]of all new filescollect_installed_files(project_path)— scans the agent's directory tree and returns all files foundfinalize_setup(agent_files, extension_files)— filtersagent_filesto only track files under the agent's own directory tree (shared.specify/infrastructure is not tracked per-agent), scans for additional files from later pipeline steps (skills, extensions), and writes.specify/agent-manifest-<agent_id>.jsonInstalled-file tracking with SHA-256 hashes
finalize_setup(agent_files, extension_files)accepts categorised file lists from the CLI and records them in.specify/agent-manifest-<agent_id>.jsonwith separateagent_filesandextension_filessectionsget_tracked_files()returns an(agent_files, extension_files)tuple so the CLI can retrieve and split the tracked setscheck_modified_files()compares current file hashes against the recorded manifest to detect user modifications across both categoriesremove_tracked_files(force, files)deletes only individual tracked files — directories are never deleted. Accepts an explicitfilesdict so the CLI can feed tracked file lists directly into teardown. RaisesAgentFileModifiedErrorif any tracked file was modified since installation andforceisFalse_reregister_extension_commands()returnsList[Path]of files created by extension registration, which are passed tofinalize_setup()asextension_filesCLI-level modification check before teardown
specify agent switchchecks for modified files before calling teardown and prompts the user for confirmation. The CLI retrieves the tracked file lists viaget_tracked_files(), checks for modifications, lists any changed files, and only proceeds with teardown after the user confirms (or if--forceis passed). The file lists are then fed directly intoteardown().--agentflag onspecify initspecify init --agent claudeopts into the pack-based init flow. The--agentflag:setup()— the bootstrap owns the scaffolding process, always using bundled assetsfinalize_setup(agent_files=setup_files)to record every installed file in.specify/agent-manifest-<id>.json"agent_pack": trueininit-options.json--agentand--aiare mutually exclusive.--agentaccepts the same agent IDs as--aibut additionally enables file tracking for clean teardown when switching agents.25 embedded agent packs (
src/specify_cli/core_pack/agents/<id>/)Each pack contains
speckit-agent.ymlandbootstrap.py. Manifests carry command registration metadata (commands_dir,format,arg_placeholder,file_extension) sufficient forCommandRegistrarto render extension commands without importing the bootstrap module.Bundled in the wheel via
pyproject.tomlforce-include.specify agentCLI subcommandslist,info,validate,export,switch,search,add,remove— following the sametyper.Typer()+app.add_typer()pattern asspecify extensionandspecify preset.switchchecks for modified files and prompts before teardown, tears down the old agent (file-by-file using the tracked file lists), sets up the new one, re-registers extension commands, then callsfinalize_setup()with both agent and extension files to record the new install manifest. Updatesinit-options.jsonaccordingly.Backward compatibility
AGENT_CONFIGand all existing code paths are untouched. The pack system is purely additive —specify init --ai <agent>continues to resolve throughAGENT_CONFIG. Pack-based resolution is available viaspecify init --agent <agent>andspecify agentcommands and will become the default after validation.Tests
452 new tests in
test_agent_pack.pycovering:AGENT_CONFIGandCommandRegistrar.AGENT_CONFIGSsetup()returns actual files (TestSetupReturnsFiles, 100 tests) — every agent'ssetup()returns non-empty list of existing absolute paths, including files under the agent's directory treeTestInitFlowParity, 300 tests) — usestyper.testing.CliRunnerto invoke the realspecify initcommand for both--aiand--agentflows across all 25 agents, comparing file sets, file contents, directory structure, tracking manifests, commands_dir alignment, and CommandRegistrar metadata byte-for-byte✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.