fix: guard constitution command against feature execution (#3646)

* fix: guard constitution command scope

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: be3f0d7d-2774-4ba2-b741-efbb4870148a

* fix: render deferred command per integration

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: be3f0d7d-2774-4ba2-b741-efbb4870148a

* fix: defer all lean non-governance intents

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: be3f0d7d-2774-4ba2-b741-efbb4870148a
This commit is contained in:
Ben Buttigieg
2026-07-22 18:27:37 +01:00
committed by GitHub
parent fb7dc0c4d6
commit 8c816fac40
3 changed files with 66 additions and 0 deletions

View File

@@ -8,6 +8,24 @@ description: Create or update the project constitution.
$ARGUMENTS
```
## Scope Guard
This command's own work is limited to creating or updating the project constitution and
propagating constitution-driven changes to dependent Spec Kit artifacts.
- Classify every part of the user input as constitution content or a separate non-governance
intent. Feature implementation, code generation, refactoring, build, and deployment requests
are examples of non-governance intents.
- You **MUST NOT** execute any non-governance intent. Defer each one to `Next Actions`.
- You **MUST NOT** create, modify, or delete application source files or other artifacts
unrelated to the constitution workflow.
- If an instruction could be either constitution content or a non-governance intent, ask for
clarification before making changes.
- After updating the constitution, list each deferred intent in a `Next Actions` section with an
appropriate follow-up Spec Kit command, such as `__SPECKIT_COMMAND_SPECIFY__`, but do not
invoke it.
- Omit `Next Actions` when there are no non-governance intents.
## Outline
1. Create or update the project constitution and store it in `.specify/memory/constitution.md`.

View File

@@ -14,6 +14,25 @@ $ARGUMENTS
You **MUST** consider the user input before proceeding (if not empty).
## Scope Guard
This command's own work is limited to updating the project constitution and propagating
constitution-driven changes to the dependent artifacts identified in this command.
- Classify every part of the user input as either constitution content or a separate,
non-governance intent.
- If the input includes feature implementation, code generation, refactoring, building, or
deployment requests, you **MUST NOT** execute them. Extract them as deferred intents instead.
- You **MUST NOT** create, modify, or delete application source files, feature routes,
components, tests, deployment files, or other artifacts unrelated to the constitution
workflow and its required propagation.
- If it is unclear whether an instruction is constitution content, ask for clarification before
making changes.
- After completing the constitution update, include a `Next Actions` section for each deferred
intent. List the original intent and suggest the appropriate follow-up Spec Kit command, such
as `__SPECKIT_COMMAND_SPECIFY__`, without invoking it.
- If there are no non-governance intents, omit the `Next Actions` section.
## Pre-Execution Checks
**Check for extension hooks (before constitution update)**:
@@ -104,6 +123,7 @@ Follow this execution flow:
- New version and bump rationale.
- Any files flagged for manual follow-up.
- Suggested commit message (e.g., `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).
- A `Next Actions` section for any deferred non-governance intents.
Formatting & Style Requirements:

View File

@@ -5381,6 +5381,9 @@ class TestPresetEnableDisable:
LEAN_PRESET_DIR = Path(__file__).parent.parent / "presets" / "lean"
CORE_CONSTITUTION_COMMAND = (
Path(__file__).parent.parent / "templates" / "commands" / "constitution.md"
)
LEAN_COMMAND_NAMES = [
"speckit.specify",
@@ -5391,6 +5394,31 @@ LEAN_COMMAND_NAMES = [
]
@pytest.mark.parametrize(
"command_path",
[
CORE_CONSTITUTION_COMMAND,
LEAN_PRESET_DIR / "commands" / "speckit.constitution.md",
],
ids=["core", "lean"],
)
def test_constitution_commands_guard_against_non_governance_work(command_path):
"""Constitution commands defer non-governance work instead of executing it."""
content = command_path.read_text()
lower_content = content.lower()
normalized_content = " ".join(lower_content.split())
assert "## Scope Guard" in content
assert "**MUST NOT**" in content
assert "Classify every part" in content
assert "application source files" in content
assert "non-governance intent" in content
assert "`Next Actions`" in content
assert "__SPECKIT_COMMAND_SPECIFY__" in content
assert "omit" in lower_content
assert "do not invoke it" in normalized_content or "without invoking it" in normalized_content
class TestLeanPreset:
"""Tests for the lean preset that ships with the repo."""