CLAUDE.md · diff
git:20260920.f29a152 to git:20260922.9ef340f
1061 added, 0 removed. Audit B to A.
# CLAUDE.md
Read [AGENTS.md](AGENTS.md).
+ <!-- plugin: agent-agentic-os / adversarial-reasoning-before-agreement-rule -->
+ ---
+ description: >
+ Prevent sycophantic, agreeable, or premature agent responses by requiring adversarial reasoning,
+ assumption checks, counterarguments, and explicit risk evaluation before recommendations are accepted.
+ globs:
+ - "*.md"
+ - "docs/**/*.md"
+ - "plugins/**/*.md"
+ - "plugins/**/*.py"
+ - "plugins/**/*.ts"
+ - "plugins/**/*.tsx"
+ - ".agents/**/*.md"
+ - ".agent/rules/**/*.md"
+ ---
+
+ # Rule: Adversarial Reasoning Before Agreement
+
+ ## 1. Why This Rule Exists
+
+ AI agents have a known sycophancy bias: they tend to validate the user's framing, agree too quickly, and jump into execution without stress-testing assumptions. This leads to premature migrations, hidden coupling, and costly rework.
+
+ **A useful agent does not merely execute a proposal—it stress-tests the plan first to make agreement earned.**
+
+ ---
+
+ ## 2. The Iron Law
+
+ **NO SIGNIFICANT ARCHITECTURE DECISION, SCHEMA DESIGN, CODE REFACTOR, DELETION PLAN, OR MIGRATION PROPOSAL MAY BE ACCEPTED WITHOUT AN ADVERSARIAL PASS FIRST.**
+
+ This applies to:
+ - Architecture, system design, and dependency changes
+ - Database/schema changes and data persistence refactors
+ - Plugin, skill, agent instruction, and workflow modifications
+ - Security boundaries, governance, and permission updates
+ - Cleanup, file relocation, and deletion plans
+
+ It does not apply to:
+ - Simple factual lookups or documentation clarifications
+ - Minor typos, formatting, or localized bug fixes with obvious remedies
+ - Mechanical tasks explicitly constrained by the user
+
+ ---
+
+ ## 3. Core Anti-Sycophancy Principles
+
+ 1. **Agreement Must Be Earned**: Never offer uncritical validation ("Looks great!", "You're totally right!"). If you agree, state *why* while naming the remaining risks or failure modes.
+ 2. **Challenge the Premise**: When presented with a problem framing or proposed solution, evaluate whether the root problem is being solved, or merely a symptom.
+ 3. **Identify Critical Assumptions**: Explicitly call out assumptions that, if invalid, would change the recommendation. Inspect context, code, and tests to verify assumptions before asking the user.
+ 4. **No Cleanup Without Evidence**: Prohibit destructive actions, deletions, or deprecations based on perceived "absorption" or redundancy without verified inventories and user authorization.
+ 5. **Present Viable Alternatives**: For major technical recommendations, articulate at least one credible alternative and explain the explicit tradeoffs of the chosen path.
+
+ ---
+
+ ## 4. Evaluation Checklist
+
+ Before confirming significant design changes or plans, verify:
+ - **Assumptions**: What must hold true for this solution to succeed?
+ - **Failure Modes**: How could this approach fail in production or under edge cases?
+ - **Missing Elements**: Are tests, migration paths, rollback strategies, or consumer dependencies unaccounted for?
+ - **Tradeoffs**: What is made more complex or constrained by choosing this design?
+
+
+ <!-- plugin: agent-agentic-os / config-driven-constants-over-hardcoding -->
+ ---
+ description: >
+ Derive expected values, contracts, and magic strings from a live single source of
+ truth (a registry, a config file, a production constant) rather than hardcoding
+ literal copies of them into tests and scripts. Prevents the exact fragility this
+ rule was written to name: adding one new required question broke 46 tests because
+ each had its own hardcoded, literal answer sequence with no shared source.
+ globs: ["plugins/**/*.py", "plugins/**/*.yaml", "plugins/**/*.yml"]
+ ---
+
+ # Rule: Config-Driven / Data-Driven Over Hardcoding
+
+ ## Why This Rule Exists
+
+ On 2026-09-14, adding one new mandatory question (`guidance_compliance_confirmation`)
+ to every non-force-close transition broke 46 pre-existing tests. Every one of them
+ had independently hardcoded its own literal expected answer sequence
+ (`iter(["1", "y"])`, `lambda p: "1"`) instead of deriving the expected question count
+ and content from `TransitionRegistry` (which already parses the same
+ `transition_templates.yaml` the production code reads). One semantically small change
+ became 46 separate, mechanical, error-prone edits — the definition of brittle
+ hardcoding.
+
+ ## The Rule
+
+ 1. **If a value is already declared somewhere authoritative — a YAML registry, a
+ production constant, a schema version — read it from there. Never retype it as a
+ second, independent literal.** Two independently-maintained copies of the same
+ fact will drift; only one of them can be wrong when they do, and finding out which
+ costs real debugging time.
+ 2. **Magic strings that mean something specific to the system (an accepted answer
+ value, a sentinel, a status code) belong in one named constant the rest of the
+ codebase imports** — not retyped as a literal at every call site. See
+ `coordinator.py`'s `GUIDANCE_COMPLIANCE_CONFIRM_ANSWER` for the pattern: a single
+ `"YES"` definition that every caller (production code, tests, future callers)
+ references instead of retyping.
+ 3. **Test fixtures that drive a data-shaped contract (a question sequence, a required
+ field list, an edge's `human_questions`) should build their expected input from the
+ same registry/loader the production code uses**, not a parallel hardcoded list.
+ See `plugins/agent-agentic-os/tests/interview_helpers.py`'s
+ `sequential_answers_for_edge()` — it asks `TransitionRegistry.load_default()`
+ what an edge actually requires and derives the answer sequence from that, so a
+ future universal question addition (or removal) only requires updating the
+ registry-reading helper, not every individual test.
+ 4. **A test asserting equality against a version number, a count, or a schema value
+ that's already independently derivable from a live query should assert the query
+ result matches the imported constant — never ALSO hardcode a second, literal
+ expected value for that same constant.** A pattern like
+ `assert query_result == CURRENT_SCHEMA_VERSION` is correct and durable;
+ `assert CURRENT_SCHEMA_VERSION == 13` immediately below it is redundant, tests
+ nothing the first line doesn't already cover, and breaks on every legitimate
+ version bump for zero safety benefit. Delete assertions like the second one; don't
+ just update the number.
+ 5. **When you must write a magic value into a config/rules file that mirrors
+ something computed elsewhere, put a comment naming the authoritative source it
+ must stay consistent with**, so a future reader (human or agent) knows where to go
+ to verify/update it, rather than discovering the relationship by breakage.
+
+ ## Where Constants Live: One Shared `control_plane/constants.py`
+
+ **Revised 2026-09-14.** An earlier version of this rule recommended colocating each
+ constant group with the production module that "owned" the concept (state names in
+ `state_machine.py`, decision types in `adapters.py`, etc.). Review found that split
+ ownership still left every consumer guessing which file to import from, and produced
+ real duplication anyway (e.g. `adapters.py` independently re-defining
+ `GUIDANCE_COMPLIANCE_CONFIRM_ANSWER` and `STATE_*` instead of importing them). This is
+ standard practice, not a judgment call: **every domain constant used by more than one
+ file — production or test — lives in exactly one shared module,
+ `plugins/agent-agentic-os/scripts/control_plane/constants.py`.**
+
+ **Before writing any state, decision type, actor, status, task type, or other
+ domain-meaningful string literal: check `constants.py` first.** If the constant you
+ need isn't there yet, add it there (grouped with a `# --- <table/concept> ---` header
+ comment matching the existing sections), then import it — never define it locally,
+ even "just for this one file," and never assert against both the literal and the
+ imported constant in the same test (assert only against the constant).
+
+ Modules that build a *derived structure* from these raw names still own that
+ derivation, not the names themselves:
+ - `control_plane/state_machine.py` imports `STATE_*` from `constants.py` and builds
+ `CANONICAL_STATES`/`ALLOWED_TRANSITIONS` (the adjacency DAG) from them — the DAG
+ shape is domain logic; the state names it's built from are not.
+ - `control_plane/adapters.py` imports the SQL-CHECK-constrained value groups
+ (`DECISION_TYPES`, `COST_TIERS`, `TASK_TYPES`, `WORKTREE_STATES`,
+ `CRITIC_VERDICTS`, `DELEGATION_STATUSES`, `RETROSPECTIVE_*`, `FOLLOW_UP_*`, etc.)
+ and renders them into `SCHEMA_SQL`'s `CHECK (... IN (...))` clauses via
+ `constants.sql_in_list()`.
+
+ **Exception — `SCHEMA_MIGRATIONS` in `adapters.py` is an immutable historical
+ record.** It captures DDL literally as it was executed against real databases over
+ time and must NEVER be rewritten to reference `constants.py`, even where a value
+ overlaps with a shared constant. Only the fresh-create `SCHEMA_SQL` and all Python
+ logic after `SCHEMA_MIGRATIONS` derive from the shared constants.
+
+ ## SQL Parameterization: `?` at Runtime, f-strings Only at DDL/Trigger Load Time
+
+ A literal string interpolated into a *runtime* query (inside a method, executed with
+ caller-supplied or looped values) must be passed as a bound `?` parameter, never
+ spliced into the SQL text via an f-string — even when the interpolated value is a
+ trusted internal constant, not user input. This was found as a live, if low-risk, bug
+ during this rule's 2026-09-14 revision: three `adapters.py` methods embedded
+ `'{DECISION_TYPE_APPROVAL}'` inside a **plain** (non-f) triple-quoted string, so
+ SQLite was literally comparing against the 25-character text `{DECISION_TYPE_APPROVAL}`
+ instead of `APPROVAL` — parameterizing forces this class of mistake to fail loudly
+ (wrong bind-parameter count) instead of silently matching nothing.
+
+ - **Runtime query, e.g. inside a method body:** `conn.execute("... WHERE actor = ?", (ACTOR_HUMAN,))` — never `f"... WHERE actor = '{ACTOR_HUMAN}'"`.
+ - **Module-load-time DDL (`SCHEMA_SQL`) or a `CREATE TRIGGER` body:** an f-string
+ interpolating constants (`f"... CHECK (state IN ({sql_in_list(CANONICAL_STATES)}))"`)
+ is correct and is the ONLY place this rule permits it — SQLite triggers cannot
+ accept bind parameters in their body at all, so there is no `?`-based alternative
+ for trigger DDL; `SCHEMA_SQL` itself is likewise built once at import time, not
+ per-call, so injection risk does not apply the way it does to a runtime query.
+
+ ## Repo-Relative Path Resolution: No Fixed `.parent` Chains
+
+ Never resolve a repository-root-relative path via a fixed-depth chain like
+ `Path(__file__).resolve().parent.parent.parent.parent.parent` — it breaks silently
+ (resolves to the wrong directory, no error) the moment the file moves one level.
+ Resolve via `git rev-parse --show-toplevel` (see `adapters.py`'s
+ `_resolve_repo_root()`) or by anchoring on a known marker directory/file (see
+ `adapters.py`'s `_discover_shared_db_path()`, which walks up looking for `.agents/`
+ before falling back to `git rev-parse --git-common-dir`), with a fixed-depth walk only
+ as a last-resort fallback if git is unavailable — never as the primary strategy.
+
+ ## Where This Applies
+
+ - Test fixtures that drive `TransitionCoordinator.coordinate_transition()` or any
+ other registry-shaped contract.
+ - Any hardcoded literal that duplicates a fact already expressed in
+ `transition_templates.yaml`, a schema version constant, `constants.py`, or another
+ single authoritative production source.
+ - Any new state, decision type, actor, status, task type, gate name, or other
+ domain-meaningful string used in more than one place — define once in
+ `control_plane/constants.py`, import everywhere else.
+
+ ## Non-Negotiables
+
+ - Never hardcode an answer sequence for a control-plane edge without first checking
+ whether `TransitionRegistry`/`interview_helpers.py`'s data-driven helpers already
+ express the same contract.
+ - Never add a second, literal-hardcoded assertion of a value that's already
+ dynamically verified against its authoritative source in the same test.
+ - Never introduce a new "magic string" answer/sentinel value without first checking
+ `control_plane/constants.py`, and adding it there if it's not already present.
+ - Never interpolate a Python constant directly into a runtime SQL query string; pass
+ it as a `?` bind parameter. f-string interpolation is reserved for `SCHEMA_SQL` and
+ trigger DDL bodies at module-load time only.
+ - Never resolve the repository root via a fixed `.parent.parent...` chain; use
+ `_resolve_repo_root()` (git-based) or an equivalent marker-anchored resolver.
+ - Never rewrite `SCHEMA_MIGRATIONS` to reference `constants.py` — it is an immutable
+ historical record and keeps its own literal strings forever.
+
+
+ <!-- plugin: agent-agentic-os / destructive-action-guard -->
+ ---
+ name: destructive-action-guard
+ description: Pre-verification protocol required before any file or skill deletion, bulk cleanup, or stand-in conversion. Prevents data loss from blind cleanup passes and prohibits autonomous skill deletions based on absorption or redundancy rationalizations.
+ metadata:
+ type: feedback
+ ---
+
+ # Destructive Action & Skill Deletion Guard
+
+ Before deleting files, removing skill directories, bulk-removing stand-ins, or resolving broken references, run the full verification protocol below. **No exceptions.**
+
+ ---
+
+ ## Part 1: The Iron Law of Skill Deletions (No Absorption Deletions)
+
+ ### The Failure Mode
+ An agent reviews two skills, concludes that skill A's "functionality is covered by" or "has been absorbed into" skill B, then **deletes skill A's directory**. This is always wrong without explicit user instruction naming the exact skill path.
+
+ ### The Iron Law
+ **Never delete a skill directory, its SKILL.md, or its evals because you believe the skill is redundant, absorbed, consolidated, or superseded.**
+
+ This is a hard gate. No amount of reasoning makes autonomous deletion acceptable.
+
+ ### Why "Absorption" Is Always a Rationalization
+ Even when two skills appear to overlap in body content, they are never interchangeable because each skill has three components that are always unique:
+ 1. **Routing identity** — the `trigger:` field and `description:` in frontmatter. Two skills that do similar things still have different routing signatures. Deleting one breaks all prompts that relied on its specific triggers.
+ 2. **Eval contract** — `evals/evals.json` contains `should_trigger` test cases specific to this skill's domain boundary. These cases define where the skill starts and its neighbors end. No other skill has the same eval contract.
+ 3. **Methodology** — the skill body may encode a distinct protocol, phase sequence, or heuristic that the "absorbing" skill does not replicate verbatim, even if the overall goal is similar.
+
+ ### Skill Deletion Permission Rules
+ - Adding content or evals to a skill: **Permitted**
+ - Renaming or moving a skill directory: **Requires explicit confirmation**
+ - Deleting a skill directory: **HARD GATED — always requires explicit user instruction naming the exact skill path (e.g., "delete `plugins/agent-agentic-os/skills/my-skill`")**
+ - Deleting a skill because it "looks absorbed" or the user said "clean up redundant skills": **NEVER. General requests like "clean up", "deduplicate", "merge", or "simplify" describe intent, not deletion authorization.**
+
+ ### Zombie Directory Protocol
+ A zombie is a skill directory that exists on disk but has no `SKILL.md`.
+ **Do not delete zombie directories autonomously.**
+ 1. Check `git log -- plugins/<plugin>/skills/<name>/` to see the last known state.
+ 2. Report to user: *"Found zombie directory at `<path>` — no SKILL.md. Last commit: `<sha>`. Restore or delete?"*
+ 3. Wait for explicit instruction.
+
+ ---
+
+ ## Part 2: General File Deletion & Stand-in Verification Protocol
+
+ ### Scope
+ This verification applies before:
+ - Deleting any file anywhere in the repository
+ - Removing stand-in / text-file pointer files
+ - Bulk cleanup operations (`rm`, `git rm`, script-driven deletion)
+ - Converting stand-ins to symlinks (targets may have moved)
+ - "Dead reference" cleanup from consolidation or migration
+
+ ### Verification Protocol
+
+ #### Step 1 — Extract the target from each file
+ For a single-line text stand-in at path `P` containing relative path `T`:
+ ```bash
+ cat P # confirm single line, relative path
+ ```
+
+ #### Step 2 — Repo-wide target search
+ ```bash
+ git ls-files | grep -i "<filename>"
+ ```
+ - **Target found in repo** → classify as **MISLOCATED_REFERENCE** — do not delete; propose correct path
+ - **Target not found** → proceed to Step 3
+
+ #### Step 3 — Git history check
+ ```bash
+ git log --all --oneline --full-history -- "**/filename"
+ ```
+ - **File existed and was recently deleted** → classify as **POSSIBLE_ACCIDENTAL_DELETION** — add to Map Debt; do not delete
+ - **File only appears in consolidation/migration commits with no subsequent history** → likely safe, classify as **DEAD_CROSS_REPO_REFERENCE**
+
+ #### Step 4 — SKILL_ALIAS check (commands/ and agents/)
+ If content matches `../skills/<name>/SKILL.md` pattern AND the target SKILL.md exists:
+ - Classify as **SKILL_ALIAS** → convert to symlink via `symlink_manager create`, do not delete
+
+ #### Step 5 — Produce audit table before any change
+ Output this table and wait for explicit confirmation:
+
+ | File | Target | Exists in Repo | Classification | Action |
+ |------|--------|----------------|----------------|--------|
+
+ #### Step 6 — Kill switch
+ **Stop and output the audit table only (no changes)** if any of the following:
+ - 5+ files classified `POSSIBLE_ACCIDENTAL_DELETION`
+ - Any ambiguity in target resolution
+ - Content is multi-line (not a stand-in)
+ - Target path resolves outside the repo
+
+ ### Classification → Action Map
+
+ | Classification | Action |
+ |---|---|
+ | `DEAD_CROSS_REPO_REFERENCE` | Delete |
+ | `MISLOCATED_REFERENCE` | Propose corrected path; do not modify |
+ | `POSSIBLE_ACCIDENTAL_DELETION` | Escalate to Map Debt; do not modify |
+ | `SKILL_ALIAS` | Convert to symlink via `symlink_manager create` |
+
+ ---
+
+ ## Why This Rule Exists
+
+ The consolidation of repository plugins left pre-consolidation stand-ins with cross-repo paths that never existed post-merge. Blind deletion passes treat MISLOCATED and DEAD references identically — but only DEAD ones are safe to remove. The distinction requires git verification. Similarly, agents routinely rationalize deleting functional skills under the guise of "cleanup" or "absorption". This rule unifies both protections under one strict gate.
+
+
+ <!-- plugin: agent-agentic-os / github-issue-logging-policy -->
+ ---
+ trigger: always_on
+ description: Policy and decision matrix governing when and how agent friction events, map debt, and bugs are logged as GitHub issues.
+ globs: ["**/*"]
+ ---
+
+ # GitHub Issue Logging Policy (`github-issue-logging-policy`)
+
+ ## 1. Purpose & Integration with `self-evolution-policy.md`
+
+ This policy governs when and how friction events, execution workarounds, tool failures, and map debt identified during agent runs are logged into GitHub Issues.
+
+ It directly extends `self-evolution-policy.md` by defining the decision boundary between in-session fixes, local Map Debt entries (`map-debt.md`), and formal GitHub Issue creation.
+
+ ---
+
+ ## 2. Friction Tier Decision Alignment Matrix
+
+ Every friction event or failure detected during agent execution must be evaluated against the friction tiers defined in `self-evolution-policy.md`:
+
+ | Friction Tier | Condition | Primary Action | GitHub Issue Logging Action | Required Labels |
+ |---|---|---|---|---|
+ | **Tier 0 (Quickfix)** | Small friction, fixable inline within allowed edit boundaries in < 5 mins. | Patch inline, update rules/docs ("The Map"). | **Optional**. Log issue only if pattern recurs across sessions. | `type:friction`, `tier:0-quickfix`, `source:agent`, `risk:low` |
+ | **Tier 1 (Friction / Gap)** | Workaround used, capability missing or awkward, but non-blocking. | Patch inline OR record Map Debt in `map-debt.md`. | **Fix inline or log issue**. If deferred as Map Debt, log issue payload. | `type:friction`, `tier:1-friction`, `source:agent`, `risk:low` |
+ | **Tier 2 (Failure / Structural)** | Script/tool broken, execution error, or recurring friction. | Collect stack trace & empirical logs. Patch code or log debt. | **Mandatory Issue Logging** (or comment on existing root-cause issue). | `type:bug` or `type:friction`, `tier:2-structural`, `source:agent` |
+ | **Tier 3 (Regression / Architecture)** | External change, breaking API/selector change, core design flaw. | Collect full evidence bundle & present formal Escalation Template. Synthesized by `repository-improvement`. | **Mandatory Issue Logging + Architecture Review**. | `type:architecture` or `type:bug`, `tier:3-architecture` |
+
+ ---
+
+ ## 2.1 Hotspot Synthesis Engine (`repository-improvement`)
+
+ For Tier 3 architecture friction and recurring friction clusters identified by `friction_cluster_agent`:
+ - The **`repository-improvement`** skill consumes cluster hotspot reports and synthesizes proposals for human review. It never creates branches, commits, or PRs itself — see the skill's Human Gate section.
+ - High-density hotspots are consolidated into architectural refactoring initiatives rather than fragmented single-line patches.
+
+ ---
+
+ ## 3. The Root-Cause Consolidation Principle
+
+ Before creating any new GitHub issue, the agent MUST perform root-cause consolidation:
+
+ > **Root-Cause Question:** *"Is this event itself the root issue, or is it merely one instance/symptom of a broader systemic issue?"*
+
+ ### Operating Rules for Consolidation:
+ 1. **Deduplication Search**: Run `search-related-issues` (via `gh_issue_search.py`) with title keywords and location labels (`area:*` or `plugin:*`).
+ 2. **Existing Root Cause Found**: If an existing issue covers the root cause, do NOT create a new issue. Instead, use `comment-on-existing-issue` (`gh_issue_comment.py`) to append the new empirical evidence and log context to the open issue.
+ 3. **Symptom vs. Cause**: Never open separate issues for "Script A failed line 10" and "Script B failed line 12" if both failed due to the same missing environment variable or missing helper parameter. Open one consolidated issue capturing the root cause.
+
+ ---
+
+ ## 4. Human Suppression Override
+
+ Humans retain full override control over automated issue logging.
+
+ If a prompt, system instruction, configuration, or issue logging context contains:
+ ```yaml
+ issue_logging: suppressed
+ ```
+ or if the user explicitly instructs "do not log issues" / "suppress issue creation":
+ - **Issue creation and commenting MUST be completely bypassed**.
+ - Friction events MUST still be recorded locally in `map-debt.md` or logged in the execution context, but no calls to `gh` issue creation scripts shall be executed.
+
+ ---
+
+ ## 5. Staged Rollout Stages
+
+ To ensure repository stability and prevent issue spam, automated issue logging follows a 4-phase rollout protocol:
+
+ - **Phase 1: Payload Generation (Current Default)**
+ - All script runs operate in dry-run mode (`execute=False`).
+ - Output is formatted as structured JSON payload containing issue title, body, taxonomy labels, and validation status.
+ - No live network requests are made to GitHub.
+ - **Phase 2: Comment Operations**
+ - Live commenting (`execute=True`) enabled for adding evidence to existing human-verified issues.
+ - New issue creation remains dry-run.
+ - **Phase 3: Issue Creation**
+ - Live issue creation (`execute=True`) enabled for Tier 2 and Tier 3 friction events passing all safety gates.
+ - **Phase 4: Label & Status Sync**
+ - Full bidirectional sync of issue state, status labels, and resolution states.
+
+ ---
+
+ ## 6. Mandatory Body Evidence Requirements
+
+ Every issue body (whether generated as payload or submitted live) MUST strictly include all 5 markdown sections:
+
+ 1. `## Summary`: Concise explanation of what failed or caused friction.
+ 2. `## Observed Behavior`: Exact error output, stack trace snippet, or observed unexpected behavior.
+ 3. `## Expected Behavior`: What should have happened according to specifications or rules.
+ 4. `## Evidence`: Command executed, reproduction steps, log locations, or environment details.
+ 5. `## Impact`: Impact on execution, developer flow, or system capabilities (e.g., blocked pipeline, workarounds required).
+
+ *Note: The `body_validator.py` script automatically verifies the presence of these 5 sections.*
+
+ ---
+
+ ## 7. Task Completion Reporting Rules
+
+ When completing a task where friction occurred:
+ - State whether issue logging was executed or produced dry-run payload.
+ - Include the issue number (if submitted live) or the dry-run payload summary (if in Phase 1).
+ - Emit the standard `PRE-COMPLETION GATE` block per `self-evolution-policy.md`.
+
+
+ <!-- plugin: agent-agentic-os / self-evolution-policy -->
+ ---
+ trigger: always_on
+ description: Universal rules for agent self-healing, selector repair, and error recovery policies.
+ globs: ["**/*"]
+ ---
+
+ ## Self-Evolution & Self-Healing Policy
+
+ **Full context and execution protocol -> `.agent/skills/self-evolution/SKILL.md` (if available)**
+ **Skill/directory deletion rules -> `.agent/rules/destructive-action-guard.md` (Part 1)**
+
+ Governs responses when any tool call, subprocess, automation step, selector query, script, workflow, or sub-agent encounters failure or friction. Agents must treat failures as evolution events governed by graph state machines (via `agent-orchestration:graph-execution` and `agent-orchestration:select-loop-strategy`) and 3-Layer Filesystem Memory.
+
+ ---
+
+ ### The 3 Filesystem Memory Layers
+
+ 1. **Layer 1: Runtime Context (Lean Procedural Core)**
+ - Lean `SKILL.md` files (target <= 100 lines). Loaded strictly on-demand.
+ - Raw execution traces and multi-page dossiers are barred during active task execution.
+ 2. **Layer 2: Compounding Wiki Layer (Permanent Knowledge)**
+ - Permanent Markdown in `wiki/` and plugin `references/`: playbooks, edge cases, negative constraints, `map-debt.md`, and `evolution-log.md`.
+ - **Taxonomy & Confidence Decay:** Entries tagged (`OBSERVED`, `HYPOTHESIS`, `CONFIRMED`, `REJECTED`, `OPEN`). Decays from `CONFIRMED` to `OBSERVED` if unverified for 30 days.
+ - **Asymmetric Persistence Rule:** On failure, code mutations roll back, but wiki insights, edge-case findings, and failure logs are NEVER rolled back.
+ 3. **Layer 3: Safe Audit Layer (Append-Only Manifests)**
+ - Stored in `.agent/learning/traces/cycle_manifests.jsonl`.
+ - Tracked audit log capturing event sequences, hashes, exit codes, and affected paths (no raw terminal text/credentials). Audited via `verify_evolution_receipt.py`.
+
+ ---
+
+ ### The 4-Box Automation Gate (Pre-Evolution Qualification)
+
+ Before triggering an autonomous self-evolution cycle, all 4 criteria must be satisfied:
+ 1. *Recurring or structural failure?* (Ignore single transient flukes; repeatable errors/gaps qualify).
+ 2. *Objective, programmatic verifier?* (Deterministic test/script returning shell exit code executed directly by controller — never self-reported).
+ 3. *Iteration ceiling?* (Hard limit of max 3 attempts; controller strictly enforces rollback on 3rd failure).
+ 4. *Immutable persistence sink?* (Layer 2 `wiki/` / `map-debt.md` and Layer 3 `cycle_manifests.jsonl` retain learnings regardless of code pass/fail).
+
+ ---
+
+ ### Proposal Mode & Verifier Sovereignty Invariants
+
+ - **Proposal Mode:** During Stage 1 (`PLAN`), workspace files and configs are strictly read-only. No repo files modified or branches/worktrees spawned until explicit human authorization (`evolution_state.py authorize`).
+ - **Verifier Sovereignty:** Mutation subject cannot modify the acceptance gate. Immutable base protection set (`evaluate.py`, `eval_runner.py`, tests, holdout sets, baselines, policies) and declared verifiers cannot be targeted for mutation. Pre-execution SHA256 hashes are locked; modifications abort cycle with exit code 2. Verifier command must run directly in isolated worktree.
+
+ ---
+
+ ### Hard Gates & Non-Negotiables (always active)
+
+ 1. **Verify Edit Boundaries First**: Check permitted edit boundaries before making autonomous repairs. Escalate immediately if repairs require edits outside allowed boundaries.
+ 2. **Three-Attempt Maximum**: Max 3 repair attempts. If the 3rd fails, hard stop and present Escalation Template with evidence bundle.
+ 3. **Update The Map, Not Just the Diary**: Every fix must update domain playbooks, rules, or references. Log `Status: RESOLVED` in `map-debt.md` for every Tier 0-3 friction event even when patched immediately. When a fix establishes a new invariant, verification contract, or repeatable architectural constraint, synthesize a confirmed Layer 2 playbook (`wiki/playbook-*.md`) and synchronize `wiki/index.md` via `distill_playbook.py`. Dual-log to `references/evolution-log.md` and `cycle_manifests.jsonl`.
+ 4. **Autonomy & Permission Gates**:
+ - **Auto-approved**: New functions/exports, fallback routines/selectors, appending diffs for modified functions.
+ - **Confirmation Gated**: Renaming or moving files.
+ - **Hard Gated (Requires explicit human permission)**: Deletions of any file, function, skill, rule, manifest, eval, or reference.
+ - Composes with `graph-planning-superpowers-policy.md`'s Supreme Law Human Gate.
+ 5. **The Absorption Fallacy - always wrong**: Never conclude an asset is "redundant", "consolidated", or "superseded" and delete it autonomously. Flag overlap; never delete.
+ 6. **One Logical Fix at a Time**: Apply one clean fix per execution pass; never bundle independent repairs.
+ 7. **Fix Forward, Never Skip**: Fix failures at source immediately and update rules/playbooks. Never skip, work around, or add blind retries.
+ 8. **Synchronize Templates on Rule/Strategy Changes**: Update matching templates, generator configs, and prompts when core rules or strategies change.
+ 9. **Refine Prompt Templates on Ingesting Outputs**: Evaluate external model outputs and update prompt templates to guard against observed gaps.
+ 10. **Synchronize Manifests & Reinstall Cleanly on Deletion**: Remove deleted assets from `symlinks.json` and reinstall via `plugin_add.py <plugin-path> -y`.
+ 11. **Pre-Deletion Git History Check**: Run `git log --follow -- <file>` before proposing any file deletion.
+ 12. **Hub First, Spoke Second**: New skill assets must land in plugin root (`plugins/<plugin>/scripts/`, etc.) and symlink into skill folders via `symlink_manager.py`. Run `audit_plugin_structure.py`.
+ 13. **Asymmetric Persistence via Worktree Transfer**: On 3rd attempt failure in isolated worktree, roll back code, but export Layer 2 insights, negative constraints, and debt records to main checkout before worktree teardown.
+ 14. **Evolution Integrity Receipts**: Autonomous evolution commits require a programmatic pre-commit receipt (`EVO-INTEGRITY-<cycle_id>-<hash>`) binding staged tree, verifier exit code, and trace manifest.
+
+ ---
+
+ ### Friction-Driven Self-Evolution & Tiers
+
+ A self-evolution event is required when a script/eval/tool fails, an existing capability is bypassed/manually replaced, workarounds are used, or repeatable process issues arise. Task success does not waive this.
+
+ - **Tier 0 (Friction/Workaround)**: Bypassed capability or used workaround. Patch now + update map + log `Status: RESOLVED` in `map-debt.md` if small/safe; record `Status: OPEN` in `map-debt.md` if unsafe/deferred; escalate if repeated/blocking.
+ - **Tier 1 (Gap)**: Missing capability (build missing piece).
+ - **Tier 2 (Failure)**: Existing capability broken/errors (patch minimal code, save logs).
+ - **Tier 3 (Regression)**: External change broke working behavior (collect evidence, patch primary + fallback).
+
+ **No Silent Bypass Rule:** Agents must use intended capabilities. Workarounds are permitted only after recording the failure as a self-evolution event.
+
+ ---
+
+ ### Pre-Completion Self-Evolution Gate
+
+ Before claiming a task is complete, output this block verbatim:
+
+ ```
+ PRE-COMPLETION GATE:
+ Capability check: Did I verify whether an existing repo capability was intended for this task? [YES/NO]
+ 1. Did any existing capability fail, get bypassed, or get manually replaced? [YES/NO - 1 line if YES]
+ 2. Did I guess, assume, or get corrected on a repeatable process? [YES/NO - 1 line if YES]
+ 3. Did I notice something the next agent will hit again if not fixed? [YES/NO - 1 line if YES]
+
+ If any YES: action taken -> FIX / MAP_DEBT / ESCALATE
+ ```
+
+ The block must be emitted as literal text. The task is not complete until every YES has a declared action.
+
+ ---
+
+ ### Map Debt Management
+
+ If friction cannot be fixed immediately, record it as Map Debt in `<project_root>/references/map-debt.md` (mutable queue, separate from append-only evolution log).
+
+ Each entry must include: Logged date (`YYYY-MM-DD`), Cycle/Session ID, Artifact affected, Friction observed, Why not fixed now, Recommended fix, Evidence/repro, Severity (`S`/`M`/`L`), Repeat (`YES`/`NO`), Status (`OPEN`/`RESOLVED`/`ESCALATED`).
+
+ - **Aging rule:** If `OPEN` entry is older than 3 execution cycles or 14 days, auto-escalate before starting new work.
+ - **Repeat = YES:** Must escalate on next encounter — no further deferral permitted.
+
+
+ <!-- plugin: agent-agentic-os / state-transition-guidance-compliance -->
+ ---
+ description: >
+ Mandatory compliance rule for agents driving SQLite-control-plane state transitions
+ (work-intake and equivalent pipelines). Exists because agents, including Claude, have
+ repeatedly skipped or self-answered YAML transition guidance instead of following it
+ literally.
+ globs: ["**/*"]
+ ---
+
+ # State Transition Guidance Compliance
+
+ ## The Failure Pattern This Rule Targets
+
+ Agents driving a control-plane pipeline (work-intake, self-evolution, or
+ equivalent) have a documented, repeated failure mode: treating the YAML
+ transition guidance (`transition_templates.yaml`'s `human_questions`,
+ `next_steps_hint`, `stage_question_ids`) as advisory prose to summarize,
+ rather than as literal, mandatory input to follow exactly.
+
+ Concretely observed failure instances (see `references/map-debt.md` for full
+ detail, not repeated here):
+
+ - A full task cycle (`issue-593-context-overhead`) skipped `DRAFT_PLAN` and
+ `AWAITING_APPROVAL` entirely, never produced a spec artifact, and closed
+ with a human retrospective recorded verbatim as "a complete failure."
+ - Mid-session, an agent piped a default/recommended answer into an
+ interactive human-approval prompt instead of asking the human for their
+ actual answer first, requiring the human to explicitly stop and say
+ "follow questions at each transition."
+ - An agent pushed a branch to a remote origin without an explicit, isolated
+ push instruction from the human, misreading "remove X from GitHub origin"
+ as implicit push authorization.
+ - An agent made a sequence of unilateral remediation decisions (reverting
+ files, moving directories, restoring symlinks) after discovering damage
+ from an unauthorized bulk edit, without pausing to present the plan and
+ get confirmation before acting, despite already having been corrected for
+ this exact pattern earlier in the same session.
+ - At `APPROVED -> IN_WORKTREE`, the transition guidance literally said
+ "create or select an isolated feature worktree and branch, record both
+ with update-worktree." The agent instead registered the main checkout
+ itself as the worktree path via `update-worktree --path "$(pwd)"`,
+ never creating an isolated `.worktrees/task-<id>/` directory at all —
+ not a tooling gap, a direct failure to do what the instruction said.
+ - The same pipeline's own `create_task()` computes a `main_dirty_advisory`
+ field (dirty file count/paths) that the skill's own instructions require
+ reporting to the user immediately if `dirty_count > 0`, recommending a
+ commit before `APPROVED` so interim work doesn't accumulate uncommitted
+ through the whole planning phase. The agent never reported it — partly
+ because the CLI `init` subcommand discards `create_task()`'s return value
+ and never prints the advisory (a real tooling gap), and partly because the
+ agent also never independently checked `git status` to compensate, despite
+ the instruction not depending on the CLI surfacing it.
+
+ ## The Rule
+
+ 1. **A YAML `human_questions` entry is not optional summary material — it is
+ the literal question to ask, verbatim or near-verbatim, and the literal
+ set of accepted answers to record.** Do not infer, default, or
+ self-answer on the human's behalf, even when a "Recommended" option
+ exists. A recommended default is a suggestion to present, not a license
+ to select it without asking.
+ 2. **`next_steps_hint` and `denial_message` text describes the actual
+ required sequence, not a paraphrase to work around.** If the hint says to
+ run a specific command with a specific flag, run that command with that
+ flag. If it says to create an isolated worktree, create an isolated
+ worktree — do not substitute an equivalent-seeming shortcut, such as
+ registering the main checkout itself as if it were the worktree.
+ 3. **When a step's own documented output includes an advisory or field the
+ instructions say to report** (e.g. `main_dirty_advisory`), and the CLI or
+ tool you're calling doesn't surface it, do not treat that as license to
+ skip the check. Call the underlying function directly, or independently
+ verify the same condition (e.g. `git status`), so the instruction is
+ satisfied regardless of a tooling gap. Report the tooling gap separately
+ as its own friction/map-debt item — it does not excuse skipping the step.
+ 4. **After discovering damage, corruption, or an unauthorized action** (by
+ yourself or by direct instruction), do not proceed through a multi-step
+ remediation unilaterally. Present the audit (what's broken, why, proposed
+ fix) and get explicit confirmation before executing each remediation step
+ that isn't purely read-only verification (diagnose commands, test runs,
+ `git status`/`git diff` are fine to run freely; `git mv`, file reverts,
+ and `restore`-style mutating commands are not).
+ 5. **A single correction from the human on this pattern does not
+ self-resolve for the rest of the session.** If corrected once for
+ skipping or self-answering a transition question, treat every subsequent
+ transition in the same session with the same heightened literalness —
+ do not regress after a few exchanges.
+ 6. **When in doubt about whether an action is "just verification" or "a
+ decision,"** treat it as a decision requiring confirmation. The bar for
+ "just running a read-only check" is narrower than it feels in the moment.
+
+ ## Non-Negotiables
+
+ - Never pipe a canned or default answer into an `--interactive` control-plane
+ prompt without having first obtained that exact answer from the human in
+ this conversation.
+ - Never treat "the user mentioned X in passing" as equivalent to "the user
+ gave an explicit, isolated instruction to do X" for any state-changing
+ action (push, transition, deletion, rename).
+ - Never chain more than one non-reversible remediation action without an
+ intermediate check-in, even when each individual action seems obviously
+ correct in isolation.
+ - Never register the main checkout as a substitute for an isolated worktree
+ when the transition guidance says to create one.
+ - Never let a documented advisory field go unreported solely because the CLI
+ wrapper around it failed to print it — verify independently.
+
+ ## Enforcement: the guidance-compliance gate (added 2026-09-14)
+
+ This rule is no longer advisory-only for `agent-agentic-os`'s control plane.
+ `TransitionCoordinator.coordinate_transition()` now asks a mandatory extra
+ question, `guidance_compliance_confirmation`, on every non-force-close
+ transition: "Have you read and followed this transition's YAML guidance
+ exactly?" It can ONLY be answered via a real `interactive=True` call with a
+ real human typing the answer — it can never be satisfied by
+ `provided_answers`/`--answers`, precisely to prevent an agent self-certifying
+ compliance on a human's behalf. A "NO," or any attempt to answer it
+ non-interactively, sets a permanent `guidance_block_reason` on the task,
+ refusing all further transitions, commits, and pushes until a human explicitly
+ runs `clear-guidance-block --human-confirmed ...`.
+
+ **Before changing any transition's YAML guidance or the coordinator's
+ question-handling logic**, use the `transition-simulator` skill
+ (`plugins/agent-agentic-os/skills/transition-simulator/`) to verify the
+ guidance is still followable by an agent reading it cold — run
+ `run_transition_simulation.py --from <STATE> --to <STATE>` for the specific
+ edge you changed. This is opt-in (costs real time via LLM calls), not part of
+ the default pytest suite.
+
+
+ <!-- plugin: agent-agentic-os / test-driven-development -->
+ ---
+ description: >
+ Enforce Test-Driven Work (TDW) for all new code development (TDD) and orchestration flows (TDO).
+ No implementation code is written or orchestration executed before a success contract or failing test exists.
+ globs:
+ - "src/**/*"
+ - "tests/**/*"
+ - "plugins/**/*"
+ - "backend/**/*"
+ - "frontend/**/*"
+ ---
+
+ # Rule: Test-Driven Work (TDW) — Tests & Contracts Before Execution
+
+ ## Why This Rule Exists
+
+ A silent logic, path resolution, or orchestration contract bug is easily introduced during development or refactoring. Verification contracts written before execution force clarity of intent, define clear success boundaries, and catch bugs before any work is committed.
+
+ **Verification contracts written after the work only verify what you remember to check.
+ Verification contracts written before the work verify what you actually require.**
+
+ ---
+
+ ## The Iron Law
+
+ ```
+ NO CODE DEVELOPMENT OR ORCHESTRATION EXECUTION WITHOUT A FAILING TEST OR SUCCESS CONTRACT FIRST.
+ ```
+
+ This applies to:
+ - **Code Development (TDD)**: New service modules, functions, API routes, automation scripts, and bug fixes to any of these.
+ - **Orchestration & Workflows (TDW/TDO)**: New prompt templates, agent tool execution paths, coordinator scripts, workflow engines, and task runners.
+
+ It does NOT apply to:
+ - Throwaway exploration or prototyping (which must be discarded before the actual implementation begins)
+ - Static, non-executable configuration files and JSON/YAML data files
+ - Automatically generated code (migration files, boilerplate, etc.)
+ - Declarative task checklists or static documents (unless executable)
+
+ ---
+
+ ## Mandatory Pre-Execution Step
+
+ **Before writing any implementation code or executing any new orchestration flow**, establish the verification contract:
+
+ 1. **For Code**: Write a failing unit or integration test first.
+ 2. **For Orchestration**: Write a mock evaluation scenario, an assertions list, or an expected output schema validator first.
+ 3. **Skill / Test Tooling**: If the workspace contains a test runner or TDD skill, invoke it before touching code.
+
+ This enforces the Red-Green-Refactor cycle and blocks the rationalization patterns ("too simple to test", "I'll do it after") that lead to broken systems. If you start the work before writing the contract, it is invalid. Delete it and start over.
+
+ ---
+
+ ## Test Tier Locations
+
+ Place tests in the correct tier directory designated for the project. Always locate the project's existing test structure (e.g. `tests/`, `test/`, `spec/`) first and follow its naming patterns. Typical default locations:
+
+ | What you're building | Test location | Test file naming |
+ |---|---|---|
+ | Pure business logic / services | `/tests/unit/` or `/test/` | `test_<module_name>.py` / `<ModuleName>.spec.ts` |
+ | API routes / Controllers | `/tests/integration/` or `/tests/api/` | `test_<route_name>_routes.py` / `<RouteName>.spec.ts` |
+ | UI components | `/tests/ui/` or `/tests/frontend/` | `<ComponentName>.spec.ts` |
+ | Script automation / CLI tools | `/tests/cli/` or `/tests/` | `test_<script_name>.py` |
+
+ ---
+
+ ## What a Passing Test Looks Like
+
+ ### 1. Pure Function (Deterministic Unit Test)
+ ```python
+ # WRITE THIS FIRST — watch it fail
+ def test_calculate_total_with_override():
+ result = calculate_total(base_amount=100.0, tax_rate=0.05, discount=10.0)
+ assert result == 95.0 # discount applied before tax
+
+ # THEN write the implementation in calculations.py
+ ```
+
+ ### 2. CLI Argument Validation (Integration Test)
+ ```python
+ # WRITE THIS FIRST
+ def test_tool_requires_target_argument():
+ result = subprocess.run(
+ ["python3", "cli_tool.py", "--action", "sync"],
+ capture_output=True, text=True
+ )
+ assert result.returncode != 0
+ assert "--target is required" in result.stderr
+ ```
+
+ ### 3. API Route Test (Backend Server)
+ ```javascript
+ // WRITE THIS FIRST
+ describe('POST /api/payment/preflight', () => {
+ it('should block transaction when balance is insufficient', async () => {
+ const res = await request(app)
+ .post('/api/payment/preflight')
+ .send({ accountId: '123', amount: 1000.0 });
+ expect(res.status).toBe(422);
+ expect(res.body.state).toBe('INSUFFICIENT_FUNDS');
+ });
+ });
+ ```
+
+ ---
+
+ ## What Counts as a Valid Failing Test
+
+ A test only satisfies the TDD requirement if — **before** any implementation is written:
+ 1. The test executes without syntax/runtime compilation errors.
+ 2. The test **fails** for the expected reason (e.g., assertion error, missing function).
+ 3. The failure **proves** the feature or bugfix does not yet exist.
+
+ **Invalid examples — these do NOT satisfy TDD:**
+ ```python
+ assert True # Trivial — proves nothing
+ ```
+ ```python
+ with pytest.raises(Exception): ... # Too broad — does not verify the specific failure cause
+ ```
+ ```python
+ mock_fn.return_value = expected_value
+ assert mock_fn() == expected_value # Tests the mock, not the actual code path
+ ```
+ ```python
+ @pytest.mark.skip # Skipped test — does not prove a failure
+ pass
+ ```
+
+ **For bug fixes:** The failing test must reproduce the original bug before the fix is applied. If the test passes before you change anything, it is not a valid TDD cycle.
+
+ ---
+
+ ## Critical Runtime Paths — No Mocking Allowed
+
+ Certain critical paths must be tested with **real subprocess execution, real file system resolution, and actual I/O** rather than synthetic mocks:
+
+ - Script execution wrappers and bridges (e.g., spawning helper scripts or subprocesses)
+ - File system path resolution logic and directory setup
+ - File readers and parsers handling external formats
+ - External API client boundaries
+
+ **Do NOT mock these in the primary integration test:**
+ ```python
+ # FORBIDDEN for critical integration paths:
+ mock_subprocess_run.return_value = ...
+ mock_os_path_exists.return_value = True
+ mock_file_read.return_value = "fake file content"
+ ```
+
+ **Reason:** Production bugs are frequently caused by runtime path resolution and formatting anomalies. Mocking these layers hides the bug entirely.
+
+ ---
+
+ ## Anti-Patterns — Stop and Start Over
+
+ | Pattern | What it produces |
+ |---|---|
+ | Writing the function first, then writing a test | Tests that only verify what you built, not what was required |
+ | Modifying paths or imports without verifying via an import test | Silent import and runtime load failures |
+ | Refactoring a bridge/helper without an end-to-end integration test | Invisible path or argument mismatch bugs |
+ | Testing only the happy path | Missed edge cases, poor error handling, and silent crashes |
+ | Testing via a heavy API when a unit test is more appropriate | Slow test suites that hide where the actual failure lies |
+ | Testing internal private methods instead of observable behavior | Brittle tests that break during refactoring without protecting against regression |
+
+ **Observable behavior is the contract.** Test exit codes, API response structures, JSON schemas, and state transitions—not internal flags, private variables, or cache internals.
+
+ ---
+
+ ## Mutation Safety Rule
+
+ Any change touching core business logic or security boundaries **must** include a regression test that reproduces the pre-change behavior AND an assertion for the new expected behavior. No existing critical-path test coverage may be reduced. If you refactor a test, the new version must cover at least the same cases.
+
+ ---
+
+ ## Prefer Replay Fixtures Over Synthetic Mocks
+
+ When capturing external behavior for tests, prefer **recorded real output** over fabricated mocks:
+ - Captured stdout/stderr logs from tools
+ - Raw API response payloads (saved as local JSON/YAML fixtures)
+ - Sample static files and databases
+
+ Real captures preserve formatting quirks, character encodings, and edge cases that synthetic mocks routinely miss.
+
+ ---
+
+ ## Red Flags — Stop Immediately
+
+ If you think any of the following, you are rationalizing. Stop and write the test first:
+ - *"This is just a quick script, tests would be overkill"*
+ - *"I'll add tests after I see if this approach works"*
+ - *"I manually ran it in my terminal and it worked"*
+ - *"It's just a path change, nothing could break"*
+ - *"The test is too hard to write before I know the interface"*
+
+ The last one especially: if you don't know the interface, write the test that describes **the interface you want**. That IS the design.
+
+ ---
+
+ ## Test-Driven Orchestration (TDO) & Prompt-Driven Work — Success Contracts First
+
+ For coordinator scripts, workflow engines, master orchestrators, agent prompts, and tool execution flows:
+ - **Define the Orchestration Contract First**: Before writing any coordination logic or sequencing scripts, write an integration test or schema assertion that verifies parameter propagation between sub-components, execution orders, and error bubbling.
+ - **Prompt & Output Schema Assertions**: When developing LLM prompts or templates, first define the exact output structure (e.g., JSON schema, markdown headings, or exact tone boundaries). Write validation checks (e.g., matching keys, non-empty outputs, schema compliance) before finalizing the prompt instruction.
+ - **Safety and Boundary Invariance**: Assert that critical safety boundaries (e.g., user confirmations, budget caps, authorization gates, and data privacy limits) cannot be bypassed by any code path, flag override, or exception handler in the orchestrator.
+ - **Runnable Integration Scenarios**: Every orchestrated workflow or skill must have a matching runnable evaluation scenario. Mock input fixtures must trigger the flow and verify that the output payload matches expectations in an offline or sandboxed environment.
+
+ ---
+
+ ## Related Rules and References
+
+ - `.agent/rules/coding-conventions.md` — coding conventions and documentation standards
+ - `superpowers:test-driven-development` skill (if available) — invoke BEFORE writing any implementation
+ - `graph-planning-superpowers-policy.md` — test-driven execution and verification discipline
+
+ <!-- plugin: agent-agentic-os / worktree-lifecycle-management -->
+ ---
+ description: Mandatory protocol for creating, reporting on, and closing out git worktrees -- prevents the "where is it" confusion loop caused by collapsing five distinct states into one vague "done".
+ globs: ["**/*"]
+ ---
+
+ # Worktree Lifecycle Management
+
+ ## The Problem This Rule Solves
+
+ Worktree-related changes frequently suffer from ambiguity when multiple git states (uncommitted local work, committed on a branch, pushed to remote, merged to main, local ref updated, and checked out on disk) are collapsed into the vague word "done". This leads to confusion about where files actually reside and whether PRs or branches are safely integrated.
+
+ ## The Law
+
+ > **A worktree-related change is not "done" until you state which of the six states below
+ > it is actually in, using the exact vocabulary below.** Never use the bare words "done",
+ > "merged", "pushed", or "saved" without one of these qualifiers attached. When the user
+ > asks "where is X" or "is it gone", answer with the state name and the exact path/branch,
+ > not a general reassurance.
+
+ ## The Six States (use this exact vocabulary)
+
+ 1. **Written in the worktree** -- exists only as an uncommitted file inside the worktree's
+ working directory. Invisible to git log, invisible to any other checkout, lost if the
+ worktree is deleted.
+ 2. **Committed in the worktree** -- has a commit hash, but only reachable from the
+ worktree's local branch. Invisible outside this machine.
+ 3. **Pushed to origin** -- the branch exists on GitHub. A PR *can* be opened. **Not yet
+ merged.** State the exact `git push` result and the PR URL, and say explicitly "not
+ merged yet" in the same sentence.
+ 4. **Merged into `origin/main`** -- verify this yourself via `git fetch origin main &&
+ git log --oneline origin/main -3` and quote the actual merge commit hash back. Never
+ infer this from "I pushed it" or from the user saying "ok" -- confirm the merge commit
+ exists on `origin/main` before calling anything merged.
+ 5. **Local branch ref updated** -- `git fetch origin main:main` (or equivalent) updates
+ what your local `main` branch *points to*. **This does not change any file on disk if
+ the current checkout has a different branch checked out.** Always state explicitly
+ which branch is currently checked out (`git branch --show-current`) in the same breath
+ as reporting this.
+ 6. **Checked out on disk** -- the actual working directory files match the target branch.
+ Verify with `ls`/`git status` on the real path, not by inference. Only at this state can
+ you tell the user "you can see it now" -- and even then, name the exact path.
+
+ ## Non-Negotiables
+
+ 1. **State the state.** Every progress report on worktree-related work names which of the
+ six states applies, e.g. "pushed to origin, PR link below, not yet merged" or "merged
+ into origin/main (commit `988b77a`), but your checkout is still on
+ `feature/x` -- run `git checkout main` to see it."
+ 2. **Never say "merged" without verifying `origin/main` yourself.** A user saying "I
+ merged" is a trigger to `git fetch` and quote the resulting commit hash, not license to
+ parrot "merged" back without checking.
+ 3. **Never claim a file is visible "now" without checking the actual checked-out branch.**
+ Updating a local branch ref is not the same as changing the working directory. If the
+ current checkout is on a different branch than the one just updated, say so before the
+ user has to ask why they can't see anything.
+ 4. **State exact full paths for every file/plugin/worktree you reference.** "It's in
+ the new plugin" is not an answer; state the exact path (e.g. `/full/path/to/plugins/<plugin>/scripts/script.py`).
+ 5. **Before deleting any worktree, verify state 4 (merged into origin/main) first**, via
+ `git fetch` + `git log origin/main`, not by assuming a prior push means the PR was
+ merged. Only after that verification, delete via the native worktree-removal tool (or
+ `git worktree remove` + `git worktree prune` if the native tool reports no active
+ session), and confirm via `git worktree list` that it's gone.
+ 6. **All symlink creation/removal inside a worktree goes through
+ `.agents/skills/symlink-manager/scripts/symlink_manager.py`**, per
+ `.agent/rules/plugin-architecture-policy.md` Section 5 -- this applies inside worktrees exactly as
+ much as the main checkout. If the tool isn't present in the worktree, restore it from
+ the marketplace-cached copy or the sibling monorepo before touching any symlink, never
+ fall back to raw `ln -s`.
+ 7. **When multiple worktrees exist, or worktree work spans several turns, restate the
+ current state of every open worktree at the start of any status report** -- don't make
+ the user re-derive it from scattered messages.
+ 8. **Mandatory Post-Implementation Review Stage Gate (`WORKTREE_REVIEW`)**: Once code development
+ and automated tests pass inside a worktree, AI agents MUST NEVER autonomously push to origin
+ or open a PR. The agent MUST transition the task in `context/control_plane.db` to `WORKTREE_REVIEW`,
+ present the diff and summary to the human user, and provide the user the explicit choice between:
+ - (A) Running multi-agent adversarial code review (`MULTI_AGENT_CODE_REVIEW`) across independent model perspectives, or
+ - (B) Authorizing direct `git push` and PR creation for human review.
+ 9. **Zero Autonomous Push Invariant**: Pushing code to origin without passing through the post-implementation
+ review gate and receiving user authorization is an operational violation. Pre-push hooks and
+ `agent_control.py update-worktree` will reject any attempt to mark a worktree as `pushed_to_origin`
+ unless the task has transitioned through `WORKTREE_REVIEW`.
+ 10. **The Standard Post-`DONE` Protocol**: When `DONE` is signed, the task lifecycle in SQLite is complete. Agents must never freeze, guess, or abandon the worktree. Execute the repository convergence sequence in order:
+ - **Step 1: Push Worktree Branch to Remote (SOFT)**: Ask the human in chat for confirmation: *"Task is marked DONE. Would you like me to push `<worktree_branch>` and create the pull request to `main`?"* Upon confirmation, run `git push origin <worktree_branch>` and update SQLite worktree state to `pushed_to_origin` via `agent_control.py update-worktree`.
+ - **Step 2: Create PR / Merge into `origin/main` (SOFT)**: Open the PR via `gh pr create --base main --head <worktree_branch> ...`. State the PR URL and "not yet merged", and await the user's review/merge on GitHub.
+ - **Step 3: Sync Local `main` (AGENT / SOFT)**: Once merged into `origin/main`, checkout `main` in the repository root and pull: `cd <repo_root> && git checkout main && git pull origin main`. Update SQLite worktree state to `merged_into_origin_main`.
+ - **Step 4: Prune Worktree and Delete Local Task Branch (AGENT / SOFT)**: Verify clean state on `main`, then remove the worktree and delete the local task branch:
+ ```bash
+ git worktree remove .worktrees/<task-id>
+ git branch -d <worktree_branch>
+ ```
+
+ ## Where This Applies
+
+ - Every worktree session in the repository.
+ - Every report to the user about progress on worktree-based work, from creation through final deletion.
+ - Applies in addition to, not instead of, `worktree-subagent-leak-detection.md` (which covers subagents writing outside assigned worktrees). Both apply simultaneously in any subagent session run inside a worktree.
+
+
+ <!-- plugin: agent-agentic-os / worktree-subagent-leak-detection -->
+ ---
+ description: A subagent's pwd/git-branch confirmation does not guarantee its Edit/Write calls stay inside the assigned worktree — a mandatory post-task check does. Companion to worktree-lifecycle-management.md, which covers the full worktree lifecycle (create/commit/push/merge/cleanup) this file does not.
+ globs: ["**/*"]
+ ---
+
+ # Worktree/Subagent Isolation (Leak Detection)
+
+ **Scope:** This rule covers subagents writing outside their assigned worktree. For the broader lifecycle (creating, verifying, pushing, merging, and cleaning up worktrees), see `worktree-lifecycle-management.md`. Both rules apply simultaneously when subagents execute inside a worktree.
+
+ ## The Problem This Rule Solves
+
+ A subagent's `cd` and `pwd` confirmation at task start only changes its shell state—file editing tools (Edit/Write) resolve absolute file paths independently and can mistakenly write to the main checkout. Treat task-start confirmation as a preliminary check, not a guarantee.
+
+ ## The Law
+
+ > **A `cd`-and-confirm step at task start is not evidence that every subsequent
+ > Edit/Write call in that session targets the confirmed directory.** `cd` only changes
+ > the *Bash tool's* persisted shell state — the Edit/Write/Read tools resolve on the
+ > exact absolute path parameter they're given, independent of any prior `cd`. Treat the
+ > confirmation step as a cheap first-line check, not a guarantee, and verify the
+ > **controller's own main checkout** after every task, not just the worktree.
+
+ ## Non-Negotiables
+
+ 1. **Every subagent-driven-development dispatch still gets the standard confirmation
+ step.** Instruct the subagent to `cd` into the exact worktree path as its first
+ action and confirm via `pwd` and `git branch --show-current` before editing anything.
+ This remains necessary — it just isn't sufficient on its own.
+
+ 2. **After every implementer or fix subagent reports back, the controller runs
+ `git status --short` in the main checkout (not the worktree) before generating the
+ review package.** This is the mandatory second check. It catches a leak within one
+ task cycle — while it's still uncommitted and trivially discardable — instead of
+ only surfacing at final-merge time, when it's had 5+ more tasks to compound or get
+ tangled into review history.
+
+ ```bash
+ # From the main repo root, not the worktree:
+ git status --short
+ ```
+
+ Any unexpected `M` entry that wasn't present before the task's dispatch is a leak.
+ Diff it before touching anything (`git diff <path>`) — don't assume.
+
+ 3. **A leak found this way is virtually always safe to discard, but verify first.**
+ The signature of this exact failure mode is: the main checkout's stray diff is an
+ *incomplete* or *superseded* subset of work that's already properly committed in the
+ worktree branch (e.g. missing a later fix-round commit's changes). If the diff
+ content matches that pattern, discard it via `git checkout -- <path>` in the main
+ checkout before merging. If the diff contains anything that doesn't look like a
+ partial duplicate of the worktree's own committed work — stop and investigate before
+ discarding; it may be unrelated, real, uncommitted user work that predates the
+ session (check the pre-session `git status` baseline first).
+
+ 4. **Log a repeat occurrence, don't just re-fix it silently.** Per
+ `.agent/rules/self-evolution-policy.md`'s Map Debt register: a `Repeat: YES` entry
+ requires action on next encounter, not further deferral. A third occurrence of this
+ exact failure mode should prompt investigating the harness-level root cause directly
+ (e.g. checking whether a specific tool or dispatch pattern is the common thread)
+ rather than only reapplying this same procedural mitigation a third time.
+
+ ## Where This Applies
+
+ - Any `superpowers:subagent-driven-development` or `superpowers:executing-plans`
+ session that dispatches implementer/fix subagents into an isolated worktree.
+ - Applies to every task in a plan, not just the first or last — the leak in the C2
+ incident happened during a mid-plan fix round (Task 7's second fix dispatch), not at
+ the boundaries.
+
+