一键导入
implement-feature
Implement approved OpenSpec proposal with tiered execution (coordinated / local-parallel / sequential)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Implement approved OpenSpec proposal with tiered execution (coordinated / local-parallel / sequential)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Generate throughput and quality reports from coordinator audit data and episodic memory
Orchestrate the full plan-review-implement-validate-PR lifecycle with multi-vendor review convergence
Comprehensive project health diagnostic — collects signals from CI tools, existing reports, deferred issues, and code markers into a prioritized finding report
Generate changelog entries and suggest semantic version bumps from git history
Ingest raw session transcripts from coding-agent harnesses via vendor-specific adapters, normalize to a common event schema, triage for struggle signals, and write structured findings to episodic memory
Readiness gate for sync-point operations — inspect validation, rework, and active-agent state before merge
| name | implement-feature |
| description | Implement approved OpenSpec proposal with tiered execution (coordinated / local-parallel / sequential) |
| category | Git Workflow |
| tags | ["openspec","implementation","pr","parallel","dag","work-packages"] |
| triggers | ["implement feature","build feature","start implementation","begin implementation","code feature","linear implement feature","parallel implement feature","parallel implement","parallel build feature"] |
Implement an approved OpenSpec proposal. Automatically selects execution tier based on coordinator availability and existing artifacts. Ends when PR is created and awaiting review.
$ARGUMENTS - OpenSpec change-id (required)
openspec/changes/<change-id>//plan-feature first if no proposal existsWhen this skill delegates work packages, treat the provider-neutral dispatch adapter
as the canonical cross-provider path. Claude Code, Codex, Antigravity, Grok, and
Pi are first-class providers when configured; Claude-style Task(...)
or Agent(...) snippets are provider-specific examples, with inline execution
as the fallback.
Use OpenSpec-generated runtime assets first, then CLI fallback:
.claude/commands/opsx/*.md or .claude/skills/openspec-*/SKILL.md.codex/skills/openspec-*/SKILL.mdopenspec CLI commandsRun the coordinator detection script:
python3 "<skill-base-dir>/../coordination-bridge/scripts/check_coordinator.py" --json
Parse JSON output and set capability flags. Then select tier:
If COORDINATOR_AVAILABLE and CAN_DISCOVER and CAN_QUEUE_WORK and CAN_LOCK:
TIER = "coordinated"
Else if work-packages.yaml exists at openspec/changes/<change-id>/:
TIER = "local-parallel"
Else if tasks.md has 3+ independent tasks with non-overlapping file scopes:
TIER = "local-parallel"
Else:
TIER = "sequential"
Emit tier notification:
Tier: <tier> -- <rationale>
If CAN_HANDOFF=true, read recent handoff context.
Per D11 of add-coordinator-task-status-renderer: at the very start of
/implement-feature, query the coordinator for any issues bearing
change:<change-id>. If the list is empty AND the coordinator is reachable,
the seeder was either skipped at Gate 2 or its earlier run failed — invoke it
now before claiming any work:
# Pseudocode — drop in coordination_bridge.try_issue_list to inspect.
if coordinator_reachable and try_issue_list(labels=["change:<change-id>"]) is empty:
python3 "<skill-base-dir>/../coordinator-task-status-renderer/scripts/seed_tasks_from_md.py" <change-id>
This "seeding retry" path makes Gate 2 robust to transient coordinator outages:
empty change-ids are auto-repaired at the first implementation step. The
seeder is idempotent on (change:<id>, task:<key>), so re-running is safe.
Skip this step when the coordinator is genuinely unreachable; the renderer's
stale-marker fallback still works and /implement-feature proceeds.
openspec show <change-id>
cat openspec/changes/<change-id>/tasks.md
Confirm the proposal is approved before proceeding.
AGENT_FLAG=""
if [[ -n "${AGENT_ID:-}" ]]; then
AGENT_FLAG="--agent-id ${AGENT_ID}"
fi
eval "$(python3 "<skill-base-dir>/../worktree/scripts/worktree.py" setup "<change-id>" ${AGENT_FLAG})"
cd "$WORKTREE_PATH"
# Two distinct branches matter here:
#
# WORKTREE_BRANCH — this worktree's branch, which for parallel work-package
# agents is <parent>--<agent-id>. Used for commits inside
# this worktree and for local branch verification.
# FEATURE_BRANCH — the PARENT feature branch that agent branches merge into
# and that gets pushed as the PR head. In the single-agent
# case it equals WORKTREE_BRANCH. In the parallel case it
# is the operator/default branch without the agent suffix.
#
# The parent branch is what plan-feature pushed and what the PR is opened
# against. Resolve it explicitly so the final push/PR target is stable.
eval "$(python3 "<skill-base-dir>/../worktree/scripts/worktree.py" resolve-branch "<change-id>" --parent)"
FEATURE_BRANCH="$BRANCH"
Operator branch override: If OPENSPEC_BRANCH_OVERRIDE was set at plan time, it MUST be set at implement time too — otherwise plan-feature and implement-feature will disagree on the branch and commits will diverge. The safest pattern is for the operator to set the env var for the entire session.
Parallel disambiguation: When AGENT_ID is set (parallel work-package agents), each agent gets <FEATURE_BRANCH>--<agent-id> as its WORKTREE_BRANCH so parallel agents don't clobber each other. The wp-integration package (or merge_worktrees.py) merges those sub-branches back into $FEATURE_BRANCH before the final push.
CURRENT_BRANCH="$(git branch --show-current)"
# In single-agent mode, WORKTREE_BRANCH == FEATURE_BRANCH.
# In parallel mode, WORKTREE_BRANCH is <FEATURE_BRANCH>--<agent-id>.
if [[ "$CURRENT_BRANCH" != "$WORKTREE_BRANCH" ]]; then
echo "ERROR: worktree is on '$CURRENT_BRANCH' but expected '$WORKTREE_BRANCH'" >&2
echo "Hint: if OPENSPEC_BRANCH_OVERRIDE is set, ensure it matches what plan-feature used" >&2
exit 1
fi
These rules govern every line of code written under this skill. They apply to all tiers and to every sub-agent dispatched in Step 3b. When in doubt, re-read this section.
write_allow requires. Do not opportunistically clean up adjacent code, refactor unrelated imports, or add features that weren't asked for. When you spot something genuinely broken outside scope, log it with the Scope discipline template below — do not silently fix it.feat(auth): add login AND fix unrelated typo is two commits pretending to be one.When a sub-agent (or you) notices an issue outside the current work package's scope, do NOT fix it. Log it with this exact template at the bottom of the work-package result and file a follow-up:
NOTICED BUT NOT TOUCHING:
- <file or area>: <what's wrong> — out of scope for this work package, file follow-up.
This template is mandatory for any out-of-scope observation. It surfaces the issue (so it isn't lost) without polluting the current diff.
Before any reviewer/validator dispatch happens later in phase C3, record this worker's
vendor in the change-scoped dispatch-state file. The vendor_diversity policy in
agent-coordinator/agents.yaml (worker_vs_validator) excludes the worker's vendor
from validator selection — see parallel-infrastructure/scripts/review_dispatcher.py
(record_worker_vendor, select_validator_vendor).
# AGENT_TYPE is set by the harness (e.g., "claude_code", "codex", "antigravity").
# Map agent type to vendor short-name; default to the type itself if unmapped.
case "${AGENT_TYPE:-claude_code}" in
claude_code) WORKER_VENDOR="claude" ;;
codex) WORKER_VENDOR="codex" ;;
antigravity) WORKER_VENDOR="antigravity" ;;
grok) WORKER_VENDOR="grok" ;;
pi) WORKER_VENDOR="pi" ;;
*) WORKER_VENDOR="${AGENT_TYPE}" ;;
esac
python3 - <<PY
import sys
from pathlib import Path
sys.path.insert(0, "<skill-base-dir>/../parallel-infrastructure/scripts")
from review_dispatcher import record_worker_vendor
record_worker_vendor("<change-id>", "${WORKER_VENDOR}")
PY
This is idempotent (safe to call multiple times) and a no-op if the dispatcher
script isn't on the path (degrade gracefully). Validator selection in C3 reads
this state and excludes ${WORKER_VENDOR} from candidate validators when the
policy is enforced.
Before implementing, create the traceability skeleton and write failing tests:
openspec/changes/<change-id>/specs/. For each SHALL/MUST clause, create a row in the Requirement Traceability Matrix.contracts/ exists and contains machine-readable artifacts (not just README.md): map the requirement to the contract file it validates (e.g., contracts/openapi/v1.yaml#/paths/~1users, contracts/events/coordinator.schema.json). Use --- if no contract applies to this specific requirement.contracts/ exists but contains only README.md (no applicable interfaces): use --- for all contract refs.contracts/ does not exist (legacy change predating universal artifacts): log a warning that contract-based validation was skipped. Use --- for all contract refs.--- for affected contract refs. Do not block implementation on parse failures.design.md (e.g., D3) that this requirement validates. Use --- if none applies. If design.md exists, also populate the Design Decision Trace section.Use template from openspec/schemas/feature-workflow/templates/change-context.md. Write to openspec/changes/<change-id>/change-context.md.
Implementation strategy depends on the selected tier:
Work through tasks sequentially from tasks.md. Use the runtime-native apply workflow or CLI fallback:
openspec instructions apply --change "<change-id>" --json
openspec status --change "<change-id>"
Before dispatching implementation agents, resolve the archetype model. This enables complexity-based escalation from Sonnet to Opus for large work packages:
import sys
from pathlib import Path
bridge_scripts = Path("<skill-base-dir>").parent / "coordination-bridge" / "scripts"
sys.path.insert(0, str(bridge_scripts))
import coordination_bridge
# For each package, resolve implementer model based on complexity signals
package_metadata = {
"write_allow": <from work-packages.yaml scope.write_allow>,
"dependencies": <from work-packages.yaml depends_on>,
"loc_estimate": <from work-packages.yaml metadata.loc_estimate>,
"complexity": <from work-packages.yaml metadata.complexity or None>,
}
resolved = coordination_bridge.try_resolve_archetype_for_phase(
"IMPLEMENT", package_metadata
)
impl_model = resolved["model"] if resolved else None
runner_model = None
If resolution is unavailable, omit model= so the harness uses its configured
default. Thresholds remain coordinator-configurable without requiring local
coordinator source or configuration files.
When tasks.md contains 3+ independent tasks (no shared files), implement concurrently:
Task(
subagent_type="general-purpose",
model=impl_model, # archetype: implementer (sonnet, or opus if escalated)
description="Implement task N: <brief>",
prompt="You are implementing OpenSpec <change-id>, Task N.
**Your Task**
<TASK_DESCRIPTION>
**File Scope (CRITICAL)**
You MAY modify: <list specific files>
You must NOT modify any other files.
**Context**
- Read openspec/changes/<change-id>/proposal.md
- Read openspec/changes/<change-id>/design.md
Do NOT commit - the orchestrator will handle commits.",
run_in_background=true
)
When to parallelize: 3+ independent tasks with no file overlap. When NOT to: Tasks that share files/state or have logical dependencies.
Per-package context checkpoint: not applicable. This tier has no per-package completion boundary — tasks are not partitioned into work packages, so there is nothing to checkpoint per package. Do not invent a boundary to hang one on; see Per-Package Context Checkpoint below.
Uses work-packages.yaml for structured DAG execution within a single feature worktree.
A. Parse and validate work-packages.yaml:
python3 "<skill-base-dir>/../parallel-infrastructure/scripts/dag_scheduler.py" \
--validate openspec/changes/<change-id>/work-packages.yaml
Compute topological order from packages[].depends_on.
B. Execute root packages sequentially:
For each root package (depends_on == []), implement within the feature worktree.
C. Dispatch independent packages in parallel:
For each package whose dependencies are satisfied, dispatch via Agent tool:
Task(
subagent_type="general-purpose",
model=impl_model, # archetype: implementer (sonnet, or opus if escalated)
description="Implement <package-id>",
prompt="You are implementing work package <package-id> for OpenSpec <change-id>.
**File Scope (CRITICAL)**
write_allow: <from work-packages.yaml>
read_allow: <from work-packages.yaml>
deny: <from work-packages.yaml>
**Context**
<context slice from Context Slicing table below>
**Verification**
After implementation, run:
<verification steps from work-packages.yaml>
**Scope Discipline**
Follow Implementation Rules 0–5 (see `skills/implement-feature/SKILL.md`).
If you notice issues outside this package's `write_allow`, do NOT fix them.
Append to your result using the literal `NOTICED BUT NOT TOUCHING:` template
documented in the parent skill, so they're filed as follow-ups instead of
silently widening this PR.
Do NOT commit - the orchestrator will handle commits.",
run_in_background=true
)
D. Collect results and verify scope:
python3 "<skill-base-dir>/../parallel-infrastructure/scripts/scope_checker.py" \
--packages openspec/changes/<change-id>/work-packages.yaml \
--diff <git diff output>
D.5 Run the per-package context checkpoint:
For each package whose results were just collected, evaluate it and run a checkpoint when
it invalidated project context. Do this before E, so the change-context update reflects
the checkpoint. See Per-Package Context Checkpoint below for the command and the
unmigrated reporting rule.
E. Update change-context.md:
git diff --name-only main..HEADFull multi-agent DAG execution with coordinator integration. Each work package runs in its own worktree with explicit lock claims.
A1. Parse and validate work-packages.yaml against schema
A2. Validate contracts exist
A3. Compute DAG order (topological sort, cycle detection)
A3.5. Generate Change Context with relevant rows per package
A4. Create or reuse feature branch
A5. Implement root packages (sequentially, each in own worktree)
A6. Setup worktrees for parallel packages (branch from feature branch)
A7. Dispatch parallel agents with WORKTREE_PATH, BRANCH, CHANGE_ID, PACKAGE_ID
A8. Begin monitoring loop (discover_agents, get_task polling)
Each worker agent follows steps B1-B11: session registration, pause-lock check, deadlock-safe lock acquisition (lexicographic order), code generation within scope, deterministic scope check via git diff, verification steps, structured result publication.
Workers MUST call heartbeat every 30 minutes:
python3 "<skill-base-dir>/../worktree/scripts/worktree.py" heartbeat "${CHANGE_ID}" --agent-id "${PACKAGE_ID}"
C1. Result validation against work-queue-result.schema.json
C1.5. Per-package context checkpoint (see "Per-Package Context Checkpoint" below).
Runs here, before C3, so reviewers read the report.
C2. Escalation processing
C3. Per-package multi-vendor review (via /parallel-review-implementation)
- Self-review + vendor dispatch via parallel-infrastructure/scripts/review_dispatcher.py
- Consensus synthesis via parallel-infrastructure/scripts/consensus_synthesizer.py
C4. Integration gate (consensus-aware)
C5. Integration merge (wp-integration package, merge_worktrees.py)
C5.5. Finalize Change Context (Files Changed, Design Decision Trace, Review Findings Summary)
C6. Execution summary generation
Teardown (after PR creation or on failure):
python3 "<skill-base-dir>/../worktree/scripts/worktree.py" unpin "<change-id>"
for pkg in <package-ids> integrator; do
python3 "<skill-base-dir>/../worktree/scripts/worktree.py" teardown "<change-id>" --agent-id "$pkg"
done
python3 "<skill-base-dir>/../worktree/scripts/worktree.py" gc
When a work package completes, evaluate it for context impact and run a branch-local checkpoint if its surfaces indicate project context was invalidated. The checkpoint is read-only and advisory: it never writes the shared refresh ledger, and detected drift is data in its report, not a build failure.
Hook points, one per tier:
| Tier | Where | Why there |
|---|---|---|
| Local Parallel | Step 3b D.5 — after D collects results and runs scope_checker.py, before E | The package's changed-file list only exists once results are collected |
| Coordinated | Phase C C1.5 — after C1 result validation, before C3 review | The review reads the checkpoint report |
| Sequential | No hook | This tier has no per-package boundary; do not invent one |
python3 "<skill-base-dir>/../project-context-refresh/scripts/cli.py" checkpoint \
--change-id "<change-id>" --package-id "<package-id>" \
--changed-file <path> [--changed-file <path> ...]
Supply the package's changed files explicitly. The trigger is deliberately git-free, so it
decides correctly on an uncommitted worktree between package completion and commit — never
substitute a git range for --changed-file. The report lands at
openspec/changes/<change-id>/context-checkpoints/<package-id>.json and is tracked, so a
reviewer sees it in the PR diff.
Reporting rule — unmigrated is never "no context impact" (REQUIRED).
| Package state | Status | Record in the implementation summary as |
|---|---|---|
| Declares surfaces its changed files invalidate | declared / rationalized | checkpoint ran, with the report path |
Declares an explicitly empty context_impact.surfaces list | declared | the package asserted no impact |
Declares no context_impact block at all | unmigrated | unmigrated — that literal word |
The last two both skip the checkpoint, and reporting them the same way is the failure this rule exists to prevent: an empty list is an assertion that nothing is affected, a missing block is absence of evidence. Collapsing them lets a package nobody checked appear verified.
undeclared and spurious_rationale are the context-impact gate's failing statuses — the
package's declaration is wrong, not merely absent. The checkpoint refuses to run and exits
non-zero; fix the declaration before treating the package as complete.
Use TodoWrite for in-session state tracking. Additionally, tasks.md is the canonical post-session record of what's done — keep it in sync commit-by-commit, not batched at the end.
Per-task checkbox discipline (REQUIRED):
For each task you complete, flip its - [ ] to - [x] in openspec/changes/<change-id>/tasks.md in the same commit that implements the task. Do NOT defer checkbox updates into a trailing "mark tasks complete" commit.
tasks.md, then commit togetherfeat(<scope>): <task summary> (<change-id> task N.N)Why this discipline matters: When PRs auto-merge via review-queue automation, a trailing "mark tasks complete" commit is often skipped, lost during rebase, or bundled into an unrelated squash. Coupling the checkbox flip to the implementation commit means the bookkeeping travels with the code, and archive-time drift (tasks.md showing 0/N while implementation is 100% landed) becomes structurally impossible. Past incident: specialized-workflow-agents (archived 2026-04-22) shipped all 29 tasks of code to main with 0/29 checkboxes flipped, requiring retroactive reconciliation via /openspec-verify-change before archive.
This is a last-line-of-defense check after per-task discipline. If Step 4 was followed, this should pass trivially.
grep -E "^\s*- \[ \]" openspec/changes/<change-id>/tasks.md
# Should return nothing (all boxes checked)
If it returns any lines, STOP and reconcile before proceeding:
chore(openspec): reconcile task N.N checkbox) — do NOT amend implementation commits already on mainopenspec/changes/<change-id>/deferred-tasks.md with a short rationale, and remove it from tasks.mdDo NOT run quality checks (Step 6) or /validate-feature (Step 6.5) while tasks.md has unchecked boxes — the spec-compliance phase will fail the task-drift gate.
Run all environment-safe checks. These must pass in both cloud and local environments:
Task(subagent_type="Bash", model=runner_model, prompt="Run pytest and report pass/fail", run_in_background=true)
Task(subagent_type="Bash", model=runner_model, prompt="Run mypy src/ and report type errors", run_in_background=true)
Task(subagent_type="Bash", model=runner_model, prompt="Run ruff check . and report linting issues", run_in_background=true)
Task(subagent_type="Bash", model=runner_model, prompt="Run openspec validate <change-id> --strict", run_in_background=true)
Task(subagent_type="Bash", model=runner_model, prompt="Run validate_flows.py --diff main...HEAD", run_in_background=true)
Fix all failures before proceeding.
Run live service smoke tests if a test environment is available:
python3 "<skill-base-dir>/../validate-feature/scripts/phase_deploy.py" --env docker --timeout 120
python3 "<skill-base-dir>/../validate-feature/scripts/phase_smoke.py"
python3 "<skill-base-dir>/../validate-feature/scripts/stack_launcher.py" teardown
If Docker/Neon is unavailable, log a WARNING and continue with smoke status "skipped" in validation-report.md. This is a soft gate — implementation proceeds regardless.
Skip if TIER is "sequential".
Delegate to /validate-feature for environment-safe validation phases:
/validate-feature <change-id> --phase spec,evidence
This runs the canonical validation skill targeting:
spec phase): Audits change-context.md Requirement Traceability Matrix — verifies no --- entries in Files Changed, updates Coverage Summary counts, and checks each requirement against the implementation.evidence phase): Validates work-package results against work-queue-result.schema.json, checks revision consistency, scope compliance, and cross-package consistency. Populates the Evidence column in change-context.md.These phases are environment-safe and run in both cloud and local. Docker-dependent phases (deploy, smoke, security, E2E) are deferred to the merge-time validation gate in /cleanup-feature or /merge-pull-requests.
Document patterns, gotchas, and design changes in CLAUDE.md and AGENTS.md.
Construct a PhaseRecord for the Implementation phase and call write_both(). The structured fields (Decisions, Alternatives, Trade-offs, Completed Work, In Progress, Next Steps, Relevant Files) flow into both the session-log markdown and the coordinator handoff_documents — wp-integration and any downstream phase can hydrate the next phase's context from read_handoff() rather than re-parsing markdown.
Capture from this implementation:
validate-feature should pick up first.Persist via PhaseRecord.write_both():
This step MUST run BEFORE the git add . in Step 8 so the session-log entry is included in the implementation commit.
python3 - <<'EOF'
import sys
from pathlib import Path
sys.path.insert(0, str(Path("<skill-base-dir>").parent / "session-log" / "scripts"))
from phase_record import PhaseRecord, Decision, Alternative, TradeOff, FileRef
record = PhaseRecord(
change_id="<change-id>",
phase_name="Implementation",
agent_type="<agent-type>",
summary="<2-3 sentences: what was implemented, deviations from plan>",
decisions=[
Decision(title="<title>", rationale="<rationale>", capability="<kebab-case-capability>"),
],
alternatives=[Alternative(alternative="<approach>", reason="<rejection reason>")],
trade_offs=[TradeOff(accepted="<X>", over="<Y>", reason="<reason>")],
open_questions=["<question for validation>"],
completed_work=["<deliverable>"],
next_steps=["<what validation should check first>"],
relevant_files=[FileRef(path="<path>", description="<why it matters>")],
)
result = record.write_both()
print(f"markdown_path={result.markdown_path}")
print(f"sanitized={result.sanitized}")
print(f"handoff_id={result.handoff_id or '(local fallback)'}")
print(f"handoff_local_path={result.handoff_local_path}")
for w in result.warnings:
print(f"WARN: {w}", file=sys.stderr)
EOF
write_both() runs three best-effort steps internally: append rendered markdown → sanitize in-place → coordinator handoff (or local fallback at openspec/changes/<change-id>/handoffs/implementation-<N>.json). Each step logs warnings on failure but does not raise. The session-log.md is included in git add . in Step 8.
Commit quality matters: OpenSpec PRs use rebase-merge by default, so every commit appears individually on main. Structure commits as logical, self-contained units:
feat(scope):, fix(scope):, test(scope):, docs(scope):git add .
git commit -m "$(cat <<'EOF'
feat(<scope>): <description>
Implements OpenSpec: <change-id>
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
# Push to the resolved feature branch (honors OPENSPEC_BRANCH_OVERRIDE)
git push -u origin "$FEATURE_BRANCH"
gh pr create --title "feat(<scope>): <title>" --body "..."
If CAN_HANDOFF=true, write a completion handoff.
STOP HERE -- Wait for PR approval before proceeding to cleanup.
When dispatching work packages, each agent receives only the context it needs:
| Package Type | Context Slice |
|---|---|
wp-contracts | proposal.md + spec deltas + contract templates |
| Backend packages | design.md (backend section) + contracts/openapi/ + package scope |
| Frontend packages | design.md (frontend section) + contracts/generated/types.ts + package scope |
wp-integration | Full work-packages.yaml + all contract artifacts |
$FEATURE_BRANCH (default openspec/<change-id>, or whatever OPENSPEC_BRANCH_OVERRIDE resolved to)After PR is approved:
/cleanup-feature <change-id>
| Rationalization | Why it's wrong |
|---|---|
| "While I'm in this file I'll fix the unrelated bug too" | Violates Rule 0.5 (Scope Discipline). The fix may pass review on its own merit but it bloats the diff, hides the real change, and couples your PR's fate to an unrelated risk. Use the NOTICED BUT NOT TOUCHING: template instead. |
| "This commit is broken but the next one fixes it — squash will hide it" | Violates Rule 2. Rebase-merge means every commit lands on main individually; a broken middle commit breaks git bisect for the next person to chase a regression. |
| "Adding the new flag and flipping the default in one go is cleaner" | Violates Rule 4 (Safe Defaults). Default-flip changes behavior for every existing caller silently. Land the flag OFF, ship it, then change the default in a separate, revertable commit. |
| "I'll skip the per-task checkbox flip and batch them at the end" | The trailing "mark tasks complete" commit is routinely lost in rebase/squash. Past incident: 0/29 checkboxes flipped while 100% of code was on main. Couple the bookkeeping to the implementation commit. |
write_allow without a recorded NOTICED BUT NOT TOUCHING: justification (Rule 0.5 violation).tasks.md shows unchecked boxes after Step 5 (per-task checkbox discipline violation).FEATURE_X_ENABLED, default OFF").git log --oneline main..HEAD followed by spot-checking ≥1 mid-branch commit.write_allow from work-packages.yaml, OR every such touch is documented under NOTICED BUT NOT TOUCHING:.grep -E "^\s*- \[ \]" openspec/changes/<change-id>/tasks.md returns nothing (per-task checkbox discipline applied).