Skip to content

feat: add gpd:goal — goal-directed autonomous runs under binding caps - #254

Open
hvgazula wants to merge 15 commits into
mainfrom
worktree-goal-command
Open

feat: add gpd:goal — goal-directed autonomous runs under binding caps#254
hvgazula wants to merge 15 commits into
mainfrom
worktree-goal-command

Conversation

@hvgazula

@hvgazula hvgazula commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds gpd:goal "<statement>" [--budget-usd X] [--max-phases N]: a goal-directed autonomous run that continues itself toward a stated outcome under a binding cap, modeled on the existing autonomous workflow.

  • Typed goal contract (goal_contract field on ResearchState): statement, success criteria tied to plan-contract claim ids, USD budget and/or phase-count cap, run status.
  • Dual cap: the USD budget binds where the runtime records cost telemetry (codex today); the --max-phases cap binds everywhere. The strictest enforceable cap wins, and a run with no enforceable cap fails closed rather than running uncapped.
  • Verifier-gated completion: criteria reference plan-contract claim ids; only contract_results.claims outcomes written by the verification machinery into phase VERIFICATION.md can mark the goal achieved. The run loop cannot self-declare success. (A non-strict fallback knob exists for demo robustness; failed criteria always block.)
  • New CLI surfaces: gpd goal status (receipt), gpd goal gate (machine decision), gpd validate goal-contract.
  • The autonomous workflow and its stage manifest are untouched; gpd:goal ships its own workflows/goal/ workflow plus a top-level workflows/goal.md compatibility index.

Implemented incrementally via TDD with an adversarial reviewer gating each task.

Design docs

  • Spec (with adversarial-review amendments): docs/superpowers/specs/2026-06-04-goal-command-design.md
  • Implementation plan: docs/superpowers/plans/2026-06-04-goal-command.md

Notable caveat

The USD-budget receipt only populates on runtimes that record cost telemetry (codex). Under Claude Code the cost ledger stays empty, so the phase-count cap is what binds there — a blocker the spec review caught and the design was reworked around.

Registration & budgets

Adding a new command required registering it across the repo's cross-cutting contracts: skill-category map, command/workflow prompt-budget baselines, runtime-neutral command prefix, same-stem workflow index, and a proportional ratchet of a few runtime-projection advisory ceilings (e.g. the codex per-skill runtime-note aggregate, which grows by one fixed-template note per command). No correctness assertion was weakened; the only assert value changed is an advisory size ceiling.

Test status

  • Full suite green: 13009 passed, 7 skipped, 0 failed (uv run pytest tests/ -q)
  • Goal-module suites: test_goal_contract, test_goal_gate, test_goal_evidence, test_cli_goal, test_goal_smoke
  • Cross-runtime: registry, install-roundtrip, metadata-consistency, autonomous-stage-topology (unchanged)
  • Generated-surface checks: repo graph, public surface, help surface (all --check exit 0)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added goal-directed workflow and state support with CLI: gpd goal status (human receipt), gpd goal gate (JSON decision), and gpd validate goal-contract (validity + issues; non-zero exit on problems).
  • Documentation

    • Added design/specs, workflows, command reference, README, CONTRIBUTING guardrails, and CHANGELOG entries for the goal workflow and validation surface.
  • Tests

    • Added unit, CLI, smoke, and integration tests covering contract validation, evidence aggregation, gating logic, and end-to-end goal scenarios.

hvgazula added 10 commits June 4, 2026 16:32
- Dual cap (USD + max-phases): Claude Code emits no cost telemetry, so the
  USD budget binds only where cost_usd is available (codex today); the phase
  cap binds everywhere; fail closed when neither is enforceable
- Criteria reference plan-contract claim ids, aggregated from VERIFICATION.md
  contract_results.claims (existing verifier machinery) instead of a
  nonexistent per-check surface
- Separate workflows/goal/ workflow; autonomous stage manifest untouched
  (topology tests forbid edits)
- Typed goal_contract field on ResearchState; validator precedent corrected
  to review-ledger/referee-decision (JSON+pydantic)
- Generated-surface regen (repo graph, public surface, help surface) added
  to scope
- strict_criteria fallback knob (claim-id threading robustness; fail still blocks)
- explicit max-phases-N-permits-N semantics (wrap_up = one final consolidation phase)
- Task 6 end-to-end gate-plumbing smoke test (demo floor)
- minimal-demoable-slice note; USD-on-codex marked unverified stretch
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bfaeb47-4e57-432f-8fc0-d724e257a476

