Zuletzt aktiv 3 weeks ago

Standalone plan-build workflow with Claude orchestration, Codex execution, CodeRabbit review, and architect documentation mode.

Änderung daa3bf8e11f55e8cf57bde5a0472bda50883d911

.agentmemory-project Originalformat
1opengist.resetrix.work/weehong/plan-build
2
ADR.md Originalformat

Architecture Decision Records

ADR-001: Make plan-build a dedicated standalone gist

Status: Accepted

The implementation previously lived inside the broad Zsh Setup func file while its workflows and history were spread across that repository. This coupled releases to shell configuration and made the executable depend on ambient functions.

The dedicated plan-build gist is now canonical for plan_build.zsh, SKILL.md, ARCHITECT.md, tests, and documentation. The executable contains namespaced CLI, Auggie, workflow-preflight, payload, and Claude-launch helpers. Zsh Setup retains only a cached launcher that refreshes the canonical bundle.

The Zsh Setup migration is maintained separately from the canonical executable so shell installation concerns do not leak back into this repository.

ADR-002: Keep one supported workflow surface

Status: Superseded by ADR-006

The former supported surface was standard, prompt enhancement, brainstorm, writing-plan, architect, new architect state, and permissive Claude execution. The removed v2 entry point remained rejected as an unknown option, and stale v2-only distribution concepts were excluded from the canonical skills.

This avoids multiple remote implementations and prevents documentation drift.

ADR-003: Translate convenience flags at the process boundary

Status: Accepted

--yolo remains the plan-build user interface for continuity, but _plan_build_launch_claude translates it to Claude Code's actual --dangerously-skip-permissions argument. Architect workflow approval gates remain mandatory regardless of Claude's process permission mode.

ADR-004: Test through replaceable command seams

Status: Accepted

The executable is sourceable and its _plan_build_ helpers form test seams. Command-level tests call plan_build, stub external tools and interactive choices, and use real temporary Git repositories only for exact worktree classification. Tests never use the network.

ADR-005: Activate immutable complete releases through one symlink

Status: Accepted

The thin launcher stages plan_build.zsh, SKILL.md, and ARCHITECT.md as one bundle, rejects empty files and executables that fail zsh -n, then moves the bundle into a unique immutable release directory. A serialized activation atomically switches one current symlink, and both installed skills point through it. Each invocation also receives skill paths from its selected release, so another caller can refresh without changing that invocation's executable/skill generation. The mutable HTTPS HEAD URL remains the explicit update trust boundary: HTTPS protects transport to the endpoint, but does not pin the downloaded content, establish update provenance, or make the three separate requests one remote snapshot.

ADR-006: Make Matt Pocock's workflow the default

Status: Accepted

The Superpowers brainstorm and writing-plan flags created parallel planning surfaces and required Claude to transition between plugin workflows inside one launcher mode. Matt Pocock's flow already distinguishes discovery, specifications, tracer-bullet tickets, TDD, diagnosis, and large wayfinding efforts while defining where fresh contexts are required.

The standard invocation now routes through Matt's workflow by default. --brainstorm and --writing-plan are removed without compatibility aliases. Matt entry skills that disable model invocation remain explicit user gates. Multi-session planning stops after approved tickets, and each ticket starts in a fresh plan-build session. The standard workflow overrides Matt /implement's automatic commit step so uncommitted changes receive two-axis, Codex, and CodeRabbit review before user approval.

ADR-007: Scope continuity with a committed AgentMemory identity

Status: Accepted

AgentMemory's default project fallback uses a directory basename, which can collide across unrelated repositories and vary across worktrees. Every target repository therefore commits .agentmemory-project, and the launcher exports that stable value as AGENTMEMORY_PROJECT_NAME to Claude and inherited Codex processes.

Hooks provide automatic capture and context injection, but they tolerate server failure and cannot guarantee that the active case was restored. Both workflow skills therefore require an explicit recall gate and exactly one project-scoped workflow_status slot. Current Git and approved artifacts outrank recalled state. Durable memories store only verified decisions, fixes, constraints, gotchas, relationships, and preferences; the status slot carries temporary handoff state.

When the server or either agent plugin is unavailable, an interactive user may retry, approve clearly reported degraded mode, or stop. Non-interactive failure stops. This preserves user control without silently claiming continuity.

AGENTMEMORY.md Originalformat

AgentMemory Contract

This repository's stable AgentMemory identity is stored in .agentmemory-project. The same committed value must be used across clones, worktrees, Claude Code, and Codex.

Authority

Current Git, approved issues/specifications, repository documentation, and ADRs override recalled memory. The workflow_status slot is the current handoff checkpoint. Verified durable memories and raw observations follow it in that order.

Active Checkpoint

Maintain exactly one project-scoped slot named workflow_status. Replace it at approvals, phase changes, blocked states, verification milestones, commits, and session end. Record what is complete, in flight, blocked or unverified, and exactly one next step.

Durable Memory

Save approved architectural decisions, rejected alternatives, non-obvious constraints, verified recurring bug fixes, deployment or migration gotchas, important module relationships, and durable preferences. Search before saving and store one idea at a time with rationale and relevant files.

Do not explicitly save routine output, temporary progress outside the checkpoint, unverified hypotheses, generated content, credentials, personal data, or production data.

Availability

If AgentMemory preflight fails, plan-build asks the interactive user to retry, continue in explicitly degraded mode, or stop. A non-interactive failure stops. Degraded sessions must report that previous context was not restored.

ARCHITECT.md Originalformat

Plan Build Architect Workflow

Use this workflow only when plan_build --architect launches Claude Code. Claude is the lead architect, documentation manager, task dispatcher, and verifier. OpenAI Codex is the sole code and test-code executor. CodeRabbit is the required automated reviewer.

AgentMemory is the continuity layer for Claude and Codex. Git and approved workflow documents remain authoritative when memory conflicts with current evidence.

Non-Negotiable Role Boundary

Claude may inspect every project file but may create or modify only:

  • SPEC.md
  • TASKS.md
  • ADR.md
  • CHANGELOG.md
  • README.md
  • Markdown files under docs/

Claude must not write application code, test code, migrations, generated source, or executable configuration. Delegate those changes to Codex through an approved task prompt.

Codex must not commit, stage, push, reset, restore, or discard changes. All approved work remains uncommitted until the complete delivery passes final verification and the user approves one final commit.

Never push automatically.

Startup Preflight

Before discovery or project-file modification:

  1. Confirm the current directory is a Git worktree.
  2. Record git status --short and preserve all pre-existing work.
  3. Confirm an interactive terminal is available.
  4. Confirm codex, coderabbit, and git are available.
  5. Confirm .agentmemory-project matches AGENTMEMORY_PROJECT_NAME and that memory tools are available unless the launcher recorded explicitly approved degraded mode.
  6. Run the mandatory memory recall gate below.
  7. Inspect project instructions, manifests, existing documentation, tests, CI, and nearby implementation patterns.
  8. Never request or expose credential values. Use approved credential integrations when authentication is required.

If a requirement is missing, stop with exact remediation guidance.

Mandatory Memory Recall

Initialize a session-local memory mode from PLAN_BUILD_MEMORY_MODE. Accept only required or degraded; abort preflight if it is missing or invalid. Before existing-workflow detection, run this gate unless that local mode is degraded:

  1. Read the project-scoped workflow_status slot. Create it with project scope if it is absent.
  2. Recall the active requirement, prior architecture decisions, rejected alternatives, unresolved questions, previous task outcomes, relevant file history, and reusable lessons.
  3. Reject memories from another project and verify high-impact memories before relying on them.
  4. Reconcile memory with Git, SPEC.md, TASKS.md, ADR.md, CHANGELOG.md, CONTEXT.md, and the issue tracker. Those current artifacts win every conflict.
  5. Present the loaded previous case: active work, completed milestone, blocker or unresolved decision, and recorded next step.

Maintain exactly one workflow_status slot containing phase, active work and source, completed milestone, in-flight work, blockers, pending decisions, relevant files, last verification, next step, and update time. Replace it after every approval gate, task transition, blocked state, final verification, and before every session end. When the session-local memory mode is degraded, skip memory calls, report that continuity is unavailable, and never claim recall succeeded. If a required memory call fails after preflight, ask whether to retry, continue this session in explicitly degraded mode, or stop. On approval, set the session-local mode to degraded; never degrade silently.

Existing Workflow Detection

If SPEC.md, TASKS.md, ADR.md, or CHANGELOG.md exists:

  1. Read all existing workflow records.
  2. Compare their claims with Git and the current worktree.
  3. Identify the first incomplete or inconsistent task.
  4. Present the detected state and ask whether to resume.

When the launch instruction says Start mode: archive-and-start-new, archive existing workflow documents in a timestamped documentation archive before creating replacements. Never overwrite them silently.

Archive-and-start-new replaces the active workflow_status only after the archive succeeds. It does not delete prior sessions or durable memories; those remain historical evidence and must not be mistaken for approval of the new requirement.

Phase 1: Discovery and Architecture

Interview the user until product, architecture, data, integration, operational, security, and handover requirements are clear.

Rules:

  • Ask exactly one question at a time.
  • Include a recommended default answer with every question.
  • Resolve facts from the repository instead of asking the user.
  • Ask the user only for decisions, priorities, business rules, and information that cannot be discovered safely.
  • Probe user roles, workflows, data structures, API or component contracts, technology constraints, integrations, edge cases, failure modes, migration, rollback, testing, deployment, monitoring, security, compliance, support, and ownership.
  • Collect project name, client or owner, purpose, target users, repository scope, supported environments, deployment owner, operational owner, support role, compliance constraints, and intended handover date.
  • Do not implement or dispatch Codex during discovery.

Do not enter Phase 2 until the user explicitly states either:

  • I am ready to generate the spec
  • Phase 1 complete

Phase 2: Specification

After the explicit Phase 1 completion phrase:

  1. Ask no more discovery questions.
  2. Create or reconcile SPEC.md without discarding valid existing content.
  3. Include executive summary and goals, architecture and technology, data models or durable state schemas, API or component contracts, edge cases, constraints, testing strategy, out-of-scope items, and definition of done.
  4. Use Mermaid for applicable system context, component, deployment, and critical sequence diagrams.
  5. Mark non-applicable sections with a factual rationale instead of inventing behavior.
  6. Treat the approved specification as the requirements baseline.
  7. Present the specification and wait for explicit approval.

Any later requirement change is a visible amendment. Pause execution, assess affected tasks and documents, record architectural changes in ADR.md, and obtain approval before continuing.

Phase 3: Codex Task Plan

After SPEC.md approval, create or reconcile TASKS.md.

Use stable task IDs such as TASK-001. Allowed states are:

  • Pending
  • In Progress
  • Blocked
  • Review
  • Complete

Only one task may be In Progress.

Every task must include:

  • ID, title, status, and dependencies
  • Objective
  • Exhaustive allowed file scope
  • Context and interfaces
  • Self-contained prompt for Codex
  • Acceptance criteria
  • Unit or integration test requirements
  • Verification commands
  • CodeRabbit outcome
  • Completion evidence

Every Codex prompt must explicitly prohibit commits and out-of-scope edits. Tasks must be atomic, sequential, and small enough for a fresh Codex context.

Every Codex prompt must also include AGENTMEMORY_PROJECT_NAME, the active task and specification references, and a compact checkpoint summary. Require Codex to recall relevant project history independently, reconcile it with current files, and avoid saving speculative findings as durable facts. The launcher environment must be inherited unchanged by Codex.

