Skip to content

Deterministic Plan Tooling

Plan Metadata

  • Plan type: plan
  • Parent plan: N/A
  • Depends on: N/A
  • Status: draft

Status semantics: - draft: Plan is being created or updated and is not final. - approved: Plan is approved but not yet applied in code. - documentation: Code currently exists and matches the plan contract.

Update rule: - When an existing plan is edited, set status to draft until re-approved.

System Intent

  • What is being built: Deterministic tooling for new-plan, resolve-plans, and plan enablement that parses plan contracts and outputs machine-readable create/update/delete implementation scope.
  • Primary consumer(s): AI agents and developers running plan-first workflows before implementation.
  • Boundary (black-box scope only): Parse plan metadata/flows from docs/plans/*.md, resolve graph dependencies, classify contract diffs, and emit deterministic manifests/checklists without LLM reasoning.
  • Script ownership: implement scripts under scripts/plan_tooling/ so planning skills can call a stable CLI instead of re-parsing markdown.
  • Runtime parser requirement: implement executable parsing code that is run during planning/execution to parse plan files and produce implementation TODOs/manifests; do not rely on ad-hoc LLM-only interpretation.
  • Mermaid change-state requirement: implementation scripts must verify that every Mermaid updated/created/deleted node has matching implemented changes; after verification passes, scripts must normalize Mermaid nodes to unchanged.

Stage Gate Tracker

  • [ ] Stage 1 Mermaid approved
  • [ ] Stage 2 I/O contracts approved
  • [ ] Stage 3 pseudocode/technical details approved or skipped

1. Mermaid Diagram

Reference: .agent/skills/create-mermaid-diagram/SKILL.md

flowchart TD
  A[Plan Docs - docs/plans/*.md] -->|parse metadata + flow + types| B[Plan Contract Indexer]
  G[Git Base or Snapshot] -->|compare revisions| C[Contract Diff Classifier]
  B -->|parent dependency child reverse-dependency edges| D[Related Plan Resolver]
  C -->|create update delete deltas| E[Update TODO Builder]
  D -->|ordered related plans| E
  E -->|CREATE UPDATE DELETE notes| F[Plan Update TODO Manifest]
  F -->|file targets + action notes| H[Enable Plans Manifest]
  H -->|validate plan-owned vs generated files| I[File Policy Validator]
  I -->|deterministic TODO checklist| J[Planning Output for Skills]

  classDef unchanged fill:#d3d3d3,stroke:#666,stroke-width:1px;
  classDef updated fill:#ffe58a,stroke:#666,stroke-width:1px;
  classDef deleted fill:#f4a6a6,stroke:#666,stroke-width:1px;
  classDef created fill:#a8e6a3,stroke:#666,stroke-width:1px;

  class A,G,B,C,D,E,F,H,I,J created;

2. Black-Box Inputs and Outputs

Keep this short. Define types in JSON-style blocks and capture each flow with path-level rows. - Flow naming rule: each flow uses this format: - ### Flow: `<flowname>` - - Test files: <path/to/test_file.ext>, ... (or N/A when no automated test is required) - - Core files: <path/to/core_file.ext>, ... - N/A means explicit no-test-required waiver for that flow (not a missing mapping).

Global Types

PlanMetadata {
  plan_path: string (repo-relative docs/plans path)
  plan_type: "plan" | "sub-plan"
  parent_plan: string ("N/A" or docs/plans file name)
  depends_on: list[string] (normalized from Depends on / Dependency plans / Depandency plans)
  status: "draft" | "approved" | "documentation"
}

PlanChange {
  plan_path: string
  change_type: "created" | "updated" | "deleted" | "unchanged"
  changed_sections: list[string] (metadata, mermaid, io-contracts, pseudocode)
}

FlowContract {
  plan_path: string
  flow_name: string
  test_files: list[string] or "N/A"
  core_files: list[string]
  path_names: list[string]
}

TypeContract {
  plan_path: string
  type_name: string
}

ContractPathChange {
  plan_path: string
  flow_name: string
  path_name: string
  change_type: "created" | "updated" | "deleted" | "unchanged"
  updated_marker: "Y" | ""
  test_files: list[string] or "N/A"
  core_files: list[string]
}

TypeChange {
  plan_path: string
  type_name: string
  change_type: "created" | "updated" | "deleted" | "unchanged"
}

RelatedPlan {
  plan_path: string
  discovered_from: string
  relation: "seed" | "parent" | "child" | "dependency" | "reverse-dependency"
}

TodoItem {
  action: "CREATE" | "UPDATE" | "DELETE"
  target_kind: "plan" | "flow" | "type" | "path-row" | "file"
  target_id: string
  source_plan: string
  related_plan: string
  required_note: string
  file_targets: list[string]
}

ResolvePlansManifest {
  seed_plans: list[string]
  traversal_order: list[string] (seed, parent-first, dependencies, children, reverse-dependencies)
  related_plans: list[RelatedPlan]
  checklist_rows: list[{
    plan_path: string
    discovered_from: string
    action: "review"
    status: "pending" | "updated" | "no-change"
  }]
}

PlanUpdateTodoManifest {
  seed_plans: list[string]
  related_plans: list[string]
  flow_changes: list[ContractPathChange]
  type_changes: list[TypeChange]
  todo_items: list[TodoItem]
  todo_markdown_lines: list[string] (one line per item: "[ACTION] <target_kind> <target_id> - <required_note>")
  blocking_errors: list[string]
}

MermaidNodeChangeState {
  plan_path: string
  node_id: string
  state: "unchanged" | "updated" | "created" | "deleted"
  referenced_targets: list[string]
}

PlanImplementationVerificationManifest {
  plan_path: string
  mermaid_nodes: list[MermaidNodeChangeState]
  checked_targets: list[string]
  unresolved_change_nodes: list[string]
  missing_targets: list[string]
  blocking_errors: list[string]
}

EnablePlansManifest {
  plan_items: list[string]
  file_items: list[{
    plan_path: string
    file_path: string
    required_reason: string
  }]
  delete_items: list[{
    plan_path: string
    target_path: string
    reason: string
  }]
  todo_items: list[TodoItem]
  file_policy_items: list[{
    file_path: string
    policy: "plan-owned" | "generated"
    generated_pattern: "<filename>.generated.<extension>" | ""
  }]
  blocking_errors: list[string]
}

API Reference

plan-tool new-plan --plan <docs/plans/*.md> [--base <git-ref>]
  -> PlanMetadata + ContractPathChange summary

plan-tool resolve-plans --seed <docs/plans/a.md> [--seed <docs/plans/b.md> ...] [--base <git-ref>]
  -> ResolvePlansManifest + PlanUpdateTodoManifest

plan-tool generate-update-todos --seed <docs/plans/a.md> [--base <git-ref>] [--out-json <path>] [--out-md <path>]
  -> PlanUpdateTodoManifest

plan-tool enable-plans --seed <docs/plans/a.md> [--base <git-ref>] [--mode approved|documentation] [--todo <manifest.json>]
  -> EnablePlansManifest

plan-tool validate-plan-file-policy --todo <manifest.json>
  -> file policy report + blocking errors

plan-tool verify-plan-implementation --plan <docs/plans/*.md> [--base <git-ref>] [--todo <manifest.json>]
  -> PlanImplementationVerificationManifest

plan-tool normalize-mermaid-state --plan <docs/plans/*.md> --require-clean-implementation
  -> plan file updated with Mermaid class nodes set to unchanged

Skill Integration Contract

update-plan skill stage (resolve plans):
  1) plan-tool resolve-plans --seed <updated-plan> --base <git-ref>
  2) plan-tool generate-update-todos --seed <updated-plan> --base <git-ref> --out-json <tmp/todos.json> --out-md <tmp/todos.md>
  3) planning skill consumes todos.json/todos.md and executes CREATE/UPDATE/DELETE notes in order.

reconcile-plans skill stage:
  1) use related_plans from ResolvePlansManifest as deterministic review queue.
  2) if any reconciled plan changes, re-run generate-update-todos for that plan before implementation.

execute-plan skill stage:
  1) consume todo_items directly; do not infer missing work from prose.
  2) call validate-plan-file-policy before write/commit to enforce exact naming and .generated policy.
  3) run parser + manifest commands as the source of truth for what gets implemented.
  4) run verify-plan-implementation to prove Mermaid change nodes are fully implemented.
  5) run normalize-mermaid-state only after verification passes so Mermaid shows no-change.
  6) set plan status to `documentation` only after Mermaid normalization succeeds.

required implementation output files for this plan:
  1) .agent/skills/update-plan/SKILL.md
  2) .agent/skills/reconcile-plans/SKILL.md
  3) .agent/skills/execute-plan/SKILL.md
  4) scripts/plan_tooling/* (parser/manifest code)

Flow: plan-metadata-parse

  • Test files: main/server/tests/unit/test_plan_tooling_parser.py
  • Core files: scripts/plan_tooling/plan_parser.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
plan-metadata-parse.success plan markdown with Plan Metadata block PlanMetadata happy path parser extracts Plan type, Parent plan, Depends on, and Status Y
plan-metadata-parse.legacy-dependency-keys plan markdown with Dependency plans or Depandency plans label PlanMetadata depends_on normalized subpath accept legacy key spellings deterministically Y
plan-metadata-parse.invalid-metadata plan missing required metadata key blocking error with exact missing field error required before any resolve/enable operation Y

Flow: plan-contract-index

  • Test files: main/server/tests/unit/test_plan_tooling_contract_index.py
  • Core files: scripts/plan_tooling/contract_index.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
plan-contract-index.flows-and-types plan markdown with Global Types and Flow blocks FlowContract + TypeContract index happy path all flow names and type names are captured verbatim for exact-match validation Y
plan-contract-index.missing-flow-test-line flow heading without Test files line blocking error with plan path + flow name error rejects implicit test mappings Y
plan-contract-index.missing-flow-core-line flow heading without Core files line blocking error with plan path + flow name error every flow must define implementation target files Y

Flow: plan-change-classification

  • Test files: main/server/tests/unit/test_plan_tooling_diff.py
  • Core files: scripts/plan_tooling/plan_diff.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
plan-change-classification.created-plan new plan path exists in workspace but not in base PlanChange change_type=created happy path generated for new-plan command seeds Y
plan-change-classification.updated-plan plan content differs from base PlanChange change_type=updated changed_sections populated happy path section-aware diff drives deterministic review scope Y
plan-change-classification.deleted-plan plan path exists in base but not workspace PlanChange change_type=deleted subpath emitted so enable manifest can include delete work Y
plan-change-classification.unchanged-plan plan content equal to base PlanChange change_type=unchanged subpath unchanged plans can still appear in dependency traversal as no-change Y
plan-change-classification.type-and-flow-deltas old + new contract indexes TypeChange + ContractPathChange with created/updated/deleted happy path tracks new flows, deleted flows, and changed types deterministically Y
  • Test files: main/server/tests/unit/test_plan_tooling_resolve.py
  • Core files: scripts/plan_tooling/plan_graph.py, scripts/plan_tooling/resolve_plans.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
resolve-plans-related-graph.parent-first seed plan list with valid metadata ResolvePlansManifest traversal_order starts with seed then parent before dependencies happy path parent contract is always reviewed before dependency fan-out Y
resolve-plans-related-graph.reverse-links all plan metadata scanned children + reverse-dependencies discovered happy path pulls related plans that reference the seed so no impacted plan is skipped Y
resolve-plans-related-graph.cycle-handled relationship cycle across plans ResolvePlansManifest produced without infinite loop error cycle recorded as warning and traversal continues Y

Flow: resolve-plans-todo-generation

  • Test files: main/server/tests/unit/test_plan_tooling_todo_manifest.py
  • Core files: scripts/plan_tooling/todo_manifest.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
resolve-plans-todo-generation.create-update-delete seed plan changes + related plans + flow/type deltas PlanUpdateTodoManifest todo_items with action CREATE/UPDATE/DELETE happy path emits deterministic TODO notes for every impacted plan/flow/type/path row Y
resolve-plans-todo-generation.no-llm-gap same input snapshot run multiple times stable sorted TODO output happy path deterministic sort key prevents LLM omissions or ordering drift Y
resolve-plans-todo-generation.action-note-format todo_items with required_note todo_markdown_lines in exact format [ACTION] target_kind target_id - note subpath planning skills can read/update TODO files without parsing markdown sections Y
resolve-plans-todo-generation.missing-related-plan diff references plan not present in graph blocking error with seed + missing plan path error prevents partial TODO manifests Y

Flow: planning-skill-handoff

  • Test files: main/server/tests/unit/test_plan_tooling_skill_handoff.py
  • Core files: scripts/plan_tooling/skill_handoff.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
planning-skill-handoff.write-json-and-md PlanUpdateTodoManifest + output paths todos.json + todos.md written deterministically happy path planning skills receive one machine-readable artifact and one human-readable checklist Y
planning-skill-handoff.strict-action-order unordered todo_items sorted output by (related_plan, target_kind, target_id, action) happy path stable order prevents checklist churn and missed updates Y
planning-skill-handoff.unknown-action todo item action outside CREATE/UPDATE/DELETE blocking error with target_id + action error prevents ambiguous TODO execution Y

Flow: planning-skill-trigger-enforcement

  • Test files: main/server/tests/unit/test_plan_tooling_skill_contracts.py
  • Core files: scripts/plan_tooling/skill_contracts.py, .agent/skills/update-plan/SKILL.md, .agent/skills/reconcile-plans/SKILL.md, .agent/skills/execute-plan/SKILL.md

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
planning-skill-trigger-enforcement.required-files implementation diff for deterministic-plan-tooling scope blocking error if any required skill file is not updated error guarantees skill wiring changes are included with parser/tooling implementation Y
planning-skill-trigger-enforcement.update-plan-hooks updated update-plan skill explicit command hooks for resolve-plans and generate-update-todos happy path ensure resolve stage always triggers deterministic TODO generation Y
planning-skill-trigger-enforcement.reconcile-hooks updated reconcile-plans skill explicit command hook using ResolvePlansManifest related_plans queue happy path ensures related plans are discovered/reviewed from tooling output, not manual inference Y
planning-skill-trigger-enforcement.execute-hooks updated execute-plan skill explicit command hook for validate-plan-file-policy before writes happy path prevents implementation drift outside plan contracts Y

Flow: plan-file-policy-validation

  • Test files: main/server/tests/unit/test_plan_tooling_file_policy.py
  • Core files: scripts/plan_tooling/file_policy.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
plan-file-policy-validation.plan-owned-exact-match todo item targets non-generated file all symbols in file match plan-defined flow/type names exactly happy path non-generated files are contract-owned and cannot include undocumented symbols Y
plan-file-policy-validation.generated-allowed todo item targets <filename>.generated.<extension> file marked policy=generated subpath generated files may contain helper code not explicitly modeled in plans Y
plan-file-policy-validation.non-generated-extra-symbol non-generated file contains symbol not in plan contracts blocking error with file path + symbol error enforces strict plan-to-code contract boundaries Y

Flow: mermaid-change-implementation-validation

  • Test files: main/server/tests/unit/test_plan_tooling_mermaid_validation.py
  • Core files: scripts/plan_tooling/mermaid_validation.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
mermaid-change-implementation-validation.pass plan with Mermaid nodes marked updated/created/deleted + implemented targets present PlanImplementationVerificationManifest with unresolved_change_nodes=[] happy path proves each Mermaid change marker has corresponding implemented contract/file changes Y
mermaid-change-implementation-validation.missing-target Mermaid changed node references target file/symbol not implemented blocking error with node_id + missing target error prevents claiming completion when implementation is incomplete Y
mermaid-change-implementation-validation.status-doc-with-changes plan status=documentation while Mermaid has non-unchanged nodes blocking error requiring normalize-mermaid-state error documentation status cannot coexist with pending Mermaid change markers Y

Flow: mermaid-change-state-normalization

  • Test files: main/server/tests/unit/test_plan_tooling_mermaid_normalize.py
  • Core files: scripts/plan_tooling/mermaid_normalize.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
mermaid-change-state-normalization.clean-to-unchanged verified plan with Mermaid changed nodes and no blocking errors plan Mermaid class lines rewritten so all nodes are unchanged happy path deterministic cleanup after implementation completion Y
mermaid-change-state-normalization.blocked-on-unresolved verification manifest with unresolved_change_nodes or missing_targets blocking error and no Mermaid mutation error guarantees no false no-change state Y
mermaid-change-state-normalization.idempotent plan already all unchanged no diff output subpath safe to run at end of every execute-plan flow Y

Flow: enable-plans-scope

  • Test files: main/server/tests/unit/test_plan_tooling_enable_scope.py
  • Core files: scripts/plan_tooling/enable_scope.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
enable-plans-scope.updated-rows-to-file-items changed plans with contract rows marked updated=Y EnablePlansManifest file_items for each flow core file happy path this is the deterministic implementation scope source Y
enable-plans-scope.deleted-path-row ContractPathChange change_type=deleted EnablePlansManifest delete_items populated subpath delete work is explicit, never inferred by LLM Y
enable-plans-scope.todo-manifest-ingest PlanUpdateTodoManifest todo_items EnablePlansManifest.todo_items preserved with action notes happy path planning skills consume TODOs directly without re-parsing markdown Y
enable-plans-scope.missing-test-mapping flow heading missing test files and not N/A blocking error with plan path + flow name error prevents execution on incomplete plan contracts Y

Flow: enable-plans-gates

  • Test files: main/server/tests/unit/test_plan_tooling_enable_gates.py
  • Core files: scripts/plan_tooling/enable_plans.py

Type Definitions

FlowInput = see Global Types
FlowOutput = see path table contracts

Paths

path-name input output/expected state change path-type notes updated
enable-plans-gates.approved-mode plans with status=approved and completed stage gates EnablePlansManifest with no gate errors happy path allows implementation mode with deterministic checklist Y
enable-plans-gates.documentation-mode plans with status=documentation and no updated=Y rows EnablePlansManifest with no gate errors happy path supports verification-only reruns Y
enable-plans-gates.blocked-status-or-gates draft status or unchecked stage gate blocking error listing violating plans error enforce planning gate before execution Y

3. Pseudocode / Technical Details for Critical Flows (Optional)

  • Flow name: resolve-and-generate-update-todos
    parse changed plans and metadata from docs/plans
    index all flow contracts and global type names exactly as written in plans
    classify plan, flow, path-row, and type deltas against base revision
    resolve related plans in deterministic order: seed, parent, dependencies, children, reverse-dependencies
    for each delta emit TodoItem action CREATE/UPDATE/DELETE with required_note
    map todo items to file targets from each flow Core files list
    verify each Mermaid node marked updated/created/deleted maps to implemented targets
    block completion when any Mermaid change node is unresolved
    after successful verification rewrite Mermaid class states to unchanged
    mark file policy as generated only when file name matches <filename>.generated.<extension>
    enforce required skill files are updated and contain command hooks for deterministic plan-tool invocations
    validate non-generated files do not contain undocumented symbols
    emit ResolvePlansManifest + PlanUpdateTodoManifest + EnablePlansManifest
    exit non-zero when any blocking errors exist
    
  • Implementation notes:
  • Output must be stable JSON and sorted by (related_plan, target_kind, target_id, action) so planning skills can consume deterministically.
  • Parser must fail fast with exact path:line diagnostics for malformed metadata, flow headings, type blocks, or missing test/core file mappings.
  • All user-defined names in plans are exact-match identifiers; no alias expansion is allowed for flow names or type names.
  • Non-generated files must only contain plan-defined contract symbols. Any extra symbol is a blocking error.
  • Generated helper outputs must follow <filename>.generated.<extension> to allow deterministic overwrite/update by tooling.

After all stages are approved, apply .agent/skills/reconcile-plans/SKILL.md to propagate contract updates across linked plans.