📥 Commits

Reviewing files that changed from the base of the PR and between 1e79725 and 2e70d21.

📒 Files selected for processing (9)
  • README.md
  • docs/superpowers/plans/2026-06-04-goal-command.md
  • docs/superpowers/specs/2026-06-04-goal-command-design.md
  • src/gpd/cli.py
  • src/gpd/core/state.py
  • src/gpd/specs/templates/state-json-schema.md
  • tests/adapters/projection_budget_support.py
  • tests/core/test_cli_goal.py
  • tests/core/test_state.py
✅ Files skipped from review due to trivial changes (3)
  • docs/superpowers/specs/2026-06-04-goal-command-design.md
  • tests/adapters/projection_budget_support.py
  • docs/superpowers/plans/2026-06-04-goal-command.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/gpd/specs/templates/state-json-schema.md
  • tests/core/test_cli_goal.py
  • src/gpd/cli.py

📝 Walkthrough

Walkthrough

Adds a typed goal-contract in state, evidence aggregation from phase VERIFICATION.md files, dual-cap gating and criteria evaluation, CLI commands (gpd goal gate, gpd goal status, gpd validate goal-contract), workflow/spec docs, and tests (unit, CLI, and end-to-end smoke).

Changes

Goal Command Feature

Layer / File(s) Summary
Goal contract schema and validation
src/gpd/core/goal_contract.py, src/gpd/core/state.py, tests/core/test_goal_contract.py
GoalContract and GoalCriterion Pydantic models define the goal-run structure stored in ResearchState.goal_contract, with validation enforcing at least one cap (USD or phases), unique criterion ids/claim refs, and non-empty criteria lists.
Evidence aggregation from phase verification
src/gpd/core/goal_evidence.py, tests/core/test_goal_evidence.py
Utilities scan GPD/phases/*-VERIFICATION.md frontmatter to aggregate claim outcome statuses and phase-level statuses; later phases override earlier ones and malformed files are silently skipped.
Goal gate decision and criteria evaluation
src/gpd/core/goal_gate.py, tests/core/test_goal_gate.py
Implements dual-cap gating: USD-based decisions (continue/wrap_up/stop) using near-budget threshold; phase-cap enforcement; strictest enforceable decision selection; and criteria evaluation with strict/non-strict fallback for pending outcomes.
CLI command implementation and validation
src/gpd/cli.py, src/gpd/commands/goal.md, tests/core/test_cli_goal.py
Exposes gpd goal gate, gpd goal status, and gpd validate goal-contract commands; loads contracts from state, aggregates evidence, computes gate decisions, and renders structured JSON or human-readable output.
Goal workflow bootstrap and orchestration
src/gpd/specs/workflows/goal/goal-bootstrap.md, src/gpd/specs/workflows/help.md
Specifies goal-run bootstrap stages (contract creation, baseline snapshot, criteria drafting), the iterative gate loop, phase-by-phase progress accounting, and terminal state handling with resume semantics.
End-to-end smoke testing and integration verification
tests/core/test_goal_smoke.py
Seeds goal contracts, simulates phase completion via verification files, invokes gate commands, and asserts achieved/budget_stopped outcomes and human-readable receipt rendering.
Design specification and implementation plan
docs/superpowers/specs/2026-06-04-goal-command-design.md, docs/superpowers/plans/2026-06-04-goal-command.md
Complete design spec covering problem, solution architecture, CLI surfaces, error handling, and testing strategy; detailed task-by-task implementation plan with test definitions.
Documentation and repository integration updates
CONTRIBUTING.md, README.md, src/gpd/specs/references/help/detailed-command-reference.md, src/gpd/specs/templates/state-json-schema.md, tests/README.md, tests/repo_graph_contract.json
Updates guardrails checklist, validation command table, command references, state schema, and repository graph metadata to include the new goal command and stem.

Sequence Diagram

sequenceDiagram
  participant CLI as gpd CLI
  participant State as GPD/state.json
  participant Evidence as goal_evidence
  participant Gate as goal_gate
  CLI->>State: load goal_contract
  CLI->>Evidence: collect_claim_outcomes & collect_phase_statuses
  CLI->>Gate: goal_gate_summary(contract, spent_usd, claim_outcomes)
  Gate-->>CLI: GoalGateSummary JSON
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • madeleinesong

Poem

🐇 I hopped through state and criteria fine,
Watching claims flip from pending to "pass" in line.
I nibbled budgets, checked phases one by one,
Said "wrap up" or "stop" when the run was done.
Hooray — a changelog nibble, the job is done!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a new gpd:goal command for goal-directed autonomous runs with binding budget/phase caps.
Description check ✅ Passed The description thoroughly covers what changed, why it was needed, testing status, design docs, and implementation details. All major template sections are addressed with substantive content.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-goal-command

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@marcpickett1

Copy link
Copy Markdown
Collaborator

🤖 RoastBot: Capitalism has arrived in the agent loop. The AI now has KPIs and hard stops. We've given it ambition and a performance review.

@hvgazula
hvgazula marked this pull request as ready for review June 4, 2026 22:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (3)
tests/core/test_goal_evidence.py (1)

5-5: 💤 Low value

Consolidate imports at module level for consistency.

collect_phase_statuses is imported locally within two test functions (lines 69, 79), while collect_claim_outcomes is imported at the module top (line 5). For consistency and clarity, import both functions at the module level.

♻️ Consolidate imports
-from gpd.core.goal_evidence import collect_claim_outcomes
+from gpd.core.goal_evidence import collect_claim_outcomes, collect_phase_statuses

Then remove the local imports at lines 69 and 79.

Also applies to: 69-69, 79-79

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/test_goal_evidence.py` at line 5, The tests import
collect_claim_outcomes at module level but import collect_phase_statuses inside
individual test functions; move the local imports of collect_phase_statuses up
to the module-level imports alongside collect_claim_outcomes, and then remove
the redundant local import statements inside the two test functions so both
helpers (collect_claim_outcomes and collect_phase_statuses) are imported
consistently at the top of the test module.
tests/core/test_cli_goal.py (2)

48-57: ⚡ Quick win

Consider strengthening the validation assertion.

Line 57 checks only for "max_phases" in the issues when both caps are None. Since the validation rule is "at least one cap is required" (per goal.md line 37), the assertion is somewhat arbitrary. If the validation error mentions budget_usd instead, or uses a more general message, the test could become brittle.

💡 More robust assertion
-    assert any("max_phases" in issue for issue in payload["issues"])
+    # Check that the validation caught the missing cap requirement
+    assert any("max_phases" in issue or "budget_usd" in issue or "at least one cap" in issue.lower() 
+               for issue in payload["issues"])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/test_cli_goal.py` around lines 48 - 57, The test
test_validate_goal_contract_reports_issues is brittle because it asserts only
that "max_phases" appears in payload["issues"]; update the assertion to check
for the required-cap validation more robustly by verifying that payload["valid"]
is False and that payload["issues"] contains either a mention of "max_phases" or
"budget_usd" or a phrase indicating the "at least one cap" rule (use the
existing runner.invoke/app/_raw_payload_from_result flow to locate the payload
and adjust the final assertion accordingly so it accepts either specific field
names or a general cap-related message).

80-86: ⚡ Quick win

Error message assertion aligns with the actual fail-closed text (optional robustness tweak).

  • GoalGateError is raised with: “... no max_phases cap is set. Set --max-phases ...”, and the CLI forwards str(exc) as the --raw JSON {"error": ...} payload.
  • Optional: assert on the more semantic "No enforceable cap" substring instead of max-phases/max_phases to avoid coupling to wording/flag formatting.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/core/test_cli_goal.py` around lines 80 - 86, Update the assertion in
test_goal_gate_fails_closed_without_enforceable_cap to check the semantic
failure message rather than flag formatting: after invoking runner.invoke(app,
["--raw", "--cwd", str(tmp_path), "goal", "gate"]) assert that the combined
output contains the lowercased semantic substring "no enforceable cap" (e.g.
assert "no enforceable cap" in combined) and you may keep the existing fallback
that checks for "max-phases"/"max_phases" if desired; this targets the
GoalGateError message forwarded by the CLI when no max_phases cap is set and
avoids coupling to flag formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-06-04-goal-command.md`:
- Line 7: Update the documentation phrase "gpd goal typer sub-app" to use the
correct product name by capitalizing Typer (i.e., "gpd goal Typer sub-app");
locate the string near the description referencing the gpd goal sub-app and
change "typer" to "Typer" so the docs consistently use the proper framework name
alongside symbols like goal_contract.py, goal_gate.py, and goal_evidence.py.
- Line 42: The markdown heading "### Task 1: Goal contract models and state
field" jumps from a level 1 heading to level 3 (violates MD001); change that
heading to a level 2 heading ("## Task 1: Goal contract models and state field")
or adjust surrounding headings so levels increment by one, ensuring the document
follows proper hierarchy and TOC parsers can correctly render sections.

In `@docs/superpowers/specs/2026-06-04-goal-command-design.md`:
- Around line 61-67: The fenced command block containing the example commands
(starting with "/gpd:goal \"Derive the dispersion relation..." and including
lines like "gpd goal status" and "gpd validate goal-contract") lacks a language
tag and triggers MD040; update the opening fence from ``` to ```bash (or
```text) so the block is labeled (e.g., ```bash) to satisfy markdownlint and
docs tooling.

In `@README.md`:
- Around line 534-535: Add two CLI reference entries for the missing
runtime-status commands alongside the existing validate lines: include `gpd goal
status [<goal-id>] [--watch]` with a short description like "Show runtime status
and metadata for a goal (optionally watch updates)" and `gpd goal gate <goal-id>
[--approve|--reject] [--reason]` with a description like "Inspect and act on
goal gates (approve/reject with optional reason)"; place these lines next to the
`gpd validate goal-contract` and `gpd validate reproducibility-manifest` rows in
the CLI table and mirror the style/flag notation used for other commands so
users see the full runtime-status surface.

In `@src/gpd/cli.py`:
- Around line 4495-4498: Replace the hard-coded "/gpd:goal" in the _error call
with the runtime-aware public command helper so the hint points to the correct
command surface; update the call in the block that calls _error (the missing
contract branch) to build the command text via the runtime/public-command helper
(e.g., use the project's runtime.public_command or get_public_command utility
with "gpd:goal") and interpolate that into the hint string along with the
existing flags and example usage.
- Around line 4504-4515: The current all_phases_passed uses
collect_phase_statuses(cwd) which returns project-wide phases and can include
unrelated failed phases; scope the phase statuses to the active goal run before
computing the boolean. Update either collect_phase_statuses (or filter its
returned dict) to accept and use the active run identifier from the current
contract (e.g., contract.run_id or contract metadata) so you only keep phases
belonging to that run, then compute all_phases_passed from that filtered set and
pass it into goal_gate_summary (symbols: collect_phase_statuses, contract,
all_phases_passed, goal_gate_summary). Ensure the filtering uses the run-scoped
field present in the contract/run state and preserves existing behavior when no
run id is available.
- Around line 4489-4505: The code uses _get_cwd() which can point to a nested
dir; change the logic in _goal_gate_payload() to resolve the repository/project
root first and use that for all reads: replace cwd = _get_cwd() with a call to
the project-root resolver used elsewhere (e.g. _get_project_root() or
_resolve_project_root()) and then pass that resolved_root to
state_load_readonly(...), build_cost_summary(...), collect_claim_outcomes(...),
and collect_phase_statuses(...) so the command always inspects the project root
state.json and related data.

In `@src/gpd/core/state.py`:
- Line 505: The normalization currently auto-heals nested GoalContract errors by
iteratively removing failing `loc` paths via
`_remove_validation_error_path(...)` in `_normalize_state_schema`; update
`_salvage_state_sections` (or the `_normalize_state_schema` recovery loop) to
special-case `goal_contract` (ResearchState.goal_contract) the same way
`project_contract` is handled: when a PydanticValidationError references any
`goal_contract` path, do not prune individual nested keys—either surface the
validation failure (raise/return an explicit integrity error) or drop the entire
`goal_contract` object and emit an integrity finding describing the drop; ensure
references to `GoalContract` and the failing `loc` are preserved in the finding
so callers can detect and fail-closed.

In `@src/gpd/specs/templates/state-json-schema.md`:
- Line 36: The JSON-only authority list is missing the newly introduced
top-level field goal_contract; update the authority list later in the document
to include `goal_contract` as an authoritative JSON-only entry (matching the
table row: `goal_contract | GoalContract | null`) so merge/recovery semantics
remain consistent; locate references to the JSON-only authority list and add
`goal_contract` to that list alongside the other JSON-only fields.

---

Nitpick comments:
In `@tests/core/test_cli_goal.py`:
- Around line 48-57: The test test_validate_goal_contract_reports_issues is
brittle because it asserts only that "max_phases" appears in payload["issues"];
update the assertion to check for the required-cap validation more robustly by
verifying that payload["valid"] is False and that payload["issues"] contains
either a mention of "max_phases" or "budget_usd" or a phrase indicating the "at
least one cap" rule (use the existing runner.invoke/app/_raw_payload_from_result
flow to locate the payload and adjust the final assertion accordingly so it
accepts either specific field names or a general cap-related message).
- Around line 80-86: Update the assertion in
test_goal_gate_fails_closed_without_enforceable_cap to check the semantic
failure message rather than flag formatting: after invoking runner.invoke(app,
["--raw", "--cwd", str(tmp_path), "goal", "gate"]) assert that the combined
output contains the lowercased semantic substring "no enforceable cap" (e.g.
assert "no enforceable cap" in combined) and you may keep the existing fallback
that checks for "max-phases"/"max_phases" if desired; this targets the
GoalGateError message forwarded by the CLI when no max_phases cap is set and
avoids coupling to flag formatting.

In `@tests/core/test_goal_evidence.py`:
- Line 5: The tests import collect_claim_outcomes at module level but import
collect_phase_statuses inside individual test functions; move the local imports
of collect_phase_statuses up to the module-level imports alongside
collect_claim_outcomes, and then remove the redundant local import statements
inside the two test functions so both helpers (collect_claim_outcomes and
collect_phase_statuses) are imported consistently at the top of the test module.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e1e30ec-85d5-485b-b8d4-806cfa56fa82

📥 Commits

Reviewing files that changed from the base of the PR and between 0f41769 and 18a19a5.

📒 Files selected for processing (21)
  • CONTRIBUTING.md
  • README.md
  • docs/superpowers/plans/2026-06-04-goal-command.md
  • docs/superpowers/specs/2026-06-04-goal-command-design.md
  • src/gpd/cli.py
  • src/gpd/commands/goal.md
  • src/gpd/core/goal_contract.py
  • src/gpd/core/goal_evidence.py
  • src/gpd/core/goal_gate.py
  • src/gpd/core/state.py
  • src/gpd/specs/references/help/detailed-command-reference.md
  • src/gpd/specs/templates/state-json-schema.md
  • src/gpd/specs/workflows/goal/goal-bootstrap.md
  • src/gpd/specs/workflows/help.md
  • tests/README.md
  • tests/core/test_cli_goal.py
  • tests/core/test_goal_contract.py
  • tests/core/test_goal_evidence.py
  • tests/core/test_goal_gate.py
  • tests/core/test_goal_smoke.py
  • tests/repo_graph_contract.json

Comment thread docs/superpowers/plans/2026-06-04-goal-command.md Outdated
Comment thread docs/superpowers/plans/2026-06-04-goal-command.md Outdated
Comment thread docs/superpowers/specs/2026-06-04-goal-command-design.md Outdated
Comment thread README.md
Comment thread src/gpd/cli.py Outdated
Comment thread src/gpd/cli.py
Comment thread src/gpd/cli.py
Comment on lines +4504 to +4515
claim_outcomes = collect_claim_outcomes(cwd)
phase_statuses = collect_phase_statuses(cwd)
all_phases_passed = bool(phase_statuses) and all(
status == "passed" for status in phase_statuses.values()
)
try:
summary = goal_gate_summary(
contract,
spent_usd=spent_usd,
claim_outcomes=claim_outcomes,
all_phases_passed=all_phases_passed,
)

@coderabbitai coderabbitai Bot Jun 4, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Scope phase verdicts to the active goal run before gating.

collect_phase_statuses(cwd) appears to scan the whole GPD/phases tree, and this code collapses every returned status into one all_phases_passed flag. That means an old failed verification elsewhere in the project can keep a brand-new goal permanently unachievable even when this goal's own criteria are satisfied. The gate needs a run-scoped phase set/window from the goal contract or run state before computing this boolean.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gpd/cli.py` around lines 4504 - 4515, The current all_phases_passed uses
collect_phase_statuses(cwd) which returns project-wide phases and can include
unrelated failed phases; scope the phase statuses to the active goal run before
computing the boolean. Update either collect_phase_statuses (or filter its
returned dict) to accept and use the active run identifier from the current
contract (e.g., contract.run_id or contract metadata) so you only keep phases
belonging to that run, then compute all_phases_passed from that filtered set and
pass it into goal_gate_summary (symbols: collect_phase_statuses, contract,
all_phases_passed, goal_gate_summary). Ensure the filtering uses the run-scoped
field present in the contract/run state and preserves existing behavior when no
run id is available.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially agree, leaving this open as a design follow-up rather than fixing it in this PR. Two mitigating points on severity: (1) all_phases_passed only feeds the non-default strict_criteria: false fallback, and that fallback can only promote pending criteria (missing claim evidence) to pass — criteria with real contract_results.claims evidence achieve the goal regardless of this flag. (2) The failure direction is conservative: a stale failed phase makes the fallback unavailable, so the run ends budget_stopped instead of wrongly achieved — it never overclaims. Properly run-scoping the boolean needs a phase-set snapshot recorded in the goal contract at bootstrap (a schema addition), which is a design decision for the author rather than a review fix. Until then, projects with pre-existing failed phases simply can't use the non-strict demo fallback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hvgazula, that’s a fair distinction. Given that all_phases_passed only affects the non-default strict_criteria: false fallback and fails conservatively, I agree this is not a correctness blocker for this PR. The remaining concern is better framed as a design/UX follow-up for demo fallback behavior, not a major review fix.

Would you like me to open a GitHub issue to track the run-scoped phase-set snapshot/schema addition for a future PR?

( (\/)
(•
•) thoughtfully noted )


✏️ Learnings added
Learnt from: hvgazula
Repo: psi-oss/get-physics-done PR: 254
File: src/gpd/cli.py:4511-4522
Timestamp: 2026-06-05T13:10:40.063Z
Learning: In `src/gpd/cli.py`, the `gpd goal gate/status` `all_phases_passed` boolean only affects the non-default `GoalContract.strict_criteria = false` fallback; strict verifier-gated criteria based on `contract_results.claims` can achieve a goal independently of this flag.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread src/gpd/core/state.py
Comment thread src/gpd/specs/templates/state-json-schema.md
hvgazula added 2 commits June 4, 2026 18:33
…w stem, category, budgets)

- Replace literal /gpd:goal slash form with runtime-neutral gpd:goal in
  cli.py error string and goal-bootstrap.md (runtime-abstraction boundary)
- Add top-level workflows/goal.md compatibility index so goal is workflow-backed
- Register gpd-goal -> execution in registry skill-category map
- Add measured COMMAND_BASELINES/WORKFLOW_BASELINES entries for goal
- Regenerate repo-graph contract + tests/README for the new workflow stem

Resolves 10 of 16 goal-registration suite failures; 6 runtime-projection
budget failures remain.
…and; wire goal command to same-stem index

Adding gpd:goal nudges several full-registry runtime-projection ceilings up
by one skill/command's worth of fixed-template pressure. Ratchet the advisory
budgets to just above the measured values:

- codex per-skill runtime-note aggregate cap 25_000 -> 26_000 (one more
  fixed-template note; cannot be compacted).
- COMMAND_ONLY_RUNTIME_PRESSURE_BUDGETS bridge_command_occurrences:
  codex 245 -> 251, copilot-cli 174 -> 179, opencode 174 -> 179 (goal's five
  gpd --raw snippets + auto-injected runtime note; Option B per the
  investigation — Option A cannot reach the budget since the injected note is
  mandatory).
- compare-experiment codex 7_700 -> 7_800, gemini 8_400 -> 8_500 (base dict).
- explain codex 6_150 -> 6_200 (both ADDITIONAL dicts); explain copilot-cli
  6_470 -> 6_550 in the diagnostics-budget dict.

Also cross-link the goal command to its same-stem compatibility index via an
inline (non-@) reference so test_commands_reference_same_stem_workflows passes
without expanding the index or adding bridge/shell pressure.
@hvgazula
hvgazula force-pushed the worktree-goal-command branch from e96947e to 1e79725 Compare June 5, 2026 12:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
docs/superpowers/plans/2026-06-04-goal-command.md (2)

42-42: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix heading level increment for markdown structure.

Line 42 jumps from # to ### without an intermediate ##, which violates MD001 and can break TOC/section parsing in some renderers.

🧰 Proposed fix
 ---
 
-### Task 1: Goal contract models and state field
+## Task 1: Goal contract models and state field
 
 **Files:**
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-06-04-goal-command.md` at line 42, The markdown
heading at "### Task 1: Goal contract models and state field" jumps from a
top-level "#" to "###", breaking heading sequence; change that heading to "##
Task 1: Goal contract models and state field" (or adjust the preceding top-level
heading to include an intermediate "##" section) so headings follow the expected
incremental levels and satisfy MD001/TOC parsers.

7-7: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Capitalize the framework name Typer.

"typer sub-app" should be "Typer sub-app" for correct product naming and doc polish.

🧰 Proposed fix
-**Architecture:** Pure-Python core modules hold the typed goal contract (`goal_contract.py`), the dual-cap gate + criteria decisions (`goal_gate.py`), and the VERIFICATION.md claim-outcome aggregator (`goal_evidence.py`). A typed `goal_contract` field is added to `ResearchState` (mirroring `project_contract`). A `gpd goal` typer sub-app exposes `status` and `gate`; `gpd validate goal-contract` follows the JSON+pydantic validator pattern of `review-ledger`/`referee-decision`. A new `goal.md` command descriptor delegates to its own `workflows/goal/goal-bootstrap.md` (the `autonomous` workflow and its stage manifest are NOT modified — its topology tests forbid that). No staged-init registration in v1.
+**Architecture:** Pure-Python core modules hold the typed goal contract (`goal_contract.py`), the dual-cap gate + criteria decisions (`goal_gate.py`), and the VERIFICATION.md claim-outcome aggregator (`goal_evidence.py`). A typed `goal_contract` field is added to `ResearchState` (mirroring `project_contract`). A `gpd goal` Typer sub-app exposes `status` and `gate`; `gpd validate goal-contract` follows the JSON+pydantic validator pattern of `review-ledger`/`referee-decision`. A new `goal.md` command descriptor delegates to its own `workflows/goal/goal-bootstrap.md` (the `autonomous` workflow and its stage manifest are NOT modified — its topology tests forbid that). No staged-init registration in v1.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-06-04-goal-command.md` at line 7, The doc uses
lowercase "typer" for the CLI framework; change occurrences to the proper
product name "Typer" (e.g., in the phrase "gpd goal typer sub-app" make it "gpd
goal Typer sub-app") and similarly update any other mentions in this paragraph
(references around goal_contract.py, goal_gate.py, goal_evidence.py, the `gpd
goal` sub-app and `gpd validate goal-contract` command descriptions) to use the
capitalized "Typer". Ensure only the product name casing is changed and no other
wording is altered.
docs/superpowers/specs/2026-06-04-goal-command-design.md (1)

61-67: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language tag to the fenced command block.

The fenced block is unlabeled, which trips markdownlint (MD040). Use bash or text for consistency with docs tooling.

🧰 Proposed fix
-```
+```bash
 /gpd:goal "Derive the dispersion relation for X and verify the long-wavelength limit" --budget-usd 5 --max-phases 6
 /gpd:goal --resume [--budget-usd 8] [--max-phases 10]
 gpd goal status        # terminal receipt: spend, phases, criteria, status
 gpd goal gate          # machine decision the run loop shells out to (--raw)
 gpd validate goal-contract <file.json|->   # typed validation surface
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/superpowers/specs/2026-06-04-goal-command-design.md around lines 61 -
67, The fenced command block in
docs/superpowers/specs/2026-06-04-goal-command-design.md is missing a language
tag (triggering MD040); update the opening triple-backtick for the block that
contains the /gpd:goal, gpd goal status, gpd goal gate, and gpd validate
goal-contract examples to include a language such as bash (e.g., ```bash) so the
block is labeled for markdownlint and docs tooling.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @docs/superpowers/plans/2026-06-04-goal-command.md:

  • Line 42: The markdown heading at "### Task 1: Goal contract models and state
    field" jumps from a top-level "#" to "###", breaking heading sequence; change
    that heading to "## Task 1: Goal contract models and state field" (or adjust the
    preceding top-level heading to include an intermediate "##" section) so headings
    follow the expected incremental levels and satisfy MD001/TOC parsers.
  • Line 7: The doc uses lowercase "typer" for the CLI framework; change
    occurrences to the proper product name "Typer" (e.g., in the phrase "gpd goal
    typer sub-app" make it "gpd goal Typer sub-app") and similarly update any other
    mentions in this paragraph (references around goal_contract.py, goal_gate.py,
    goal_evidence.py, the gpd goal sub-app and gpd validate goal-contract
    command descriptions) to use the capitalized "Typer". Ensure only the product
    name casing is changed and no other wording is altered.

In @docs/superpowers/specs/2026-06-04-goal-command-design.md:

  • Around line 61-67: The fenced command block in
    docs/superpowers/specs/2026-06-04-goal-command-design.md is missing a language
    tag (triggering MD040); update the opening triple-backtick for the block that
    contains the /gpd:goal, gpd goal status, gpd goal gate, and gpd validate
    goal-contract examples to include a language such as bash (e.g., ```bash) so the
    block is labeled for markdownlint and docs tooling.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: defaults

**Review profile**: CHILL

**Plan**: Pro Plus

**Run ID**: `d32a669a-b090-4652-a6ef-7d074b58cfa4`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e96947efa5c3b2e6ce8284227c31e14d9738d0ea and 1e79725d0cb7d33650d0011aef6e92fcc4eaa939.

</details>

<details>
<summary>📒 Files selected for processing (29)</summary>

* `CHANGELOG.md`
* `CONTRIBUTING.md`
* `README.md`
* `docs/superpowers/plans/2026-06-04-goal-command.md`
* `docs/superpowers/specs/2026-06-04-goal-command-design.md`
* `src/gpd/cli.py`
* `src/gpd/commands/goal.md`
* `src/gpd/core/goal_contract.py`
* `src/gpd/core/goal_evidence.py`
* `src/gpd/core/goal_gate.py`
* `src/gpd/core/state.py`
* `src/gpd/registry.py`
* `src/gpd/specs/references/help/detailed-command-reference.md`
* `src/gpd/specs/templates/state-json-schema.md`
* `src/gpd/specs/workflows/goal.md`
* `src/gpd/specs/workflows/goal/goal-bootstrap.md`
* `src/gpd/specs/workflows/help.md`
* `tests/README.md`
* `tests/adapters/projection_budget_support.py`
* `tests/adapters/test_codex.py`
* `tests/adapters/test_runtime_projected_prompt_parity.py`
* `tests/adapters/test_runtime_projection_diagnostics_budget.py`
* `tests/core/test_cli_goal.py`
* `tests/core/test_command_prompt_budget.py`
* `tests/core/test_goal_contract.py`
* `tests/core/test_goal_evidence.py`
* `tests/core/test_goal_gate.py`
* `tests/core/test_goal_smoke.py`
* `tests/repo_graph_contract.json`

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (9)</summary>

* CHANGELOG.md
* src/gpd/specs/workflows/help.md
* tests/README.md
* src/gpd/specs/references/help/detailed-command-reference.md
* tests/core/test_command_prompt_budget.py
* src/gpd/specs/workflows/goal.md
* README.md
* tests/adapters/test_runtime_projection_diagnostics_budget.py
* src/gpd/specs/workflows/goal/goal-bootstrap.md

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (17)</summary>

* tests/repo_graph_contract.json
* src/gpd/commands/goal.md
* tests/adapters/test_codex.py
* tests/adapters/test_runtime_projected_prompt_parity.py
* tests/adapters/projection_budget_support.py
* src/gpd/registry.py
* src/gpd/cli.py
* src/gpd/core/state.py
* tests/core/test_goal_evidence.py
* tests/core/test_goal_smoke.py
* src/gpd/specs/templates/state-json-schema.md
* src/gpd/core/goal_evidence.py
* tests/core/test_cli_goal.py
* src/gpd/core/goal_contract.py
* tests/core/test_goal_contract.py
* tests/core/test_goal_gate.py
* src/gpd/core/goal_gate.py

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

- resolve goal gate/status against the project root (mirror gpd state load)
- use runtime-aware command text in the missing-contract hint
- fail closed on malformed goal_contract during state normalization:
  drop the whole contract with an integrity finding instead of auto-healing
  individual fields (a pruned cap could silently weaken gate semantics)
- document gpd goal status / gpd goal gate in the README CLI reference
- add goal_contract to the JSON-only authority list in state-json-schema.md
- markdown polish in goal design/plan docs (Typer, heading levels, fence lang)
- ratchet the staged projection char budget for the schema template growth
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants