mirror of
https://github.com/github/spec-kit.git
synced 2026-03-17 02:43:08 +00:00
Moves constitution template from memory/ to templates/ to prevent overwrites when spec-kit is reinitialized with a different AI agent. Changes: - Move memory/constitution.md to templates/constitution-template.md - Update CLI to copy template to memory/ only on first initialization - Update constitution command to reference correct paths with .specify/ prefix - Preserve existing constitution.md when reinitializing project The CLI now checks if .specify/memory/constitution.md exists: - If it exists: preserve it (no overwrite) - If it doesn't exist: copy from .specify/templates/constitution-template.md This allows users to customize their constitution without losing changes when adding support for additional AI agents or reinitializing. Fixes #1541 Co-authored-by: jjoung1128 <jinwoong.joung@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -942,6 +942,41 @@ def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None =
|
|||||||
for f in failures:
|
for f in failures:
|
||||||
console.print(f" - {f}")
|
console.print(f" - {f}")
|
||||||
|
|
||||||
|
def ensure_constitution_from_template(project_path: Path, tracker: StepTracker | None = None) -> None:
|
||||||
|
"""Copy constitution template to memory if it doesn't exist (preserves existing constitution on reinitialization)."""
|
||||||
|
memory_constitution = project_path / ".specify" / "memory" / "constitution.md"
|
||||||
|
template_constitution = project_path / ".specify" / "templates" / "constitution-template.md"
|
||||||
|
|
||||||
|
# If constitution already exists in memory, preserve it
|
||||||
|
if memory_constitution.exists():
|
||||||
|
if tracker:
|
||||||
|
tracker.add("constitution", "Constitution setup")
|
||||||
|
tracker.skip("constitution", "existing file preserved")
|
||||||
|
return
|
||||||
|
|
||||||
|
# If template doesn't exist, something went wrong with extraction
|
||||||
|
if not template_constitution.exists():
|
||||||
|
if tracker:
|
||||||
|
tracker.add("constitution", "Constitution setup")
|
||||||
|
tracker.error("constitution", "template not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Copy template to memory directory
|
||||||
|
try:
|
||||||
|
memory_constitution.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
shutil.copy2(template_constitution, memory_constitution)
|
||||||
|
if tracker:
|
||||||
|
tracker.add("constitution", "Constitution setup")
|
||||||
|
tracker.complete("constitution", "copied from template")
|
||||||
|
else:
|
||||||
|
console.print(f"[cyan]Initialized constitution from template[/cyan]")
|
||||||
|
except Exception as e:
|
||||||
|
if tracker:
|
||||||
|
tracker.add("constitution", "Constitution setup")
|
||||||
|
tracker.error("constitution", str(e))
|
||||||
|
else:
|
||||||
|
console.print(f"[yellow]Warning: Could not initialize constitution: {e}[/yellow]")
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def init(
|
def init(
|
||||||
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here, or use '.' for current directory)"),
|
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here, or use '.' for current directory)"),
|
||||||
@@ -1108,6 +1143,7 @@ def init(
|
|||||||
("zip-list", "Archive contents"),
|
("zip-list", "Archive contents"),
|
||||||
("extracted-summary", "Extraction summary"),
|
("extracted-summary", "Extraction summary"),
|
||||||
("chmod", "Ensure scripts executable"),
|
("chmod", "Ensure scripts executable"),
|
||||||
|
("constitution", "Constitution setup"),
|
||||||
("cleanup", "Cleanup"),
|
("cleanup", "Cleanup"),
|
||||||
("git", "Initialize git repository"),
|
("git", "Initialize git repository"),
|
||||||
("final", "Finalize")
|
("final", "Finalize")
|
||||||
@@ -1128,6 +1164,8 @@ def init(
|
|||||||
|
|
||||||
ensure_executable_scripts(project_path, tracker=tracker)
|
ensure_executable_scripts(project_path, tracker=tracker)
|
||||||
|
|
||||||
|
ensure_constitution_from_template(project_path, tracker=tracker)
|
||||||
|
|
||||||
if not no_git:
|
if not no_git:
|
||||||
tracker.start("git")
|
tracker.start("git")
|
||||||
if is_git_repo(project_path):
|
if is_git_repo(project_path):
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ You **MUST** consider the user input before proceeding (if not empty).
|
|||||||
|
|
||||||
## Outline
|
## Outline
|
||||||
|
|
||||||
You are updating the project constitution at `/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.
|
You are updating the project constitution at `.specify/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.
|
||||||
|
|
||||||
|
**Note**: If `.specify/memory/constitution.md` does not exist yet, it should have been initialized from `.specify/templates/constitution-template.md` during project setup. If it's missing, copy the template first.
|
||||||
|
|
||||||
Follow this execution flow:
|
Follow this execution flow:
|
||||||
|
|
||||||
1. Load the existing constitution template at `/memory/constitution.md`.
|
1. Load the existing constitution at `.specify/memory/constitution.md`.
|
||||||
- Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
|
- Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
|
||||||
**IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.
|
**IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.
|
||||||
|
|
||||||
@@ -41,10 +43,10 @@ Follow this execution flow:
|
|||||||
- Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.
|
- Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.
|
||||||
|
|
||||||
4. Consistency propagation checklist (convert prior checklist into active validations):
|
4. Consistency propagation checklist (convert prior checklist into active validations):
|
||||||
- Read `/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
|
- Read `.specify/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
|
||||||
- Read `/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
|
- Read `.specify/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
|
||||||
- Read `/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
|
- Read `.specify/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
|
||||||
- Read each command file in `/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
|
- Read each command file in `.specify/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
|
||||||
- Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.
|
- Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.
|
||||||
|
|
||||||
5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
|
5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
|
||||||
@@ -61,7 +63,7 @@ Follow this execution flow:
|
|||||||
- Dates ISO format YYYY-MM-DD.
|
- Dates ISO format YYYY-MM-DD.
|
||||||
- Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).
|
- Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).
|
||||||
|
|
||||||
7. Write the completed constitution back to `/memory/constitution.md` (overwrite).
|
7. Write the completed constitution back to `.specify/memory/constitution.md` (overwrite).
|
||||||
|
|
||||||
8. Output a final summary to the user with:
|
8. Output a final summary to the user with:
|
||||||
- New version and bump rationale.
|
- New version and bump rationale.
|
||||||
@@ -79,4 +81,4 @@ If the user supplies partial updates (e.g., only one principle revision), still
|
|||||||
|
|
||||||
If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.
|
If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.
|
||||||
|
|
||||||
Do not create a new template; always operate on the existing `/memory/constitution.md` file.
|
Do not create a new template; always operate on the existing `.specify/memory/constitution.md` file.
|
||||||
|
|||||||
Reference in New Issue
Block a user