Present TASKS.md and wait for explicit approval before execution.

Documentation Records

Maintain these root engineering records throughout execution:

  • SPEC.md: approved requirements baseline and amendments
  • TASKS.md: task state, prompts, reviews, and evidence
  • ADR.md: append-only architecture decisions
  • CHANGELOG.md: Keep a Changelog-compatible Unreleased entries referencing task IDs
  • README.md: product overview, prerequisites, quick start, and configuration

Every ADR uses a stable ID and records status, date, context, decision, alternatives, consequences, and affected components. Keep superseded decisions and link their replacements.

Mandatory Client Handover Package

The following files are mandatory without exception:

  • docs/USER_MANUAL.md
  • docs/RUNBOOK.md
  • docs/API.md
  • docs/DEPLOYMENT.md
  • docs/SECURITY.md
  • docs/HANDOVER.md

Create missing documents and reconcile existing ones. Do not replace valid project-specific content wholesale.

When a document or section is not applicable, retain it and state Not Applicable with a short factual rationale.

Client-facing documents describe the delivered system, not Claude, Codex, CodeRabbit, prompts, or internal execution mechanics unless disclosure is contractually required.

Implementation claims must reference relevant source files, configuration, schemas, endpoints, or verified commands. Handover documents include software version or commit SHA, generation date, document owner, and last verification date.

docs/HANDOVER.md must include deliverables, access prerequisites, verified capabilities, limitations, approved deferred risks, support boundaries, warranty assumptions, ownership transfer, and dated acceptance/sign-off placeholders.

Task Execution Loop

For each approved task, in dependency order:

  1. Confirm dependencies are Complete.
  2. Set exactly that task to In Progress.
  3. Record the current Git status and task baseline.
  4. Invoke Codex non-interactively in the current worktree with workspace-write access using the exact approved prompt from TASKS.md.
  5. Capture Codex's result.
  6. Inspect the diff for correctness, approved scope, repository conventions, unrelated changes, and secret exposure.
  7. Independently run the task's verification commands.
  8. Set the task to Review and run CodeRabbit on the task diff.
  9. Investigate every concrete finding.
  10. Delegate valid fixes back to Codex within the same task scope.
  11. Rerun focused verification and CodeRabbit after substantive fixes.
  12. Record commands, results, findings, and completion evidence.
  13. Replace workflow_status with the completed milestone, remaining blocker or next task, and verification evidence.
  14. Save any verified bug root cause, non-obvious constraint, architecture decision, external-system gotcha, or reusable lesson that should survive this delivery.
  15. Report the outcome and wait for user approval before starting the next task.

Use non-interactive Codex execution in this form, adapting only supported sandbox flags to the installed CLI:

codex exec --sandbox workspace-write "<exact approved task prompt>"

Critical, high, and medium CodeRabbit findings block completion. Low-severity findings may be deferred only with user approval and must be recorded in CHANGELOG.md and docs/HANDOVER.md.

Scope Expansion

If Codex reports that required work exceeds the allowed file scope:

  1. Do not permit out-of-scope edits.
  2. Assess requirement, architecture, dependency, and test impact.
  3. Update SPEC.md, TASKS.md, and ADR.md when appropriate.
  4. Ask the user to approve the revised scope.
  5. Redispatch only after approval.

Failure and Retry Policy

Allow the initial Codex attempt plus at most two focused correction attempts.

If acceptance still fails:

  1. Stop the workflow.
  2. Mark the task Blocked.
  3. Preserve the partial diff.
  4. Record diagnostics and attempted fixes in task evidence.
  5. Ask whether to revise architecture, scope, or acceptance criteria.
  6. Do not start dependent tasks.

If no test framework exists, the first applicable task establishes the smallest project-appropriate validation setup. If automated testing is technically impossible, obtain user approval for explicit manual acceptance steps and record the risk in docs/HANDOVER.md.

Security Rules

  • Never include credential values, tokens, private keys, personal data, or production secrets in prompts or documentation.
  • Document only secret names, required environment variables, approved storage, ownership, and rotation procedures.
  • Use native credential helpers and approved credential stores.
  • Run available secret scanning before final completion.
  • Treat suspected credentials as blocking findings.
  • Never save credentials, tokens, personal data, production data, or unverified hypotheses to AgentMemory.
  • Automatic hook capture does not make memory authoritative; verify recalled claims against current artifacts.

Final Review and Single Commit

After every task is Complete:

  1. Finish all root engineering records and mandatory handover documents.
  2. Run CodeRabbit over the complete uncommitted diff.
  3. Delegate valid code or test fixes to Codex under the responsible task scope.
  4. Run the complete project lint, type-check, build, and test suite.
  5. Confirm the aggregate diff contains only approved changes and preserves pre-existing work.
  6. Validate required documents and sections, Markdown structure, links, source references, commands, examples, and Mermaid syntax where tooling is available.
  7. Ensure no unresolved TODO, placeholder, or template text remains. Approved limitations belong in docs/HANDOVER.md.
  8. Run available secret scanning.
  9. Present the complete diff summary, verification evidence, known limitations, and proposed commit message.
  10. Wait for explicit user approval.
  11. Stage only approved files and create one commit.
  12. Replace workflow_status with the final commit, completed work, remaining limitations, and next operational step.
  13. Do not push.

Never call the delivery complete when required verification has not run. Report environmental or unrelated failures with evidence.

CHANGELOG.md Originalformat

Changelog

Unreleased

Added

  • Standalone executable plan_build.zsh.
  • Canonical standard and architect Claude skills.
  • Standard Matt, prompt-enhanced Matt, and architect workflows.
  • Architect safe-resume and archive-and-start-new launch modes.
  • Command-level, network-free Zsh regression tests.
  • Dedicated installation, integration, architecture, task, and troubleshooting documentation.
  • Memory-aware Matt Pocock routing as the default workflow.
  • Stable committed .agentmemory-project identity shared by Claude and Codex.
  • AgentMemory server and Claude/Codex plugin preflight with explicit degraded-mode approval.
  • Mandatory project recall and one canonical workflow_status checkpoint in standard and architect workflows.

Changed

  • Plan-build-specific implementation and documentation now belong to the dedicated plan-build gist rather than the Zsh Setup repository.
  • --yolo is translated to Claude Code's --dangerously-skip-permissions argument.
  • Active workflow documentation no longer describes removed v2 or distribution modes.
  • Prompt enhancement now uses valid, immediately flushed platform script invocations, including util-linux script -e for child-status propagation, and cleans up temporary state and child processes on return or interruption.
  • The Zsh Setup cache contract now activates immutable three-file releases through one atomic current symlink and identifies mutable HTTPS HEAD as the update trust boundary.
  • Standard planning now follows Matt Pocock's grilling, specification, tracer-ticket, TDD, diagnosis, and wayfinding flows.
  • Matt implementation commits are deferred until working-tree review, validation, and explicit user approval.
  • Architect mode recalls and reconciles previous state before document-based resume detection and passes the same memory identity to Codex.

Removed

  • Dependence on ~/.func and ambient shell functions.
  • The obsolete v2 downloader and its former workflow variants.
  • The --brainstorm and --writing-plan options and Claude Superpowers dependency.
README.md Originalformat

plan-build

plan-build is a standalone Zsh launcher for a memory-aware multi-agent engineering workflow. Claude Code follows Matt Pocock's discovery, specification, ticketing, TDD, and review flows. AgentMemory restores the active project case and related history across fresh Claude and Codex sessions. Codex and CodeRabbit provide independent review. Architect mode keeps Claude documentation-only while Codex performs approved implementation tasks.

Prerequisites

  • Zsh
  • Git and a checked-out Git worktree
  • Claude Code CLI (claude)
  • OpenAI Codex CLI (codex)
  • CodeRabbit CLI (coderabbit)
  • AgentMemory CLI and a running AgentMemory server
  • Enabled Claude Code plugins mattpocock-skills@mattpocock and agentmemory@agentmemory
  • Enabled Codex plugin agentmemory@agentmemory
  • The installed plan-build skills described below

Claude Code safe mode must be disabled because it disables both required plugins. All modes require an interactive terminal. --prompt additionally requires Auggie (auggie), an authenticated ~/.augment/session.json, Perl, and the platform script utility.

Agent Setup

Start and connect AgentMemory according to its current installation guide. The core wiring is:

agentmemory
agentmemory connect claude-code
codex plugin marketplace add rohitg00/agentmemory
codex plugin add agentmemory@agentmemory

Install and enable the AgentMemory and Matt Pocock plugins in Claude Code. Verify the shared server before using plan-build:

agentmemory status
claude plugin list
codex plugin list

No LLM provider is required for continuity. AgentMemory's local embeddings, keyword retrieval, automatic hooks, explicit recall gate, and project-scoped status slot work without LLM compression.

Plan-Build Installation

Install the executable somewhere on PATH:

mkdir -p "$HOME/.local/bin"
curl -fsSL \
  https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/plan_build.zsh \
  -o "$HOME/.local/bin/plan_build"
chmod +x "$HOME/.local/bin/plan_build"

Install both plan-build skills:

mkdir -p \
  "$HOME/.claude/skills/plan-build" \
  "$HOME/.claude/skills/plan-build-architect"
curl -fsSL \
  https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/SKILL.md \
  -o "$HOME/.claude/skills/plan-build/SKILL.md"
curl -fsSL \
  https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/ARCHITECT.md \
  -o "$HOME/.claude/skills/plan-build-architect/SKILL.md"

For production automation, download to a temporary file in the destination directory and rename it atomically after successful validation.

Project Identity

Every target repository must commit a .agentmemory-project file containing one stable identifier. The exact grammar is [A-Za-z0-9][A-Za-z0-9._:/-]{1,127}: 2-128 characters with no whitespace. Use the normalized remote repository identity when possible:

github.com/owner/repository

For a repository without a durable remote, use a stable UUID-based value such as local/550e8400-e29b-41d4-a716-446655440000.

On the first interactive run, plan-build proposes the normalized origin URL and creates .agentmemory-project after approval. That setup run then stops: commit the file and rerun plan-build. Directory names are deliberately not used because unrelated repositories can share the same basename. A working-tree identity that differs from HEAD is rejected.

The launcher exports the ID as AGENTMEMORY_PROJECT_NAME and enables context injection for Claude except in explicitly degraded mode. Codex inherits the same environment, so both agents use one memory scope across clones and worktrees.

Usage

Run the command in the project to change, enter the payload, then put EOF alone on a line:

plan_build
Implement pagination for the audit log.
Preserve existing API compatibility.
EOF

Available modes:

plan_build                     Memory-aware Matt workflow
plan_build --prompt            Auggie enhancement, approval, then Matt workflow
plan_build --yolo              Permissive Claude process mode; gates remain active
plan_build --architect         Memory-aware architect safe resume
plan_build --architect --new   Archive active documents and start new state
plan_build --architect --yolo  Architect with permissive Claude process mode

--architect may combine only with --new and --yolo; --new is invalid without --architect. Duplicate and unknown flags fail. Removed --brainstorm, --writing-plan, and --v2 options are intentionally unknown.

The user-facing --yolo option translates to Claude Code's --dangerously-skip-permissions. It never bypasses memory, planning, review, or commit approval gates.

Workflow

Except in explicitly degraded mode, every session starts by loading the project-scoped workflow_status slot and retrieving related decisions, bugs, lessons, and file history. Claude reconciles this memory with Git, the current issue or specification, CONTEXT.md, and ADRs before acting.

The default Matt route is:

  1. Ordinary ideas enter /mattpocock-skills:grill-with-docs.
  2. Small approved work continues through /mattpocock-skills:implement and TDD in the same context.
  3. Multi-session work uses /mattpocock-skills:to-spec, then /mattpocock-skills:to-tickets.
  4. Each unblocked ticket starts in a fresh plan_build session and recovers its case through AgentMemory.
  5. Hard bugs use /mattpocock-skills:diagnosing-bugs; huge foggy efforts use /mattpocock-skills:wayfinder.
  6. Matt two-axis review, Codex review, CodeRabbit, and complete validation run before an approval-gated commit.

Matt's workflow entry skills require explicit invocation. Claude tells the user the exact namespaced command and waits rather than silently approximating it. The standard workflow overrides Matt /implement's automatic commit instruction: plan-build commits only after explicit approval and never pushes automatically.

Memory Availability

AgentMemory captures prompts, tool activity, session boundaries, subagents, compaction, and commits automatically. Plan-build adds an explicit recall and checkpoint protocol because hooks alone fail silently when the server is unavailable.

If AgentMemory, its Claude plugin, or its Codex plugin fails preflight, plan-build asks whether to retry, continue in explicitly degraded memoryless mode, or stop. A non-interactive failure stops. Degraded mode is always reported and must never claim previous context was restored.

Memory supplements the repository; it does not replace specs, tickets, CONTEXT.md, ADRs, tests, or Git. Current approved artifacts win conflicts with old memory. Secrets, personal data, production data, and unverified hypotheses must not be explicitly saved.

Architect Mode

Architect mode recalls the previous case before detecting SPEC.md, TASKS.md, ADRs, or changelog state. Claude remains documentation-only and passes the same AgentMemory project ID and checkpoint summary to every Codex task.

--architect --new archives the active workflow documents and replaces the active status slot only after successful archival. Historical sessions and durable memories remain available but do not count as approval for the new requirement.

Zsh Setup Cache Launcher

The Zsh Setup integration downloads this complete release bundle:

https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/plan_build.zsh
https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/SKILL.md
https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/ARCHITECT.md

It stages all three non-empty files, requires plan_build.zsh to pass zsh -n, moves them into one immutable release directory, and atomically switches a serialized current symlink. Failed refreshes leave the previous validated release active. Both internal skill paths are bound to the selected release, so concurrent refreshes cannot mix generations.

The mutable HTTPS HEAD URL is the explicit update trust boundary. HTTPS protects transport but does not pin content, establish provenance, or guarantee that separate requests observed one remote revision.

Testing

The suite is self-contained and never accesses the network or launches real agent CLIs:

zsh -n plan_build.zsh test_plan_build.zsh
zsh test_plan_build.zsh
git diff --check

Troubleshooting

  • AgentMemory unavailable: run agentmemory status, start the server, and retry.
  • AgentMemory tools missing: confirm the Claude and Codex plugins are enabled and connected to the same server.
  • Matt skills missing: install or enable mattpocock-skills@mattpocock in Claude Code.
  • Safe mode blocks plugins: unset CLAUDE_CODE_SAFE_MODE.
  • Project ID rejected: keep .agentmemory-project to one valid 2-128 character identifier with no whitespace.
  • Auggie cannot authenticate: run auggie login and confirm ~/.augment/session.json is non-empty.
  • Prompt enhancement does not continue: --prompt requires approval for optional indexing and the enhanced prompt.
  • Git preflight fails: run from a checked-out worktree, not a bare repository or .git directory.
  • Workflow skill missing: install SKILL.md and ARCHITECT.md at the exact paths above.
SKILL.md Originalformat

Plan-Build Memory-Aware Matt Workflow

Use this workflow when plan_build hands Claude Code a project request. Matt Pocock's skills provide discovery, specification, ticketing, TDD, and review. AgentMemory restores prior project context across Claude and Codex sessions. Codex and CodeRabbit remain independent reviewers.

Non-Negotiable Rules

  • Run from the project root and preserve all pre-existing work.
  • Treat Git, the approved issue or specification, CONTEXT.md, and ADRs as authoritative. Memory supplements them and never overrides contradictory current evidence.
  • Use the AGENTMEMORY_PROJECT_NAME supplied by the launcher for every memory operation and child Codex process.
  • Do not expose or save credentials, tokens, personal data, or production secrets.
  • Matt entry skills marked disable-model-invocation require explicit user invocation. Tell the user the exact namespaced slash command and wait for it instead of simulating the skill.
  • Override /implement's automatic commit instruction. Keep changes uncommitted until review and validation pass and the user explicitly approves the commit. Never push automatically.

Memory Precedence

Resolve conflicts in this order:

  1. Current Git state and the approved issue or specification.
  2. Current repository documentation, CONTEXT.md, and ADRs.
  3. The project-scoped workflow_status slot.
  4. Verified durable memories and lessons.
  5. Raw historical observations.

Report conflicts and correct stale memory. Never bend current implementation or requirements to match an old observation.

Mandatory Recall Gate

Run this gate before routing the request, asking discovery questions, or modifying files. Initialize a session-local memory mode from PLAN_BUILD_MEMORY_MODE, accepting only required or degraded. Treat an unset or invalid value as required and fail closed if mandatory recall cannot run. Only a launcher-supplied degraded value or an explicit user approval after a later memory failure may set the local mode to degraded and permit skipping memory calls.

  1. Confirm the current project matches AGENTMEMORY_PROJECT_NAME and read .agentmemory-project.
  2. Read the project-scoped workflow_status slot with memory_slot_get. If it does not exist, create it with project scope, a 4,000-character limit, and the template below.
  3. Redact the request before search. Query only sanitized issue or ticket identifiers and non-sensitive domain terms; remove or reject credentials, tokens, personal data, production data, and other sensitive payload values. Search for related prior bugs, decisions, and lessons, and reject results belonging to another project.
  4. After likely files are known, use file history to recover prior changes and gotchas for those files.
  5. Verify high-impact memories before relying on them. Never invent context when retrieval is empty.
  6. Reconcile recalled state with Git, the tracker, CONTEXT.md, ADRs, and current documentation.
  7. Tell the user what previous case was loaded: active work, last completed milestone, unresolved decision or blocker, and recorded next step.

Use this slot shape and replace it at milestones rather than appending an unlimited log:

Phase: <discovery|specification|ticketing|implementation|review|blocked|complete>
Active work: <title and stable issue/spec reference>
Completed: <latest completed milestone>
In flight: <current operation>
Blocked: <blocker or None>
Pending decisions: <decisions or None>
Relevant files: <paths or Unknown>
Last verified: <commands and result or Not run>
Next step: <one concrete action>
Updated: <ISO-8601 timestamp>

When AgentMemory is healthy but no prior state exists, say so and initialize the slot. If any required memory call fails after launcher preflight, ask the user whether to retry, continue this session in explicitly degraded mode, or stop. On approval, record the session-local mode as degraded, skip remaining memory calls, and report the loss of continuity. Do not continue memoryless without that approval and never claim previous context was loaded.

Route Through Matt

After recall, route the request using Matt's /ask-matt model:

Request Entry skill
Ordinary feature or idea /mattpocock-skills:grill-with-docs
Approved specification or ready ticket /mattpocock-skills:implement
Difficult, intermittent, or unclear bug /mattpocock-skills:diagnosing-bugs
Huge and foggy multi-session effort /mattpocock-skills:wayfinder
Unrefined incoming external issue /mattpocock-skills:triage
Codebase-health exploration /mattpocock-skills:improve-codebase-architecture

Do not triage tickets produced by /mattpocock-skills:to-tickets; they are already agent-ready.

Feature Flow

For an ordinary idea:

  1. Ask the user to invoke /mattpocock-skills:grill-with-docs with the payload.
  2. Resolve repository facts locally and ask one decision at a time with a recommended answer.
  3. Use /mattpocock-skills:research for external facts.
  4. For a runnable design question, use /mattpocock-skills:handoff, continue in a fresh prototype session, invoke /mattpocock-skills:prototype, then hand the learned decision back. Do not confuse Matt's file handoff with /agentmemory:handoff, which resumes recorded sessions.
  5. Do not implement until the user confirms shared understanding.
  6. Update workflow_status after shared understanding and after every later approval gate.

If the work fits one context window, agree on public testing seams, obtain a read-only Codex review of the requirements and seams, then ask the user to invoke /mattpocock-skills:implement in the same session.

If the work needs multiple sessions:

  1. Ask the user to invoke /mattpocock-skills:to-spec.
  2. Confirm the proposed public testing seams before publishing.
  3. Ask the user to invoke /mattpocock-skills:to-tickets.
  4. Obtain approval for vertical tracer-bullet tickets and their blocking edges.
  5. Run a read-only Codex review of the approved specification and tickets. Resolve valid findings and reapprove material scope changes.
  6. Record the specification, ticket frontier, and first unblocked ticket in workflow_status, then stop.
  7. Start each unblocked ticket in a fresh plan_build invocation so it gets a clean context plus the mandatory recall gate.

Implementation Flow

For a ready ticket or approved small task:

  1. Record the baseline SHA, git status --short, and pre-existing diff.
  2. Load the full ticket or specification and verify dependency completion.
  3. Recall blocker outcomes, relevant file history, durable decisions, and lessons.
  4. Confirm public testing seams with the user before writing tests.
  5. Follow /mattpocock-skills:implement and /mattpocock-skills:tdd one red-green vertical slice at a time.
  6. Run focused tests and type checking regularly; run the full project validation suite at the end.
  7. Update workflow_status when a red test is established, implementation turns green, focused validation passes, full validation passes, review begins, or work becomes blocked.
  8. Do not commit when the Matt implementation skill requests it. Continue through plan-build review and explicit approval instead.

Every Codex prompt must include the project ID, active ticket or specification, and checkpoint summary. Require Codex to recall the same project independently and to treat current repository evidence as authoritative. Read-only review prompts must prohibit edits and durable saves of speculative findings.

Review Stack

Review only the intended change against its captured baseline. Capture the startup patch, then use a three-way, patch-aware comparison between HEAD, that baseline, and the current staged, unstaged, and intended untracked files. Preserve and exclude unrelated baseline changes throughout review, approval, and staging. If intended and pre-existing edits overlap in a file or hunk, stop and ask the user instead of subtracting or guessing.

  1. Run Matt's two axes in parallel against that filtered intended change: repository Standards and originating Spec. The stock /mattpocock-skills:code-review only compares committed HEAD history, so apply its standards and spec briefs directly to the filtered working tree before the approval commit.
  2. Ask Codex for an independent review focused on bugs, regressions, unsafe assumptions, missing tests, and repository fit.
  3. Run CodeRabbit on the local change. Investigate every concrete finding.
  4. Fix valid findings and repeat affected reviews after substantive changes.
  5. Rerun focused validation and the complete suite.
  6. Reconstruct the filtered change and confirm final staging contains only approved work, preserves every baseline change, and has no secret exposure.
  7. Present the diff summary, validation evidence, known limitations, and proposed commit message.
  8. Wait for explicit approval, stage only intended files, create one commit, and do not push.

Durable Memory Writes

Search before saving and store one durable idea at a time with the project ID, rationale, real file paths where relevant, and specific concept tags.

Save durable memory for:

  • Approved architecture decisions and rejected alternatives.
  • Non-obvious constraints and important module relationships.
  • Repeated bugs with verified root causes and fixes.
  • Deployment, migration, integration, and external-system gotchas.
  • Durable user or team preferences.

Save reusable lessons separately. Do not save routine output, temporary progress outside workflow_status, unverified hypotheses, generated content, or secrets.

Before ending any session, update workflow_status with what is done, in flight, blocked or unverified, and exactly one next step. Automatic hooks capture raw activity; this explicit checkpoint is what makes the next case resumable.

SPEC.md Originalformat

Plan-Build Specification

Purpose

Plan-build is a self-contained Zsh launcher for memory-aware Claude Code engineering workflows. Matt Pocock's skills define discovery through delivery, AgentMemory provides project continuity across Claude and Codex sessions, Codex performs independent review or architect-dispatched implementation, and CodeRabbit reviews local changes. This repository is canonical for the executable, both plan-build skills, command tests, and documentation.

Public Interface

plan_build [--yolo] [--prompt]
plan_build --architect [--new] [--yolo]

The executable reads standard input until a line exactly equal to EOF. Empty payloads, duplicate flags, and unknown flags fail. --brainstorm, --writing-plan, and --v2 are intentionally unknown.

  • Default mode uses the memory-aware Matt workflow.
  • --prompt enhances the payload through Auggie and requires interactive approval before Claude launches.
  • --yolo translates to --dangerously-skip-permissions without bypassing workflow gates.
  • --architect keeps Claude documentation-only and makes Codex the implementation executor.
  • --architect --new archives active workflow documents before starting new state.

--architect may combine only with --new and --yolo.

Common Preflight

All modes require an interactive terminal, a normal Git worktree, Claude, Codex, CodeRabbit, Git, AgentMemory, and a readable non-empty selected workflow skill. Claude safe mode is rejected.

Default mode additionally requires the enabled Claude plugin mattpocock-skills@mattpocock. Every mode checks the AgentMemory server and enabled agentmemory@agentmemory plugins for Claude and Codex.

When memory preflight fails, an interactive user may retry, explicitly approve degraded memoryless mode, or stop. Non-interactive memory failure stops. Other preflight failures are not degradable.

Stable Memory Identity

Every target worktree uses a committed .agentmemory-project containing one stable 2-128 character identifier. Its exact grammar is [A-Za-z0-9][A-Za-z0-9._:/-]{1,127}; whitespace is forbidden. On first interactive use, the launcher proposes a normalized origin identity or asks for an explicit ID, writes the file after approval, and stops. A later invocation proceeds only when the file exists in HEAD and its working-tree value matches the committed value.

The launcher exports:

AGENTMEMORY_PROJECT_NAME=<committed-id>
AGENTMEMORY_INJECT_CONTEXT=<true unless degraded>
PLAN_BUILD_MEMORY_MODE=<required|degraded>

Claude and inherited Codex processes therefore share one scope across worktrees, clones, and machines.

Mandatory Recall And Checkpoint

When memory is available, before routing, discovery, workflow detection, or modification, each skill reads or creates one project-scoped workflow_status slot, retrieves related decisions, bugs, lessons, and file history, and reconciles them with current Git and approved artifacts.

In explicitly approved degraded mode, the skill skips memory calls, reports that recall and checkpoint persistence are unavailable, proceeds only from current repository evidence, and never claims previous context was restored. A later memory failure requires the same retry, explicitly degrade, or stop choice.

The slot records phase, active work and source, completed milestone, in-flight work, blockers, pending decisions, relevant files, last verification, one next step, and update time. It is replaced at meaningful milestones and before session end. Durable decisions and verified fixes are saved separately; routine output, secrets, personal data, generated content, and unverified hypotheses are not.

Authority order is current Git and approved issue/spec, repository documentation and ADRs, active status slot, verified durable memory, then raw observations.

Matt Workflow

The standard skill routes ordinary ideas to grilling, approved tickets to implementation, hard bugs to diagnosis, huge foggy efforts to wayfinding, incoming external issues to triage, and codebase health requests to architecture improvement.

Matt entry skills requiring explicit user invocation are never silently simulated. Small approved work remains in the discovery context. Multi-session work creates an approved spec and tracer-bullet tickets, then stops; every unblocked ticket starts in a fresh plan-build invocation.

Implementation uses pre-agreed public test seams and red-green vertical slices. Matt's automatic commit instruction is overridden. The uncommitted working tree receives Matt-equivalent Standards and Spec review, Codex review, CodeRabbit review, and complete validation before the user approves one commit. Plan-build never pushes automatically.

Architect Mode

Architect mode runs memory recall before existing-state detection. Claude may modify only its documented Markdown scope. Codex receives the project ID, task/spec references, and compact checkpoint, recalls relevant history independently, and remains prohibited from commits or out-of-scope edits.

Archive-and-start-new preserves historical memories but replaces the active slot after successful document archival. Historical memory is context, not approval for the new requirement.

Installed Skills

~/.claude/skills/plan-build/SKILL.md
~/.claude/skills/plan-build-architect/SKILL.md

Canonical sources are SKILL.md and ARCHITECT.md.

Standalone Constraints

  • Support Zsh on macOS, Ubuntu, and WSL.
  • Do not source user shell configuration.
  • Keep helpers in the _plan_build_ namespace.
  • Keep external command and interaction boundaries replaceable.
  • Keep tests network-free and prevent real agent launches.
  • Remain safely sourceable and run main only when executed directly.
  • Preserve the three-file immutable cache release contract.

Acceptance Criteria

  • Default, prompt-enhanced, permissive, architect resume, and architect-new modes have command coverage.
  • Removed options, invalid combinations, duplicates, and empty payloads are covered.
  • Stable project IDs are validated and reach Claude's environment.
  • AgentMemory success, degraded approval, and rejection paths are covered without network access.
  • Recall requirements appear in standard and architect launch prompts.
  • Common preflight happens before payload input.
  • Prompt enhancement cannot launch Claude without approval.
  • --yolo reaches Claude only as --dangerously-skip-permissions.
  • Syntax checks, command tests, and git diff --check pass.
TASKS.md Originalformat

Plan-Build Tasks

Completed

PB-001: Establish the dedicated project boundary

  • Extract the executable from Zsh Setup into plan_build.zsh.
  • Remove dependencies on ~/.func and unrelated shell helpers.
  • Make the executable directly runnable and safely sourceable.

PB-002: Preserve supported workflows

  • Preserve standard and prompt-enhancement behavior.
  • Preserve architect safe-resume and archive-and-start-new modes.
  • Preserve EOF-terminated payload input and interactive enhanced-prompt approval.
  • Translate --yolo to Claude Code's real --dangerously-skip-permissions option.
  • Keep --v2 rejected through the unknown-option path.

PB-003: Canonicalize skills and documentation

  • Publish the standard workflow as SKILL.md.
  • Publish the architect workflow as ARCHITECT.md.
  • Remove obsolete v2-only and distribution workflow claims from the active standard skill.
  • Document installation, prerequisites, cache integration, compatibility, testing, and troubleshooting.

PB-004: Add standalone regression coverage

  • Stub external CLIs, Claude launch, Auggie enhancement, and interactive approval.
  • Cover all modes, invalid combinations, preflight ordering, safe-resume/new architect prompts, and normal versus bare Git repositories.
  • Keep the suite network-free.

PB-005: Replace Superpowers planning with Matt Pocock's workflow

  • Make Matt routing the default standard workflow.
  • Remove --brainstorm, --writing-plan, and the Superpowers dependency.
  • Preserve Auggie prompt enhancement and architect modes.
  • Route discovery, specifications, tracer-bullet tickets, TDD, diagnosis, and wayfinding through explicit namespaced Matt skills.
  • Override automatic commits with review, validation, and explicit approval.

PB-006: Add AgentMemory continuity

  • Require a committed stable .agentmemory-project identity.
  • Verify the shared AgentMemory server and Claude/Codex plugins before payload input.
  • Allow only an explicitly approved interactive degraded mode when memory is unavailable.
  • Pass one memory scope through Claude and inherited Codex processes.
  • Require project-scoped recall and one canonical workflow_status checkpoint in both standard and architect skills.
  • Add network-free tests for project identity, memory preflight outcomes, recall prompts, and child environment propagation.

Completed outside this repository

ZS-001: Migrate the Zsh Setup launcher

Replace the old in-repository implementation with a thin cached launcher that downloads the canonical executable and skills from the plan-build gist. The Zsh Setup migration now uses immutable complete release directories, a serialized atomic current symlink switch, and skill links through that same release.

Required launcher contract:

zsh <selected-release>/plan_build.zsh "$@"

Required remote files:

https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/plan_build.zsh
https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/SKILL.md
https://opengist.resetrix.work/weehong/plan-build/raw/HEAD/ARCHITECT.md
plan_build.zsh Originalformat
1#!/usr/bin/env zsh
2
3# Standalone plan-build launcher. This file is intentionally sourceable so its
4# command seams can be replaced by the test suite.
5
6_plan_build_usage() {
7 print -r -- "Usage: plan_build [--yolo] [--prompt]
8 plan_build --architect [--new] [--yolo]"
9}
10
11_plan_build_require_cli() {
12 local binary="$1"
13 local label="$2"
14 local resolved
15
16 resolved="$(command -v "$binary" 2>/dev/null)" || resolved=""
17 if [[ -n "$resolved" && -x "$resolved" ]]; then
18 return 0
19 fi
20
21 print -u2 -r -- "Error: ${label} ('${binary}') is not installed or not in your PATH."
22 return 1
23}
24
25_plan_build_confirm_indexing() {
26 local project_root="$1"
27 local reply
28
29 if ! (: </dev/tty) 2>/dev/null; then
30 print -u2 -r -- "Notice: No interactive terminal available; enhancing without project indexing."
31 return 1
32 fi
33
34 printf "Allow Auggie to index and use project context from '%s'? (y/N) " "$project_root" >/dev/tty
35 if ! IFS= read -r reply </dev/tty; then
36 print -u2 -r -- "\nNotice: Unable to read confirmation; enhancing without project indexing."
37 return 1
38 fi
39
40 [[ "$reply" == (y|Y|yes|YES|Yes) ]]
41}
42
43_plan_build_parse_auggie_output() {
44 local log_file="$1"
45 local output_file="$2"
46
47 perl -ne '
48 s/\r$//;
49 s/.*\r//;
50 1 while s/[^\x08]\x08//g;
51 s/\x08//g;
52 s/\e\][^\a]*(?:\a|\e\\)//g;
53 s/\e\[[0-?]*[ -\/]*[@-~]//g;
54 next if /Script started on/ || /Script done on/;
55 if (/^(?:✨\s*)?Enhanced prompt:\s*(.*)$/) {
56 $capturing = 1;
57 $output .= "$1\n" if length $1;
58 next;
59 }
60 next unless $capturing;
61 exit if /^🤖/ || /Tool call:/ || /Session terminated/;
62 $output .= $_;
63 END {
64 $output =~ s/^\s*\n//;
65 $output =~ s/\s+\z//;
66 print "$output\n" if length $output;
67 }
68 ' "$log_file" >| "$output_file"
69}
70
71_plan_build_platform() {
72 command uname -s
73}
74
75_plan_build_start_auggie_script() {
76 local platform="$1" log_file="$2" workspace="$3" cache_dir="$4"
77 local auth_file="$5" prompt_file="$6" use_project_context="$7"
78 shift 7
79
80 if [[ "$platform" == Darwin ]]; then
81 command script -q -t 0 "$log_file" auggie "$@" </dev/null >/dev/null 2>&1 &
82 else
83 AUGGIE_WORKSPACE="$workspace" AUGGIE_CACHE_DIR="$cache_dir" \
84 AUGGIE_AUTH_FILE="$auth_file" AUGGIE_PROMPT_FILE="$prompt_file" \
85 AUGGIE_INDEXING="$use_project_context" \
86 command script -q -f -e -O "$log_file" -c '
87 if [ "$AUGGIE_INDEXING" = 1 ]; then
88 exec auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
89 else
90 exec auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
91 fi
92 ' </dev/null >/dev/null 2>&1 &
93 fi
94 REPLY=$!
95}
96
97_plan_build_enhance_prompt() {
98 emulate -L zsh
99 setopt localtraps
100 local prompt="$1"
101 local output_file="$2"
102 local run_dir prompt_file workspace cache_dir auth_file log_file parsed_file
103 local project_root use_project_context timeout_seconds script_pid= waited child_status=0
104 local -a auggie_args
105
106 trap 'return 130' INT
107 trap 'return 143' TERM
108 trap 'return 129' HUP
109
110 if [[ -z "$prompt" ]]; then
111 print -u2 -r -- "Error: Prompt was empty."
112 return 1
113 fi
114 if [[ ! -s "$HOME/.augment/session.json" ]]; then
115 print -u2 -r -- "Error: Auggie session file not found. Run 'auggie login' first."
116 return 1
117 fi
118
119 run_dir="$(mktemp -d "${TMPDIR:-/tmp}/plan-build-auggie.XXXXXX")" || return 1
120 trap "rm -rf -- ${(q)run_dir}" EXIT
121 prompt_file="$run_dir/prompt.txt"
122 workspace="$run_dir/workspace"
123 cache_dir="$run_dir/cache"
124 auth_file="$HOME/.augment/session.json"
125 log_file="$run_dir/auggie.log"
126 parsed_file="$run_dir/enhanced.txt"
127 mkdir -p "$workspace" "$cache_dir" || {
128 return 1
129 }
130 print -r -- "$prompt" >| "$prompt_file" || return 1
131
132 project_root="$(command git rev-parse --show-toplevel 2>/dev/null)" || project_root="$PWD"
133 use_project_context=0
134 timeout_seconds=90
135 if _plan_build_confirm_indexing "$project_root"; then
136 use_project_context=1
137 timeout_seconds=300
138 workspace="$project_root"
139 cache_dir="$HOME/.augment"
140 print -u2 -r -- "Indexing approved; enhancing with project context from '${project_root}'."
141 else
142 print -u2 -r -- "Enhancing without project indexing."
143 fi
144
145 auggie_args=(--print --enhance-prompt --workspace-root "$workspace"
146 --augment-cache-dir "$cache_dir" --augment-session-json "$auth_file"
147 --dont-save-session --instruction-file "$prompt_file")
148 if (( use_project_context )); then
149 auggie_args+=(--allow-indexing --wait-for-indexing)
150 else
151 auggie_args+=(--no-discover-workspaces)
152 fi
153
154 _plan_build_start_auggie_script "$(_plan_build_platform)" "$log_file" \
155 "$workspace" "$cache_dir" "$auth_file" "$prompt_file" \
156 "$use_project_context" "${auggie_args[@]}" || return 1
157 script_pid="$REPLY"
158 trap "kill ${(q)script_pid} >/dev/null 2>&1
159 wait ${(q)script_pid} >/dev/null 2>&1
160 rm -rf -- ${(q)run_dir}" EXIT
161 waited=0
162 while kill -0 "$script_pid" >/dev/null 2>&1; do
163 if command grep -aq "🤖" "$log_file" 2>/dev/null ||
164 command grep -aq "Tool call:" "$log_file" 2>/dev/null; then
165 kill "$script_pid" >/dev/null 2>&1 || true
166 wait "$script_pid" >/dev/null 2>&1 || true
167 script_pid=
168 trap "rm -rf -- ${(q)run_dir}" EXIT
169 child_status=0
170 break
171 fi
172 if (( waited >= timeout_seconds )); then
173 kill "$script_pid" >/dev/null 2>&1 || true
174 wait "$script_pid" >/dev/null 2>&1 || true
175 script_pid=
176 trap "rm -rf -- ${(q)run_dir}" EXIT
177 print -u2 -r -- "Error: Timed out waiting for Auggie to enhance the prompt."
178 return 124
179 fi
180 sleep 1
181 waited=$((waited + 1))
182 done
183 if [[ -n "$script_pid" ]]; then
184 wait "$script_pid"
185 child_status=$?
186 script_pid=
187 trap "rm -rf -- ${(q)run_dir}" EXIT
188 fi
189 if (( child_status != 0 )); then
190 print -u2 -r -- "Error: Auggie process failed with status ${child_status}."
191 return "$child_status"
192 fi
193
194 _plan_build_parse_auggie_output "$log_file" "$parsed_file"
195 if [[ ! -s "$parsed_file" ]]; then
196 print -u2 -r -- "Error: Auggie did not return an enhanced prompt."
197 return 1
198 fi
199 command cp "$parsed_file" "$output_file" || {
200 print -u2 -r -- "Error: Unable to save the enhanced prompt."
201 return 1
202 }
203}
204
205_plan_build_confirm_enhanced_prompt() {
206 local reply
207
208 if ! (: </dev/tty) 2>/dev/null; then
209 print -r -- "❌ Error: Cannot review the enhanced prompt without an interactive terminal; Claude was not launched."
210 return 2
211 fi
212 printf "Proceed with this enhanced prompt? (y/N) " >/dev/tty
213 if ! IFS= read -r reply </dev/tty; then
214 printf '\n' >/dev/tty
215 print -r -- "🛑 Review cancelled; Claude was not launched."
216 return 2
217 fi
218 [[ "$reply" == (y|Y|yes|YES|Yes) ]]
219}
220
221_plan_build_claude_plugin_state() {
222 local plugin_id="$1"
223 awk -v plugin_id="$plugin_id" '
224 $0 ~ plugin_id {
225 found = 1
226 next
227 }
228 found && /Status:/ {
229 if ($0 ~ /enabled/) print "enabled"
230 else print "disabled"
231 printed = 1
232 exit
233 }
234 found && /❯/ {
235 print "installed"
236 printed = 1
237 exit
238 }
239 END { if (!printed) print found ? "installed" : "missing" }
240 '
241}
242
243_plan_build_safe_mode_preflight() {
244 case "${CLAUDE_CODE_SAFE_MODE:-}" in
245 1|true|TRUE|yes|YES|on|ON)
246 print -r -- "Error: Claude Code safe mode disables the Matt Pocock and AgentMemory plugins."
247 print -r -- "Unset CLAUDE_CODE_SAFE_MODE before using plan_build."
248 return 1
249 ;;
250 esac
251}
252
253_plan_build_matt_preflight() {
254 local plugin_json plugin_state
255
256 if ! plugin_json="$(command claude plugin list 2>/dev/null)"; then
257 print -r -- "Error: Unable to inspect Claude Code plugins."
258 print -r -- "Run 'claude plugin list' to diagnose the problem."
259 return 1
260 fi
261 plugin_state="$(print -r -- "$plugin_json" | _plan_build_claude_plugin_state \
262 "mattpocock-skills@mattpocock")"
263 case "$plugin_state" in
264 enabled) return 0 ;;
265 disabled)
266 print -r -- "Error: Matt Pocock skills are installed in Claude Code but disabled."
267 print -r -- "Enable the mattpocock-skills@mattpocock plugin, then retry."
268 ;;
269 missing)
270 print -r -- "Error: Matt Pocock skills are required for the default workflow."
271 print -r -- "Install the mattpocock-skills@mattpocock Claude Code plugin, then retry."
272 ;;
273 *)
274 print -r -- "Error: Unable to determine Matt Pocock plugin status."
275 print -r -- "Run 'claude plugin list' to diagnose the problem."
276 ;;
277 esac
278 return 1
279}
280
281_plan_build_agentmemory_health() {
282 local pid exit_status waited=0
283 command -v agentmemory >/dev/null 2>&1 || return 2
284 command agentmemory status >/dev/null 2>&1 &
285 pid=$!
286 while kill -0 "$pid" >/dev/null 2>&1; do
287 if (( waited >= 10 )); then
288 kill "$pid" >/dev/null 2>&1 || true
289 wait "$pid" >/dev/null 2>&1 || true
290 return 124
291 fi
292 sleep 1
293 waited=$((waited + 1))
294 done
295 wait "$pid"
296 exit_status=$?
297 return "$exit_status"
298}
299
300_plan_build_claude_agentmemory_state() {
301 local plugin_json
302 plugin_json="$(command claude plugin list 2>/dev/null)" || return 1
303 print -r -- "$plugin_json" | _plan_build_claude_plugin_state \
304 "agentmemory@agentmemory"
305}
306
307_plan_build_codex_agentmemory_state() {
308 local plugin_list
309 plugin_list="$(command codex plugin list 2>/dev/null)" || return 1
310 print -r -- "$plugin_list" | _plan_build_codex_plugin_state
311}
312
313_plan_build_codex_plugin_state() {
314 awk '
315 $1 == "agentmemory@agentmemory" {
316 if ($0 ~ /installed, enabled/) print "enabled"
317 else print "disabled"
318 found = 1
319 exit
320 }
321 END { if (!found) print "missing" }
322 '
323}
324
325_plan_build_agentmemory_check() {
326 local claude_state codex_state failed=0 health_status
327
328 _plan_build_agentmemory_health
329 health_status=$?
330 case "$health_status" in
331 0) ;;
332 2)
333 print -r -- "AgentMemory CLI is not installed or not in PATH."
334 print -r -- "Install @agentmemory/agentmemory, then retry."
335 failed=1
336 ;;
337 124)
338 print -r -- "AgentMemory status check timed out after 10 seconds."
339 failed=1
340 ;;
341 *)
342 print -r -- "AgentMemory server is unavailable."
343 failed=1
344 ;;
345 esac
346 claude_state="$(_plan_build_claude_agentmemory_state)" || claude_state="unknown"
347 if [[ "$claude_state" != enabled ]]; then
348 print -r -- "Claude Code AgentMemory plugin state: $claude_state."
349 failed=1
350 fi
351 codex_state="$(_plan_build_codex_agentmemory_state)" || codex_state="unknown"
352 if [[ "$codex_state" != enabled ]]; then
353 print -r -- "Codex AgentMemory plugin state: $codex_state."
354 failed=1
355 fi
356
357 (( failed == 0 ))
358}
359
360_plan_build_confirm_memory_action() {
361 local reply
362
363 if ! _plan_build_has_tty; then
364 print -r -- "Error: AgentMemory preflight failed without an interactive terminal."
365 return 1
366 fi
367 printf "AgentMemory preflight failed. [r]etry, [c]ontinue without memory, or [s]top? " >/dev/tty
368 if ! IFS= read -r reply </dev/tty; then
369 return 1
370 fi
371 _plan_build_memory_action_from_reply "$reply"
372}
373
374_plan_build_memory_action_from_reply() {
375 local reply="$1"
376 case "$reply" in
377 r|R|retry|Retry|RETRY) return 2 ;;
378 c|C|continue|Continue|CONTINUE) return 0 ;;
379 *) return 1 ;;
380 esac
381}
382
383_plan_build_agentmemory_preflight() {
384 local action_status
385
386 while ! _plan_build_agentmemory_check; do
387 _plan_build_confirm_memory_action
388 action_status=$?
389 if (( action_status == 2 )); then
390 continue
391 elif (( action_status == 0 )); then
392 print -r -- "Warning: Continuing in explicitly approved memoryless mode."
393 REPLY="degraded"
394 return 0
395 fi
396 print -r -- "Memory preflight was not approved; Claude was not launched."
397 return 1
398 done
399 REPLY="required"
400}
401
402_plan_build_project_root() {
403 command git rev-parse --show-toplevel 2>/dev/null
404}
405
406_plan_build_project_id_is_valid() {
407 [[ "$1" =~ '^[A-Za-z0-9][A-Za-z0-9._:/-]{1,127}$' ]]
408}
409
410_plan_build_default_project_id() {
411 local root="$1" remote is_url=0
412 remote="$(command git -C "$root" remote get-url origin 2>/dev/null)" || return 1
413 [[ "$remote" == *://* ]] && is_url=1
414 remote="${remote#*://}"
415 remote="${remote#*@}"
416 if (( ! is_url )) && [[ "$remote" == *:* ]]; then
417 remote="${remote%%:*}/${remote#*:}"
418 fi
419 remote="${remote%.git}"
420 [[ -n "$remote" ]] || return 1
421 print -r -- "$remote"
422}
423
424_plan_build_initialize_project_id() {
425 local root="$1" candidate reply
426
427 if ! _plan_build_has_tty; then
428 print -r -- "Error: Missing $root/.agentmemory-project and no interactive terminal is available."
429 return 1
430 fi
431 candidate="$(_plan_build_default_project_id "$root")" || candidate=""
432 if [[ -n "$candidate" ]] && ! _plan_build_project_id_is_valid "$candidate"; then
433 candidate=""
434 fi
435 if [[ -n "$candidate" ]]; then
436 printf "Create .agentmemory-project with ID '%s'? (Y/n) " "$candidate" >/dev/tty
437 if ! IFS= read -r reply </dev/tty; then
438 return 1
439 fi
440 case "$reply" in
441 n|N|no|No|NO) candidate="" ;;
442 esac
443 fi
444 if [[ -z "$candidate" ]]; then
445 printf "Enter a stable AgentMemory project ID: " >/dev/tty
446 if ! IFS= read -r candidate </dev/tty; then
447 return 1
448 fi
449 fi
450 if ! _plan_build_project_id_is_valid "$candidate"; then
451 print -r -- "Error: Project ID must be 2-128 characters using letters, numbers, '.', '_', ':', '/', or '-'."
452 return 1
453 fi
454 print -r -- "$candidate" >| "$root/.agentmemory-project" || return 1
455 print -r -- "Created $root/.agentmemory-project. Commit it, then rerun plan_build."
456 return 1
457}
458
459_plan_build_resolve_project_id() {
460 local root project_file project_id committed_id
461 root="$(_plan_build_project_root)" || return 1
462 project_file="$root/.agentmemory-project"
463 if [[ ! -e "$project_file" ]]; then
464 _plan_build_initialize_project_id "$root"
465 return $?
466 fi
467 if [[ ! -f "$project_file" || ! -r "$project_file" ]]; then
468 print -r -- "Error: AgentMemory project ID file is not a readable regular file: $project_file"
469 return 1
470 fi
471 project_id="$(<"$project_file")"
472 if ! _plan_build_project_id_is_valid "$project_id"; then
473 print -r -- "Error: Invalid AgentMemory project ID in $project_file"
474 return 1
475 fi
476 committed_id="$(command git -C "$root" show HEAD:.agentmemory-project 2>/dev/null)" || {
477 print -r -- "Error: .agentmemory-project must be committed before plan_build can use it."
478 return 1
479 }
480 if [[ "$project_id" != "$committed_id" ]]; then
481 print -r -- "Error: Working-tree .agentmemory-project differs from the committed identity."
482 return 1
483 fi
484 REPLY="$project_id"
485}
486
487_plan_build_is_worktree() {
488 local inside_work_tree
489 inside_work_tree="$(command git rev-parse --is-inside-work-tree 2>/dev/null)" || return 1
490 [[ "$inside_work_tree" == true ]]
491}
492
493_plan_build_has_tty() {
494 (: </dev/tty) 2>/dev/null
495}
496
497_plan_build_common_preflight() {
498 local skill_path="$1" require_matt="$2"
499
500 if ! _plan_build_has_tty; then
501 print -r -- "Error: plan_build requires an interactive terminal."
502 return 1
503 fi
504 _plan_build_require_cli claude "Claude Code CLI" || return 1
505 _plan_build_require_cli codex "Codex CLI" || return 1
506 _plan_build_require_cli coderabbit "CodeRabbit CLI" || return 1
507 _plan_build_require_cli git "Git CLI" || return 1
508 if ! _plan_build_is_worktree; then
509 print -r -- "Error: plan_build must run inside a Git worktree."
510 print -r -- "Change to a checked-out Git worktree, then retry."
511 return 1
512 fi
513 if [[ ! -r "$skill_path" || ! -s "$skill_path" ]]; then
514 print -r -- "Error: Workflow skill is missing, unreadable, or empty: $skill_path"
515 return 1
516 fi
517 _plan_build_safe_mode_preflight || return 1
518 if (( require_matt )); then
519 _plan_build_matt_preflight || return 1
520 fi
521}
522
523_plan_build_launch_claude() {
524 local use_yolo="$1" project_id="$2" memory_mode="$3"
525 local inject_context="true"
526 shift 3
527 [[ "$memory_mode" == degraded ]] && inject_context="false"
528 if (( use_yolo )); then
529 AGENTMEMORY_PROJECT_NAME="$project_id" AGENTMEMORY_INJECT_CONTEXT="$inject_context" \
530 PLAN_BUILD_MEMORY_MODE="$memory_mode" \
531 command claude --dangerously-skip-permissions "$@"
532 else
533 AGENTMEMORY_PROJECT_NAME="$project_id" AGENTMEMORY_INJECT_CONTEXT="$inject_context" \
534 PLAN_BUILD_MEMORY_MODE="$memory_mode" command claude "$@"
535 fi
536}
537
538_plan_build_read_payload() {
539 local line payload=""
540 while IFS= read -r line; do
541 [[ "$line" == EOF ]] && break
542 if [[ -z "$payload" ]]; then
543 payload="$line"
544 else
545 payload+=$'\n'"$line"
546 fi
547 done
548 print -r -- "$payload"
549}
550
551plan_build() {
552 emulate -L zsh
553 setopt localtraps
554 local use_yolo=0 use_architect=0 use_new=0 enhance_payload=0
555 local payload enhanced_file= confirm_status enhance_status architect_start_mode
556 local project_id memory_mode
557 local standard_skill="${PLAN_BUILD_SKILL_PATH:-$HOME/.claude/skills/plan-build/SKILL.md}"
558 local architect_skill="${PLAN_BUILD_ARCHITECT_SKILL_PATH:-$HOME/.claude/skills/plan-build-architect/SKILL.md}"
559
560 trap 'return 130' INT
561 trap 'return 143' TERM
562 trap 'return 129' HUP
563
564 while (( $# )); do
565 case "$1" in
566 --yolo)
567 (( use_yolo )) && {
568 print -r -- "Error: Duplicate argument: --yolo"
569 _plan_build_usage
570 return 1
571 }
572 use_yolo=1
573 ;;
574 --architect)
575 (( use_architect )) && {
576 print -r -- "Error: Duplicate argument: --architect"
577 _plan_build_usage
578 return 1
579 }
580 use_architect=1
581 ;;
582 --new)
583 (( use_new )) && {
584 print -r -- "Error: Duplicate argument: --new"
585 _plan_build_usage
586 return 1
587 }
588 use_new=1
589 ;;
590 --prompt)
591 (( enhance_payload )) && {
592 print -r -- "Error: Duplicate argument: --prompt"
593 _plan_build_usage
594 return 1
595 }
596 enhance_payload=1
597 ;;
598 *)
599 print -r -- "Error: Unknown argument: $1"
600 _plan_build_usage
601 return 1
602 ;;
603 esac
604 shift
605 done
606
607 if (( use_new && ! use_architect )); then
608 print -r -- "Error: --new requires --architect."
609 _plan_build_usage
610 return 1
611 fi
612 if (( use_architect && enhance_payload )); then
613 print -r -- "Error: --architect may combine only with --new and --yolo."
614 _plan_build_usage
615 return 1
616 fi
617
618 if (( use_architect )); then
619 _plan_build_common_preflight "$architect_skill" 0 || return 1
620 else
621 _plan_build_common_preflight "$standard_skill" 1 || return 1
622 if (( enhance_payload )); then
623 _plan_build_require_cli auggie "Auggie CLI" || return 1
624 _plan_build_require_cli script "script utility" || return 1
625 _plan_build_require_cli perl "Perl" || return 1
626 fi
627 fi
628 _plan_build_resolve_project_id || return 1
629 project_id="$REPLY"
630 _plan_build_agentmemory_preflight || return 1
631 memory_mode="$REPLY"
632
633 print -r -- "📥 Reading payload... Type 'EOF' on a new line and press Enter when finished."
634 payload="$(_plan_build_read_payload)"
635 if [[ -z "$payload" ]]; then
636 print -r -- "❌ Error: Payload was empty."
637 return 1
638 fi
639
640 if (( enhance_payload )); then
641 enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1
642 trap "rm -f -- ${(q)enhanced_file}" EXIT
643 print -r -- "✨ Enhancing payload with Auggie..."
644 _plan_build_enhance_prompt "$payload" "$enhanced_file"
645 enhance_status=$?
646 if (( enhance_status != 0 )); then
647 print -r -- "❌ Error: Prompt enhancement failed; Claude was not launched."
648 return "$enhance_status"
649 fi
650 payload="$(<"$enhanced_file")"
651 rm -f -- "$enhanced_file"
652 enhanced_file=
653 trap - EXIT
654 if [[ -z "$payload" ]]; then
655 print -r -- "❌ Error: Enhanced payload was empty; Claude was not launched."
656 return 1
657 fi
658 printf '\n%s\n%s\n%s\n\n' \
659 "━━━━━━━━━━━━━━━━ Auggie enhanced prompt ━━━━━━━━━━━━━━━━" \
660 "$payload" \
661 "━━━━━━━━━━━━━━━━ End enhanced prompt ━━━━━━━━━━━━━━━━━"
662 _plan_build_confirm_enhanced_prompt
663 confirm_status=$?
664 if (( confirm_status == 2 )); then
665 return 1
666 elif (( confirm_status != 0 )); then
667 print -r -- "🛑 Enhanced prompt not approved; Claude was not launched."
668 return 0
669 fi
670 print -r -- "✅ Enhanced prompt approved."
671 fi
672
673 if (( use_architect )); then
674 if (( use_new )); then
675 architect_start_mode="Start mode: archive-and-start-new. Explicitly archive the prior planning state as the skill directs, then begin a new architecture plan."
676 else
677 architect_start_mode="Start mode: safe-resume-detection. Safely detect whether an existing architecture planning session should be resumed; do not archive or replace it automatically."
678 fi
679 print -r -- "🚀 Launching Claude Code in architect mode..."
680 _plan_build_launch_claude "$use_yolo" "$project_id" "$memory_mode" "Read \`$architect_skill\` and follow it strictly, including every gate even when permissive Claude execution is active. Stay in the documentation-first architect/orchestrator role: produce and coordinate documentation and planning only, and do not implement the requirement.
681
682AgentMemory project: $project_id
683Memory mode: $memory_mode. Run the skill's mandatory recall gate before workflow detection or repository modification. Pass this same project identity to every Codex process.
684
685$architect_start_mode
686
687Use the following payload as the initial requirement:
688
689$payload"
690 return $?
691 fi
692
693 print -r -- "🚀 Launching Claude Code with the memory-aware Matt workflow..."
694 _plan_build_launch_claude "$use_yolo" "$project_id" "$memory_mode" "Read \`$standard_skill\` and strictly follow its memory-aware Matt Pocock workflow.
695
696AgentMemory project: $project_id
697Memory mode: $memory_mode. Run the mandatory recall gate before routing or modifying the repository. Pass this same project identity to every Codex process.
698
699$payload"
700}
701
702_plan_build_main() {
703 plan_build "$@"
704}
705
706if [[ "${ZSH_EVAL_CONTEXT:-}" == toplevel ]]; then
707 _plan_build_main "$@"
708fi
709
test_plan_build.zsh Originalformat
1#!/usr/bin/env zsh
2
3set -u
4
5typeset -r repo_dir="${0:A:h}"
6source "$repo_dir/plan_build.zsh"
7
8typeset -gi failures=0
9functions[_plan_build_real_launch_claude]="${functions[_plan_build_launch_claude]}"
10functions[_plan_build_real_enhance_prompt]="${functions[_plan_build_enhance_prompt]}"
11functions[_plan_build_real_start_auggie_script]="${functions[_plan_build_start_auggie_script]}"
12functions[_plan_build_real_agentmemory_check]="${functions[_plan_build_agentmemory_check]}"
13
14fail() {
15 print -u2 -r -- "FAIL: $1"
16 failures=$((failures + 1))
17}
18
19assert_equal() {
20 local expected="$1" actual="$2" label="$3"
21 [[ "$actual" == "$expected" ]] || fail "$label (expected '$expected', got '$actual')"
22}
23
24assert_contains() {
25 local output="$1" expected="$2" label="$3"
26 [[ "$output" == *"$expected"* ]] || fail "$label (missing '$expected')"
27}
28
29assert_not_contains() {
30 local output="$1" unexpected="$2" label="$3"
31 [[ "$output" != *"$unexpected"* ]] || fail "$label (unexpected '$unexpected')"
32}
33
34run_plan() {
35 local args="$1" input="${2:-EOF\n}"
36 output="$(printf '%b' "$input" | plan_build ${(z)args} 2>&1)"
37 rc=$?
38}
39
40seam_events() {
41 print -r -- "$1" | sed -n 's/^SEAM://p' | paste -sd ' ' -
42}
43
44count_matches() {
45 local directory="$1" prefix="$2"
46 local -a matches
47 matches=("$directory"/"$prefix".*(N))
48 print -r -- "$#matches"
49}
50
51typeset fixture_dir
52fixture_dir="$(mktemp -d "${TMPDIR:-/tmp}/plan-build-tests.XXXXXX")" || exit 1
53trap 'rm -rf -- "$fixture_dir"' EXIT
54mkdir -p "$fixture_dir/tmp"
55export TMPDIR="$fixture_dir/tmp"
56
57command git init -q "$fixture_dir/worktree"
58command git init -q --bare "$fixture_dir/bare.git"
59
60(cd "$fixture_dir/worktree" && _plan_build_is_worktree)
61assert_equal 0 "$?" "normal Git worktree accepted"
62(cd "$fixture_dir/bare.git" && _plan_build_is_worktree)
63assert_equal 1 "$?" "bare Git repository rejected"
64(cd "$fixture_dir" && _plan_build_is_worktree)
65assert_equal 1 "$?" "non-repository rejected"
66
67plugin_state() {
68 print -r -- "$1" | _plan_build_claude_plugin_state "$2"
69}
70
71assert_equal enabled "$(plugin_state $' ❯ agentmemory@agentmemory\n Version: 1\n Status: ✔ enabled' 'agentmemory@agentmemory')" "enabled Claude plugin"
72assert_equal disabled "$(plugin_state $' ❯ mattpocock-skills@mattpocock\n Status: disabled' 'mattpocock-skills@mattpocock')" "disabled Claude plugin"
73assert_equal missing "$(plugin_state $' ❯ other@market\n Status: ✔ enabled' 'agentmemory@agentmemory')" "missing Claude plugin"
74assert_equal installed "$(plugin_state ' ❯ agentmemory@agentmemory' 'agentmemory@agentmemory')" "Claude plugin without status"
75
76assert_equal enabled "$(print -r -- 'agentmemory@agentmemory installed, enabled 1.0 /tmp/plugin' | _plan_build_codex_plugin_state)" "enabled Codex plugin"
77assert_equal disabled "$(print -r -- $'agentmemory@agentmemory installed, disabled 1.0 /tmp/plugin\nother@market installed, enabled 1.0 /tmp/other' | _plan_build_codex_plugin_state)" "disabled Codex plugin is not confused by later plugin"
78assert_equal missing "$(print -r -- 'other@market installed, enabled 1.0 /tmp/other' | _plan_build_codex_plugin_state)" "missing Codex plugin"
79
80_plan_build_project_id_is_valid "github.com/example/project"
81assert_equal 0 "$?" "valid project ID"
82_plan_build_project_id_is_valid "invalid project id"
83assert_equal 1 "$?" "project ID rejects spaces"
84_plan_build_project_id_is_valid "x"
85assert_equal 1 "$?" "project ID minimum length"
86
87command git -C "$fixture_dir/worktree" remote add origin \
88 "https://opengist.example/owner/project.git"
89assert_equal "opengist.example/owner/project" \
90 "$(_plan_build_default_project_id "$fixture_dir/worktree")" \
91 "HTTPS remote normalizes to stable project ID"
92command git -C "$fixture_dir/worktree" remote set-url origin \
93 "git@opengist.example:owner/project.git"
94assert_equal "opengist.example/owner/project" \
95 "$(_plan_build_default_project_id "$fixture_dir/worktree")" \
96 "SSH remote normalizes to stable project ID"
97command git -C "$fixture_dir/worktree" remote set-url origin \
98 "https://opengist.example:8443/owner/project.git"
99assert_equal "opengist.example:8443/owner/project" \
100 "$(_plan_build_default_project_id "$fixture_dir/worktree")" \
101 "HTTPS remote preserves port in stable project ID"
102
103print -r -- "github.com/example/project" >| "$fixture_dir/worktree/.agentmemory-project"
104command git -C "$fixture_dir/worktree" add .agentmemory-project
105command git -C "$fixture_dir/worktree" -c user.name=Test -c user.email=test@example.invalid \
106 commit -qm "test: add project identity"
107project_id_output="$(cd "$fixture_dir/worktree" && _plan_build_resolve_project_id && print -r -- "$REPLY")"
108assert_equal "github.com/example/project" "$project_id_output" "committed project ID resolves"
109print -r -- "invalid project id" >| "$fixture_dir/worktree/.agentmemory-project"
110(cd "$fixture_dir/worktree" && _plan_build_resolve_project_id) >/dev/null 2>&1
111assert_equal 1 "$?" "invalid committed project ID rejected"
112print -r -- "github.com/example/other" >| "$fixture_dir/worktree/.agentmemory-project"
113(cd "$fixture_dir/worktree" && _plan_build_resolve_project_id) >/dev/null 2>&1
114assert_equal 1 "$?" "changed project ID rejected until committed"
115rm -f -- "$fixture_dir/worktree/.agentmemory-project"
116_plan_build_has_tty() { return 1 }
117(cd "$fixture_dir/worktree" && _plan_build_resolve_project_id) >/dev/null 2>&1
118assert_equal 1 "$?" "missing project ID fails without terminal"
119unfunction _plan_build_has_tty
120
121typeset args expected label
122for args expected label in \
123 "--v2" "Unknown argument: --v2" "v2 rejection" \
124 "--unknown" "Unknown argument: --unknown" "unknown option" \
125 "--yolo --yolo" "Duplicate argument: --yolo" "duplicate yolo" \
126 "--prompt --prompt" "Duplicate argument: --prompt" "duplicate prompt" \
127 "--brainstorm" "Unknown argument: --brainstorm" "removed brainstorm" \
128 "--writing-plan" "Unknown argument: --writing-plan" "removed writing plan" \
129 "--architect --architect" "Duplicate argument: --architect" "duplicate architect" \
130 "--architect --new --new" "Duplicate argument: --new" "duplicate new" \
131 "--new" "--new requires --architect" "orphan new" \
132 "--architect --prompt" "may combine only with --new and --yolo" "architect prompt conflict"; do
133 run_plan "$args"
134 assert_equal 1 "$rc" "$label status"
135 assert_contains "$output" "$expected" "$label message"
136done
137
138export CLAUDE_CODE_SAFE_MODE=1
139output="$(_plan_build_safe_mode_preflight 2>&1)"
140rc=$?
141unset CLAUDE_CODE_SAFE_MODE
142assert_equal 1 "$rc" "safe mode failure"
143assert_contains "$output" "safe mode disables the Matt Pocock and AgentMemory plugins" "safe mode guidance"
144
145_plan_build_memory_action_from_reply retry
146assert_equal 2 "$?" "memory action parses retry"
147_plan_build_memory_action_from_reply continue
148assert_equal 0 "$?" "memory action parses continue"
149_plan_build_memory_action_from_reply stop
150assert_equal 1 "$?" "memory action parses stop"
151
152_plan_build_agentmemory_health() { return 0 }
153_plan_build_claude_agentmemory_state() { print -r -- enabled }
154_plan_build_codex_agentmemory_state() { print -r -- enabled }
155_plan_build_real_agentmemory_check >/dev/null
156assert_equal 0 "$?" "AgentMemory check accepts healthy shared setup"
157_plan_build_codex_agentmemory_state() { print -r -- disabled }
158_plan_build_real_agentmemory_check >/dev/null
159assert_equal 1 "$?" "AgentMemory check rejects disabled Codex plugin"
160
161typeset -gi memory_check_attempts=0
162_plan_build_agentmemory_check() {
163 memory_check_attempts=$((memory_check_attempts + 1))
164 (( memory_check_attempts >= 2 ))
165}
166_plan_build_confirm_memory_action() { return 2 }
167_plan_build_agentmemory_preflight >/dev/null
168assert_equal 0 "$?" "memory retry can recover"
169assert_equal 2 "$memory_check_attempts" "memory retry repeats health check"
170assert_equal required "$REPLY" "recovered memory remains required"
171
172_plan_build_agentmemory_check() { return 1 }
173_plan_build_confirm_memory_action() { return 0 }
174_plan_build_agentmemory_preflight >/dev/null
175assert_equal 0 "$?" "approved degraded memory status"
176assert_equal degraded "$REPLY" "approved degraded memory mode"
177_plan_build_confirm_memory_action() { return 1 }
178_plan_build_agentmemory_preflight >/dev/null
179assert_equal 1 "$?" "rejected degraded memory status"
180unfunction _plan_build_agentmemory_check _plan_build_confirm_memory_action
181
182mkdir -p "$fixture_dir/bin" "$fixture_dir/home/.augment" "$fixture_dir/enhance-tmp"
183print -r -- '{}' >| "$fixture_dir/home/.augment/session.json"
184print -r -- '#!/bin/sh' >| "$fixture_dir/bin/script"
185print -r -- 'printf "%s\n" "$@" > "$PLAN_BUILD_SCRIPT_ARGS"' >> "$fixture_dir/bin/script"
186print -r -- 'if [ "$1" = -q ] && [ "$2" = -t ]; then log_file=$4; shift 4; "$@" > "$log_file"; exit $?; fi' >> "$fixture_dir/bin/script"
187print -r -- 'log_file=$5; printf "Enhanced prompt: linux result\n" > "$log_file"; exit "${PLAN_BUILD_SCRIPT_STATUS:-0}"' >> "$fixture_dir/bin/script"
188print -r -- '#!/bin/sh' >| "$fixture_dir/bin/auggie"
189print -r -- 'printf "Enhanced prompt: mac result\n"; exit "${PLAN_BUILD_AUGGIE_STATUS:-0}"' >> "$fixture_dir/bin/auggie"
190chmod +x "$fixture_dir/bin/script" "$fixture_dir/bin/auggie"
191
192_plan_build_confirm_indexing() { return 1 }
193
194typeset platform script_args enhance_output
195trap 'print -u2 -r -- "test INT trap"' INT
196typeset caller_int_trap="$(trap -p INT)"
197for platform in Darwin Linux; do
198 _plan_build_platform() { print -r -- "$platform" }
199 : >| "$fixture_dir/script-args"
200 enhance_output="$fixture_dir/enhanced-$platform"
201 HOME="$fixture_dir/home" TMPDIR="$fixture_dir/enhance-tmp" \
202 PATH="$fixture_dir/bin:$PATH" PLAN_BUILD_SCRIPT_ARGS="$fixture_dir/script-args" \
203 _plan_build_real_enhance_prompt "raw prompt" "$enhance_output"
204 rc=$?
205 assert_equal 0 "$rc" "$platform script enhancement status"
206 script_args="$(<"$fixture_dir/script-args")"
207 if [[ "$platform" == Darwin ]]; then
208 assert_contains "$script_args" $'-t\n0' "macOS script immediate flushing"
209 assert_contains "$script_args" $'auggie\n--print' "macOS script direct executable dispatch"
210 assert_not_contains "$script_args" $'\ncommand\n' "macOS script excludes shell builtin"
211 assert_equal "mac result" "$(<"$enhance_output")" "macOS parsed enhancement"
212 else
213 assert_contains "$script_args" $'-q\n-f' "Linux script immediate flushing"
214 assert_contains "$script_args" $'-e\n-O' "Linux script propagates child status"
215 assert_contains "$script_args" "-c" "Linux script command mode"
216 assert_equal "linux result" "$(<"$enhance_output")" "Linux parsed enhancement"
217 fi
218 assert_equal 0 "$(count_matches "$fixture_dir/enhance-tmp" plan-build-auggie)" "$platform run directory cleanup"
219done
220assert_equal "$caller_int_trap" "$(trap -p INT)" "enhancement traps remain local to caller"
221trap - INT
222
223platform=Darwin
224_plan_build_platform() { print -r -- "$platform" }
225PLAN_BUILD_AUGGIE_STATUS=7 HOME="$fixture_dir/home" TMPDIR="$fixture_dir/enhance-tmp" \
226 PATH="$fixture_dir/bin:$PATH" PLAN_BUILD_SCRIPT_ARGS="$fixture_dir/script-args" \
227 _plan_build_real_enhance_prompt "partial prompt" "$fixture_dir/failed-enhancement" >/dev/null 2>&1
228rc=$?
229assert_equal 7 "$rc" "nonzero Auggie status propagated"
230[[ ! -e "$fixture_dir/failed-enhancement" ]] || fail "failed Auggie output was accepted"
231assert_equal 0 "$(count_matches "$fixture_dir/enhance-tmp" plan-build-auggie)" "failed run directory cleanup"
232
233platform=Linux
234PLAN_BUILD_SCRIPT_STATUS=7 HOME="$fixture_dir/home" TMPDIR="$fixture_dir/enhance-tmp" \
235 PATH="$fixture_dir/bin:$PATH" PLAN_BUILD_SCRIPT_ARGS="$fixture_dir/script-args" \
236 _plan_build_real_enhance_prompt "partial prompt" "$fixture_dir/failed-linux-enhancement" >/dev/null 2>&1
237rc=$?
238assert_equal 7 "$rc" "Linux script child status propagated"
239[[ ! -e "$fixture_dir/failed-linux-enhancement" ]] || fail "failed Linux Auggie output was accepted"
240
241print -r -- $'noise\r\n\e[32m✨ Enhanced prompt: first\e[0m\r\nsecond\r\n🤖 tool' >| "$fixture_dir/parser.log"
242_plan_build_parse_auggie_output "$fixture_dir/parser.log" "$fixture_dir/parser.out"
243assert_equal $'first\nsecond' "$(<"$fixture_dir/parser.out")" "parser strips terminal output and stops at marker"
244print -r -- "no enhanced prompt" >| "$fixture_dir/parser-empty.log"
245_plan_build_parse_auggie_output "$fixture_dir/parser-empty.log" "$fixture_dir/parser-empty.out"
246[[ ! -s "$fixture_dir/parser-empty.out" ]] || fail "parser accepted output without marker"
247
248typeset -g enhanced_text="enhanced payload"
249typeset -gi enhanced_approval=0
250typeset -gi common_preflight_result=0
251typeset -gi enhancement_result=0
252
253_plan_build_require_cli() {
254 print -r -- "SEAM:cli:$1"
255 return 0
256}
257_plan_build_common_preflight() {
258 print -r -- "SEAM:common:$2"
259 return "$common_preflight_result"
260}
261_plan_build_resolve_project_id() {
262 print -r -- "SEAM:project-id"
263 REPLY="github.com/example/project"
264}
265_plan_build_agentmemory_preflight() {
266 print -r -- "SEAM:memory"
267 REPLY="required"
268}
269_plan_build_enhance_prompt() {
270 print -r -- "SEAM:auggie:$1"
271 print -r -- "$enhanced_text" >| "$2"
272 return "$enhancement_result"
273}
274_plan_build_confirm_enhanced_prompt() {
275 print -r -- "SEAM:enhanced-approval"
276 return "$enhanced_approval"
277}
278_plan_build_launch_claude() {
279 print -r -- "SEAM:claude"
280 printf 'CLAUDE_YOLO=<%s>\nCLAUDE_PROJECT=<%s>\nCLAUDE_MEMORY=<%s>\nCLAUDE_PROMPT=<%s>\n' "$1" "$2" "$3" "$4"
281}
282
283run_plan "" "first line\nsecond line\nEOF\nignored line\n"
284assert_equal 0 "$rc" "Matt default mode status"
285assert_contains "$output" "memory-aware Matt Pocock workflow" "Matt workflow prompt"
286assert_contains "$output" "AgentMemory project: github.com/example/project" "memory project prompt"
287assert_contains "$output" "Run the mandatory recall gate" "recall gate prompt"
288assert_contains "$output" $'first line\nsecond line' "multiline payload"
289assert_not_contains "$output" "ignored line" "EOF terminates payload"
290assert_equal "common:1 project-id memory claude" "$(seam_events "$output")" "default preflight ordering"
291
292enhanced_approval=0
293run_plan "--prompt" "raw payload\nEOF\n"
294assert_equal 0 "$rc" "prompt mode approved status"
295assert_contains "$output" "enhanced payload" "enhanced prompt used"
296assert_contains "$output" "Enhanced prompt approved" "enhanced approval reported"
297assert_equal "common:1 cli:auggie cli:script cli:perl project-id memory auggie:raw payload enhanced-approval claude" "$(seam_events "$output")" "prompt seams ordering"
298
299enhancement_result=9
300run_plan "--prompt" "failed child\nEOF\n"
301assert_equal 9 "$rc" "prompt child failure status propagated"
302assert_not_contains "$output" "enhanced-approval" "failed enhancement is never parsed or approved"
303assert_not_contains "$output" "SEAM:claude" "failed enhancement prevents launch"
304assert_equal 0 "$(count_matches "$TMPDIR" plan-build-enhanced)" "enhanced temporary file cleanup"
305enhancement_result=0
306
307enhanced_approval=1
308run_plan "--prompt" "declined\nEOF\n"
309assert_equal 0 "$rc" "prompt rejection exits cleanly"
310assert_contains "$output" "not approved" "prompt rejection message"
311assert_equal "common:1 cli:auggie cli:script cli:perl project-id memory auggie:declined enhanced-approval" "$(seam_events "$output")" "prompt rejection prevents launch"
312enhanced_approval=0
313
314run_plan "--architect" "design feature\nEOF\n"
315assert_equal 0 "$rc" "architect safe-resume status"
316assert_contains "$output" "Start mode: safe-resume-detection" "architect safe-resume mode"
317assert_contains "$output" "documentation-first architect/orchestrator role" "architect role boundary"
318assert_contains "$output" "Run the skill's mandatory recall gate" "architect recall gate prompt"
319assert_equal "common:0 project-id memory claude" "$(seam_events "$output")" "architect preflight before launch"
320
321run_plan "--architect --new" "fresh design\nEOF\n"
322assert_equal 0 "$rc" "architect new status"
323assert_contains "$output" "Start mode: archive-and-start-new" "architect new mode"
324
325run_plan "--architect --yolo" "fast design\nEOF\n"
326assert_equal 0 "$rc" "architect yolo status"
327assert_contains "$output" "CLAUDE_YOLO=<1>" "architect yolo reaches launch seam"
328assert_contains "$output" "including every gate" "architect yolo retains gates"
329
330common_preflight_result=1
331run_plan "--architect" "must not be read\nEOF\n"
332assert_equal 1 "$rc" "architect preflight failure status"
333assert_not_contains "$output" "Reading payload" "architect preflight precedes payload"
334assert_equal "common:0" "$(seam_events "$output")" "architect failure stops processing"
335common_preflight_result=0
336
337run_plan "" "EOF\n"
338assert_equal 1 "$rc" "empty payload status"
339assert_contains "$output" "Payload was empty" "empty payload message"
340
341print -r -- '#!/bin/sh' >| "$fixture_dir/bin/claude"
342print -r -- 'printf "PROJECT=<%s> MEMORY=<%s> INJECT=<%s> REAL_CLAUDE:" "$AGENTMEMORY_PROJECT_NAME" "$PLAN_BUILD_MEMORY_MODE" "$AGENTMEMORY_INJECT_CONTEXT"; printf " <%s>" "$@"; printf "\n"' >> "$fixture_dir/bin/claude"
343chmod +x "$fixture_dir/bin/claude"
344output="$(PATH="$fixture_dir/bin:$PATH" _plan_build_real_launch_claude 1 "github.com/example/project" required "payload")"
345assert_contains "$output" "<--dangerously-skip-permissions>" "yolo translates to real Claude argument"
346assert_not_contains "$output" "<--yolo>" "yolo alias not forwarded"
347assert_contains "$output" "PROJECT=<github.com/example/project>" "project ID reaches Claude environment"
348assert_contains "$output" "MEMORY=<required>" "memory mode reaches Claude environment"
349assert_contains "$output" "INJECT=<true>" "context injection reaches Claude environment"
350output="$(PATH="$fixture_dir/bin:$PATH" _plan_build_real_launch_claude 0 "github.com/example/project" degraded "payload")"
351assert_contains "$output" "MEMORY=<degraded>" "degraded memory mode reaches Claude environment"
352assert_contains "$output" "INJECT=<false>" "degraded mode disables context injection"
353
354if (( failures )); then
355 print -u2 -r -- "FAIL: $failures plan_build test(s)"
356 exit 1
357fi
358
359print -r -- "PASS: plan_build tests"
360