Skip to content

Add opt-in TEA workflow support to story automator#24

Closed
dickymoore wants to merge 19 commits into
bmad-code-org:mainfrom
dickymoore:feature/tea-story-automator
Closed

Add opt-in TEA workflow support to story automator#24
dickymoore wants to merge 19 commits into
bmad-code-org:mainfrom
dickymoore:feature/tea-story-automator

Conversation

@dickymoore

@dickymoore dickymoore commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add opt-in TEA workflow support to the story automator runtime
  • generate and snapshot a run-specific TEA policy instead of requiring the default flow to change
  • detect TEA-capable projects in preflight and ask for confirmation before enabling TEA for a run

Scope

  • opt-in TEA path only
  • standard mode remains unchanged by default
  • external TEA assets remain outside the bundled automator

Explicitly out of scope

  • no default-path behavior change
  • no artifact-level verification for TEA steps yet
  • no generic workflow-engine refactor
  • no checkpoint-preview integration into the automator run

Verification

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest tests.test_runtime_policy tests.test_state_policy_metadata tests.test_orchestrator_parse
  • bash scripts/smoke-test.sh

Summary by CodeRabbit

  • New Features

    • Opt‑in TEA workflow track per story with policy-driven step sequencing, TEA prompt/parse support, and CLI commands to compute/run policy selections and detect TEA vs standard tracks.
    • Named progress updates via a new state-progress helper that updates policy-defined columns.
  • Bug Fixes

    • More robust state/progress handling with clearer error payloads for invalid or missing policy snapshots.
  • Documentation

    • Templates and workflow docs updated with TEA guidance and TEA configuration placeholders.
  • Tests

    • Added TEA-focused tests and helpers covering policy loading, parsing, CLI flows, and state updates.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@dickymoore, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 14 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c02d9a89-b873-4941-a001-82d6886501cb

📥 Commits

Reviewing files that changed from the base of the PR and between 4118637 and e4fd975.

📒 Files selected for processing (1)
  • tests/test_runtime_policy.py

Walkthrough

Adds opt-in TEA (Test Execution Automation): TEA prompt/schema assets, runtime-policy extensions (inline overrides, step pruning, sequence helpers), CLI commands for run-policy and workflow detection, markdown progress updater (state-progress), agent/task wiring from pinned policy, updated orchestration docs/templates, and broad tests and test helpers.

Changes

TEA Workflow Opt-In Support

Layer / File(s) Summary
TEA data contracts
skills/bmad-story-automator/data/tea-story-automator/parse/tea_step.json, skills/bmad-story-automator/data/tea-story-automator/prompts/tea_step.md
Defines TEA step parse schema requiring status, summary, next_action and adds the TEA step prompt template with placeholders and instructions.
Runtime policy system extensions
skills/bmad-story-automator/src/story_automator/core/runtime_policy.py
Expands valid step names, adds inline-override merging, snapshot/shape loaders, step pruning, and helpers workflow_sequence/story_task_sequence and load_policy_shape_for_state.
Dynamic task generation from policy
skills/bmad-story-automator/src/story_automator/core/agent_config.py, skills/bmad-story-automator/src/story_automator/commands/orchestrator_epic_agents.py
Agents and epic-agent builders compute per-story task lists from the pinned runtime policy shape (story_task_sequence) and return structured policy_invalid errors on policy load failure.
CLI command dispatch
skills/bmad-story-automator/src/story_automator/cli.py
Registers build-run-policy and detect-workflow-track in the CLI, updates usage text, and imports the new state commands for tests.
State document & run-policy generation
skills/bmad-story-automator/src/story_automator/commands/state.py
Implements _build_run_policy, TEA asset/skill detection and completeness checks, snapshotting with inline overrides, teaConfigurationBlock support, policy-derived progress-table header/rows, and CLI wrappers cmd_build_run_policy and cmd_detect_workflow_track.
Progress tracking command infrastructure
skills/bmad-story-automator/src/story_automator/commands/orchestrator.py
Adds state-progress action with helpers _normalize_progress_key, _parse_markdown_cells, and _render_markdown_row to apply --set key=value updates to a markdown progress table and return structured JSON results.
Workflow orchestration steps & templates
skills/bmad-story-automator/steps-c/*, skills/bmad-story-automator/templates/state-document.md, skills/bmad-story-automator/workflow.md
Rewrote orchestration step docs to use orchestrator-helper state-progress, added TEA routing and preflight detection/selection, pinned-policy sequencing guidance, and injected {{teaConfigurationBlock}} placeholder in the state template; workflow docs document TEA opt-in semantics.
Comprehensive test coverage & helpers
tests/test_orchestrator_parse.py, tests/test_runtime_policy.py, tests/test_state_policy_metadata.py, tests/test_agent_config_model.py
Adds tests validating inline override merging, TEA step parsing/skill-install behavior, workflow-track detection, state-progress behavior, TEA columns rendering, agents-build pinned sequences, and regression tests for policy-invalid handling; includes helpers to install/write TEA skills/assets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • bmad-code-org/bmad-automator#16: Overlaps with changes to agents_build_action and task-building logic; both PRs modify per-story task generation and related code paths.

Suggested reviewers

  • bma-d

Poem

🐰 I stitched a TEA wing to the automator bright,

Prompts and schemas snug, policies set right,
Markdown hops forward as progress is scored,
Tasks follow policy — no paths ignored,
Sip tea and watch stories take flight! 🍵

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add opt-in TEA workflow support to story automator' directly and clearly describes the main change: adding opt-in TEA workflow support. It is specific, concise, and accurately summarizes the primary feature being introduced.
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 unit tests (beta)
  • Create PR with unit tests

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.

@dickymoore

Copy link
Copy Markdown
Contributor Author

Follow-up changes pushed in response to review findings, kept as tight as possible:

  • Replaced the remaining fixed-column progress-row rewrites with orchestrator-helper state-progress, which updates named progress columns in the state table. Reason: TEA sequences add columns like atdd, test-review, nfr, and trace, so the old hard-coded row rewrites could corrupt TEA state.
  • Added nfr to the resume routing for the review-phase path. Reason: a paused TEA run at currentStep: nfr must resume into the same review/test-quality segment instead of falling through to the wrong phase.
  • Tightened detect-workflow-track so an explicit TEA policy only counts as TEA-capable when the required TEA skills and external assets are actually present. Reason: preflight should not recommend TEA and then fail later during policy snapshot/materialization.
  • Kept the additional helper/test code ordered as extension-path logic rather than mixed into the core path. Reason: preserve the standard flow as the visually primary path and keep the TEA support scoped as an opt-in extension.

Validation:

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest tests.test_runtime_policy tests.test_state_policy_metadata tests.test_orchestrator_parse
  • 91 tests passed

@dickymoore

Copy link
Copy Markdown
Contributor Author

Final update before readying this PR:

Latest fixes kept scope tight and addressed the remaining review findings:

  • Legacy configs with no workflowTrack now explicitly stay on the standard sequence even when a project-level TEA override exists.
  • Explicit TEA override detection now validates the actual merged policy shape rather than only checking TEA-looking step names plus skills/assets.
  • Explicit TEA overrides that include nfr now require the NFR skill during detection.
  • Standard-mode policy resolution now ignores inactive TEA override steps so default mode cannot be poisoned by unused TEA contracts.

Validation after the final fixes:

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest tests.test_state_policy_metadata tests.test_runtime_policy tests.test_orchestrator_parse
  • 100 tests passed
  • direct edge-case checks passed for:
    • legacy config staying standard with an explicit TEA override
    • rejecting explicit TEA overrides with missing step contracts
    • rejecting explicit TEA overrides with missing nfr

A final focused review pass returned no findings.

@dickymoore dickymoore marked this pull request as ready for review May 24, 2026 10:25
@dickymoore dickymoore requested a review from bma-d as a code owner May 24, 2026 10:25
@augmentcode

augmentcode Bot commented May 24, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds opt-in TEA workflow support to the story automator by selecting a per-run workflow track and snapshotting the resolved policy into the state document so execution follows a pinned sequence.

Changes:

  • Introduces bundled generic TEA prompt + parse schema fallbacks under data/tea-story-automator.
  • Adds CLI commands build-run-policy (generate inline policy override + notes) and detect-workflow-track (recommend TEA vs standard based on project signals, assets, and skills).
  • Build-state-doc now snapshots the effective policy with an inline override and renders the progress table columns from the pinned workflow sequence.
  • Adds orchestrator-helper state-progress to update named progress columns safely for variable (TEA) sequences.
  • Agent plan generation (agents-build/build_agents_file) now derives tasks-in-scope from the pinned state policy sequence.
  • Runtime policy loader now supports TEA step names, inline overrides, and prunes unreferenced step contracts; improves error wrapping for unreadable policy sources.
  • Workflow docs updated to describe the pinned-policy rule and TEA v1 scope/limitations.
  • Extensive new unit tests cover TEA detection, run-policy generation, policy snapshot loading, parsing, and progress updates.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode 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.

Review completed. 4 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread skills/bmad-story-automator/src/story_automator/commands/orchestrator.py Outdated
Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated

@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: 2

🧹 Nitpick comments (2)
skills/bmad-story-automator/steps-c/step-03-execute.md (1)

208-212: 💤 Low value

Consider redundant progress update for create=done.

Line 210 sets create=done again, but this was already set at line 151 when the create step completed. While this defensive redundancy ensures consistency, it's unnecessary and could be simplified to only update dev=done.

🤖 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 `@skills/bmad-story-automator/steps-c/step-03-execute.md` around lines 208 -
212, The progress update call to the state-progress helper is redundantly
re-setting create=done; modify the invocation of "$scripts" orchestrator-helper
state-progress (the command that passes --story "${story_id}" and --set flags)
to remove the --set create=done flag and only include --set dev=done and --set
status=in-progress so the create step isn’t updated twice.
skills/bmad-story-automator/steps-c/step-02a-preflight-config.md (1)

73-92: ⚡ Quick win

Clarify validate-create-story selection behavior.

Lines 78-82 state that validate-create-story is "advisory only and is not automated in v1", yet line 86 allows users to include it in selected_optional_steps. This could confuse users who select it expecting automated execution.

Consider either:

  • Removing it from the selectable options and documenting it as future-scoped
  • Adding explicit guidance that selecting it records user intent but doesn't trigger automation 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 `@skills/bmad-story-automator/steps-c/step-02a-preflight-config.md` around
lines 73 - 92, The wording around validate-create-story is ambiguous: update the
TEA options block so that validate-create-story is either removed from
selectable optional steps or clearly marked as non-automated intent;
specifically, leave selected_optional_steps as the list of zero-or-more of retro
and nfr only (remove validate-create-story from that enumerated selectable list)
and add one sentence after the list explaining that selecting
validate-create-story (if still referenced elsewhere) only records user intent
and will not trigger any automated action in v1 — reference the symbols
selected_optional_steps, validate-create-story, and workflow_track when making
this clarification.
🤖 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 `@skills/bmad-story-automator/src/story_automator/commands/orchestrator.py`:
- Around line 526-530: The --set parsing block in orchestrator.py can raise
ValueError when args[idx + 1] lacks an '='; before calling split("=", 1)
validate that "=" is present (e.g., if "=" not in args[idx + 1]) and handle it
by raising a clear ValueError or argparse-style error mentioning the bad
argument, or skip with a logged warning; then only call key, value = args[idx +
1].split("=", 1) and continue updating updates[_normalize_progress_key(key)] =
value and advancing idx. Ensure the fix targets the block handling args, idx,
updates and uses _normalize_progress_key to locate where to apply the
validation.

In `@skills/bmad-story-automator/src/story_automator/commands/state.py`:
- Around line 633-645: The branch currently gates TEA on asset/skill heuristics
even when an explicit override exists; change the condition so that when
explicit_policy and explicit_policy_valid (from _explicit_tea_policy_valid) are
true you accept the resolved explicit policy as source-of-truth for capability
(i.e., do not require assets_ok and not missing_skills to set
tea_capable/recommended_track). If you still need missing_assets/missing_skills
in the payload, compute them from the resolved explicit policy returned by
_explicit_tea_policy_valid (or mark them advisory) instead of using
_tea_assets_complete() and _tea_skill_availability() which only use hard-coded
roots/aliases; update the branch that currently checks explicit_policy &&
explicit_policy_valid && assets_ok && not missing_skills to rely on
explicit_policy_valid and use the resolved-policy-derived checks for advisory
fields.

---

Nitpick comments:
In `@skills/bmad-story-automator/steps-c/step-02a-preflight-config.md`:
- Around line 73-92: The wording around validate-create-story is ambiguous:
update the TEA options block so that validate-create-story is either removed
from selectable optional steps or clearly marked as non-automated intent;
specifically, leave selected_optional_steps as the list of zero-or-more of retro
and nfr only (remove validate-create-story from that enumerated selectable list)
and add one sentence after the list explaining that selecting
validate-create-story (if still referenced elsewhere) only records user intent
and will not trigger any automated action in v1 — reference the symbols
selected_optional_steps, validate-create-story, and workflow_track when making
this clarification.

In `@skills/bmad-story-automator/steps-c/step-03-execute.md`:
- Around line 208-212: The progress update call to the state-progress helper is
redundantly re-setting create=done; modify the invocation of "$scripts"
orchestrator-helper state-progress (the command that passes --story
"${story_id}" and --set flags) to remove the --set create=done flag and only
include --set dev=done and --set status=in-progress so the create step isn’t
updated twice.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b9b8934-08dc-444c-b652-e94a885b71b8

📥 Commits

Reviewing files that changed from the base of the PR and between 3b01cfd and 4c8b7b4.

📒 Files selected for processing (18)
  • skills/bmad-story-automator/data/tea-story-automator/parse/tea_step.json
  • skills/bmad-story-automator/data/tea-story-automator/prompts/tea_step.md
  • skills/bmad-story-automator/src/story_automator/cli.py
  • skills/bmad-story-automator/src/story_automator/commands/orchestrator.py
  • skills/bmad-story-automator/src/story_automator/commands/orchestrator_epic_agents.py
  • skills/bmad-story-automator/src/story_automator/commands/state.py
  • skills/bmad-story-automator/src/story_automator/core/agent_config.py
  • skills/bmad-story-automator/src/story_automator/core/runtime_policy.py
  • skills/bmad-story-automator/steps-c/step-01b-continue.md
  • skills/bmad-story-automator/steps-c/step-02a-preflight-config.md
  • skills/bmad-story-automator/steps-c/step-03-execute.md
  • skills/bmad-story-automator/steps-c/step-03a-execute-review.md
  • skills/bmad-story-automator/steps-c/step-03b-execute-finish.md
  • skills/bmad-story-automator/templates/state-document.md
  • skills/bmad-story-automator/workflow.md
  • tests/test_orchestrator_parse.py
  • tests/test_runtime_policy.py
  • tests/test_state_policy_metadata.py

Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@dickymoore

Copy link
Copy Markdown
Contributor Author

Update since the last CodeRabbit-reviewed commit (4c8b7b4):

  1. TEA review follow-ups and explicit-policy hardening
  • added structured rejection for malformed state-progress --set arguments instead of allowing a crash path
  • normalized workflowTrack in the explicit policyOverride branch
  • changed explicit TEA detection to trust a successfully resolved explicit policy, instead of re-gating valid explicit overrides with hard-coded TEA heuristics
  • fixed explicit-policy detection metadata so mixed valid TEA asset roots are reported as a display string instead of collapsing to an empty value
  • clarified the preflight wording so selected_optional_steps only enumerates retro and nfr, and validate-create-story stays explicitly advisory/non-automated in v1
  • removed the redundant create=done progress update in the dev-complete flow
  1. Merge resolution against upstream/main
  • merged upstream/main into this branch to clear the PR conflict state
  • preserved the TEA sequence-driven task selection in agents-build and related planning paths
  • preserved upstream model-selection support in the same files during conflict resolution
  1. CI fix
  • fixed the failing Actions test path caused by loading full policy assets when only the workflow sequence was needed for agent-plan generation
  • introduced a narrow sequence-only policy loader in runtime_policy.py for state-driven task sequencing
  • switched the two task-sequence call sites to use that shape-only loader so they no longer require installed skills/contracts in pure config tests

Validation on the current head (162a450):

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest discover -s tests -> 265 tests passed
  • npm run test:smoke -> smoke ok
  • PYTHONPATH=skills/bmad-story-automator/src python3 -m story_automator --help -> ok
  • post-fix subreviews: 2 independent passes, both with no findings

Scope note:

  • all fixes after 4c8b7b4 were kept focused on TEA review feedback, explicit-policy correctness, merge resolution, and the CI regression introduced by the upstream merge.

@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@augmentcode augmentcode 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.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@augmentcode augmentcode 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.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py
@dickymoore

Copy link
Copy Markdown
Contributor Author

Latest follow-up for PR reviews is now on a0a5f62.

This round stayed narrowly scoped to three items:

  • wrap raw bundled-policy read failures in PolicyError
  • prevent malformed divider rows from inflating state-metrics
  • make the Story column immutable in state-progress

Validation on this head:

  • python3 -m unittest tests.test_runtime_policy tests.test_state_policy_metadata
  • python3 -m unittest discover -s tests
  • both passed locally (274 total tests in the full suite)

All currently open review threads for this round have been replied to and resolved.

@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@augmentcode augmentcode 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.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py
Comment thread skills/bmad-story-automator/src/story_automator/commands/state.py Outdated
@dickymoore

Copy link
Copy Markdown
Contributor Author

Latest follow-up is now on 05f3ff0.

This round stayed limited to two state-layer issues:

  • reject non-object JSON in build-run-policy
  • surface present-but-invalid explicit override files during TEA detection

Validation on this head:

  • python3 -m unittest tests.test_state_policy_metadata tests.test_runtime_policy
  • python3 -m unittest discover -s tests
  • both passed locally (276 tests in the full suite)

Replying on the two new threads now and resolving them.

@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@augmentcode augmentcode 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.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread skills/bmad-story-automator/src/story_automator/core/runtime_policy.py Outdated
Comment thread skills/bmad-story-automator/src/story_automator/commands/orchestrator.py Outdated
@dickymoore

Copy link
Copy Markdown
Contributor Author

Addressed the latest unresolved review threads in 4118637 with no scope expansion beyond the permission/error-handling paths they called out.

Changes in this round:

  • wrapped unreadable project override reads in load_effective_policy() as structured PolicyError
  • made both load_policy_snapshot() and load_policy_shape_for_state() distinguish missing snapshots from unreadable stat failures
  • made state-progress return structured JSON for state-file stat, read, and write permission failures
  • updated the agent-config expectations to the newer precise policy snapshot missing wording
  • added focused regressions for all of the above

Validation:

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest tests.test_runtime_policy tests.test_state_policy_metadata tests.test_agent_config_model
  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest discover -s tests
  • focused local review pass returned no findings

@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@bma-d bma-d left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the contribution. The opt-in TEA workflow direction is useful, but I’m requesting changes because the current implementation centralizes too much policy logic in the state command path and leaves several execution/policy contracts inconsistent.

I left inline comments with concrete repros where the issue is executable. The two blocking themes are: keep the pinned workflow policy authoritative, and move TEA policy generation/detection out of broad command/helper files into a single owner with focused contract coverage.

lowered = value.strip().lower()
if lowered in {"1", "true", "yes", "y", "on"}:
return True
if lowered in {"0", "false", "no", "n", "off"}:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] This command module is now taking ownership of TEA policy selection and contract construction. The PR adds TEA asset-root probing (272-332), prompt/schema selection (335-345), skill alias resolution (347-368), full step contract generation (371-451), run-policy branching (454-542), explicit policy detection (571-612), and workflow recommendation (696-758) here. Static repro: state.py grows from 308 LOC on origin/main to 908 LOC on this PR. Please move TEA capability detection/policy selection/contract generation behind a core policy-selection module or data-backed policy path, and keep this command focused on state-doc IO/rendering.

"nfr": ("bmad-testarch-nfr", "bmad-tea-testarch-nfr"),
}

STEP_DISPLAY_NAMES = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] These display labels duplicate policy-derived data. STEP_DISPLAY_NAMES hard-codes labels even though policy step contracts carry labels, while _build_run_policy() hard-codes TEA sequence generation and orchestrator.py adds another alias table for progress columns. Caveat: the runtime step allowlist can stay as schema validation, but labels/progress headers and generated sequence should come from one policy source instead of multiple Python tables.

@@ -461,6 +468,692 @@ def test_build_state_doc_returns_json_on_policy_snapshot_failure(self) -> None:
self.assertFalse(payload["ok"])
self.assertEqual(payload["error"], "policy_snapshot_failed")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] The TEA tests are being appended to an already broad mixed test file. Static repro: this file grows from 555 LOC on origin/main to 1370 LOC on the current PR head. The same file now mixes state policy metadata, orchestrator helper behavior, tmux command rendering, agent config, TEA detection/run-policy/progress, and TEA fixtures. Please split TEA policy/detection/progress tests and reusable TEA fixtures into focused files.

### A.1 ATDD
*Run only if the pinned policy sequence includes `atdd`*

Use the same spawn/monitor/parse pattern as other session-exit steps:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] The ATDD path bypasses the per-task agent/model resolver used by the adjacent create/dev paths. create resolves with resolve_agent_for_task and conditionally passes --model, but this new ATDD block spawns/builds with $current_agent directly and never resolves atdd or applies the primary model. The TEA quality loop in step-03a has the same shape. Please route every policy-defined TEA step through the same resolver/model path as the standard steps.



def _render_markdown_row(cells: list[str]) -> str:
return "| " + " | ".join(cells) + " |"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] orchestrator-helper now owns markdown progress-table parsing and mutation. _state_progress finds the table by line.startswith("| Story "), splits cells with line.split("|"), finds the story row by markdown prefix, rewrites the row, and writes the state file. That duplicates state document schema ownership outside the state-doc layer. Please keep this CLI as a thin entry point and move progress-table parse/update/render behind the canonical state/state-document layer.

@@ -140,9 +195,11 @@ config_json=$(jq -n \
--arg currentStep "preflight" \
--arg aiCommand "$agent_cmd" \
--arg customInstructions "$custom_instructions" \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] This --argjson requires selected_optional_steps to already be valid JSON, but the TEA collection instructions only say “zero or more of retro, nfr”. Repro: selected_optional_steps='retro nfr'; jq -n --argjson selectedOptionalSteps "$selected_optional_steps" ... fails with jq: invalid JSON text passed to --argjson. This works only if the executor happens to store a JSON array like ["retro"]; please make that explicit or delegate config JSON construction to a helper.

For the TEA track, state clearly:
- **Mandatory automated TEA core:** `atdd`, `test_automate`, `test_review`, `trace`
- **Optional automated TEA add-on:** `nfr`
- **Optional epic-level add-on:** `retro`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] This introduces retro as an optional TEA add-on, but the finish path still triggers retro solely from epic completion (step-03b-execute-finish.md: trigger_retro=true then spawn retro) and does not gate that block on the pinned workflow sequence containing retro. The trigger block existed before, but this PR creates the optional policy/selection contract without honoring it. A TEA run that did not select retro can still spawn the retrospective. Please either gate the finish step on the policy sequence or remove the optional retro path and make it explicitly always-on.

config = json.loads(config_json)
except json.JSONDecodeError:
write_json({"ok": False, "error": "invalid_config_json"})
return 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] build-run-policy can return ok:true for a TEA run even when mandatory TEA core skills/assets are missing. Repro on the current PR: with no TEA skills installed, cmd_build_run_policy(["--config-json", "{"workflowTrack":"tea"}"]) returns ok:true with create, atdd, dev, test_automate, test_review, trace, review and bmad-testarch-* contracts. The later state-doc snapshot path then fails on missing required skill assets. Please validate the generated override through the same policy resolution path before returning success, or check mandatory TEA capability in _build_run_policy.

```bash
session=$("$scripts" tmux-wrapper spawn atdd {epic} {story_id} \
--agent "$current_agent" \
--command "$("$scripts" tmux-wrapper build-cmd atdd {story_id} --agent "$current_agent" --state-file "$state_file")")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] This parses the ATDD result into parsed, but the following branch reads next_action without ever assigning it from parsed. Repro: parsed='{ "next_action":"proceed" }'; [ "$next_action" = proceed ] does not proceed (and fails under set -u). The standard dev path below correctly does next_action=$(echo "$parsed" | jq -r '.next_action'). Please bind next_action (and any other normalized fields) before branching, ideally through one shared session-exit helper/pattern used by all TEA steps.

track = str(config.get("workflowTrack") or "standard").strip().lower()
if track not in {"standard", "tea"}:
track = "standard"
selected = set(_normalize_option_list(config.get("selectedOptionalSteps")))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] A valid explicit project TEA policy is detected, but state creation still generates a fresh TEA policyOverride for any workflowTrack == "tea". Because cmd_build_state_doc() snapshots with this inline override and load_effective_policy() merges inline override after the project override, generated policy wins. Repro: an explicit project sequence create, atdd, dev, trace, review with custom atdd label snapshots as generated create, atdd, dev, test_automate, test_review, trace, review, and the label becomes atdd. Please separate track selection from policy generation and snapshot explicit TEA project policy as-is unless a caller supplies an explicit per-run override.

@dickymoore

Copy link
Copy Markdown
Contributor Author

Follow-up on top of 4118637: e4fd975 is test-only and fixes the remaining macOS CI failure.

What changed:

  • stabilized test_unreadable_override_file_is_wrapped_as_policy_error by comparing resolved paths, so the patched _read_json target is matched consistently on macOS and Linux

Validation on this head:

  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest tests.test_runtime_policy
  • PYTHONPATH=skills/bmad-story-automator/src python3 -m unittest discover -s tests
  • focused local review pass returned no findings

@dickymoore

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@dickymoore

Copy link
Copy Markdown
Contributor Author

augment review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 1

🧹 Nitpick comments (1)
skills/bmad-story-automator/src/story_automator/commands/orchestrator.py (1)

590-594: ⚡ Quick win

Persist the updated state file atomically.

Line 591 rewrites the full orchestration document in place. If this helper is interrupted after truncation, the state file can be left partial and future resume/parse steps will fail. Please use atomic_write here, as you already do in _marker.

♻️ Proposed fix
     try:
-        Path(state_file).write_text("\n".join(lines) + "\n", encoding="utf-8")
+        atomic_write(state_file, "\n".join(lines) + "\n")
     except OSError:
         print_json({"ok": False, "error": "state_file_unwritable"})
         return 1
🤖 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 `@skills/bmad-story-automator/src/story_automator/commands/orchestrator.py`
around lines 590 - 594, The current code writes the orchestration state in place
via Path(state_file).write_text(...) which can leave a truncated/partial file on
interruption; replace that write with the existing atomic_write helper used by
_marker so the new content is written to a temp file and atomically moved into
place (e.g. call atomic_write(state_file, "\n".join(lines) + "\n",
encoding="utf-8")), keep the same OSError handling to print_json and return 1,
and ensure you import or reuse the same atomic_write symbol used in _marker so
behavior matches the rest of the module.
🤖 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 `@skills/bmad-story-automator/src/story_automator/commands/state.py`:
- Around line 698-699: The code currently sets teaDetected based on
explicit_override_present (from _explicit_policy_path) which makes a
standard-only story-automator.policy.json flip TEA UX; update the teaDetected
computation so it only uses TEA-specific evidence from the explicit policy
payload returned by _explicit_policy_payload(project_root) (e.g., inspect the
payload for TEA steps/flags and/or explicit_override_error TEA-related info) and
ignore plain presence of an override file; locate uses of
explicit_override_present and _explicit_policy_payload (also at the other
occurrence around the block at the previously noted lines) and change the
boolean used for teaDetected to a TEA-only predicate derived from the payload
instead of the file-existence flag.

---

Nitpick comments:
In `@skills/bmad-story-automator/src/story_automator/commands/orchestrator.py`:
- Around line 590-594: The current code writes the orchestration state in place
via Path(state_file).write_text(...) which can leave a truncated/partial file on
interruption; replace that write with the existing atomic_write helper used by
_marker so the new content is written to a temp file and atomically moved into
place (e.g. call atomic_write(state_file, "\n".join(lines) + "\n",
encoding="utf-8")), keep the same OSError handling to print_json and return 1,
and ensure you import or reuse the same atomic_write symbol used in _marker so
behavior matches the rest of the 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b999e135-a366-46f1-9584-1c662c5b6572

📥 Commits

Reviewing files that changed from the base of the PR and between c1ff3e9 and 4118637.

📒 Files selected for processing (6)
  • skills/bmad-story-automator/src/story_automator/commands/orchestrator.py
  • skills/bmad-story-automator/src/story_automator/commands/state.py
  • skills/bmad-story-automator/src/story_automator/core/runtime_policy.py
  • tests/test_agent_config_model.py
  • tests/test_runtime_policy.py
  • tests/test_state_policy_metadata.py

Comment on lines +698 to +699
explicit_override_present = _explicit_policy_path(project_root).is_file()
_, explicit_override_error = _explicit_policy_payload(project_root)

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 | 🟡 Minor | ⚡ Quick win

Keep teaDetected scoped to TEA signals.

A standard-only story-automator.policy.json now flips teaDetected to true because this payload keys off explicit_override_present, not TEA-specific evidence. That can light up TEA preflight UX even when the override contains no TEA steps.

Suggested fix
-        "teaDetected": explicit_policy or explicit_override_present or bool(signals),
+        "teaDetected": explicit_policy or bool(signals),

Also applies to: 749-750

🤖 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 `@skills/bmad-story-automator/src/story_automator/commands/state.py` around
lines 698 - 699, The code currently sets teaDetected based on
explicit_override_present (from _explicit_policy_path) which makes a
standard-only story-automator.policy.json flip TEA UX; update the teaDetected
computation so it only uses TEA-specific evidence from the explicit policy
payload returned by _explicit_policy_payload(project_root) (e.g., inspect the
payload for TEA steps/flags and/or explicit_override_error TEA-related info) and
ignore plain presence of an override file; locate uses of
explicit_override_present and _explicit_policy_payload (also at the other
occurrence around the block at the previously noted lines) and change the
boolean used for teaDetected to a TEA-only predicate derived from the payload
instead of the file-existence flag.

@augmentcode augmentcode 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.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

override = _read_json(override_path) if override_path.is_file() else {}
policy = _deep_merge(bundled, override)
try:
override = _read_json(override_path) if override_path.is_file() else {}

@augmentcode augmentcode Bot May 26, 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.

skills/bmad-story-automator/src/story_automator/core/runtime_policy.py:44 — override_path.is_file() can raise OSError/PermissionError (e.g., unreadable _bmad/bmm), which would bypass the PolicyError wrapping and can crash callers expecting structured policy_invalid JSON. Consider guarding the is_file() probe similarly to _read_json(...) so unreadable stat failures also become PolicyErrors.

Other locations where this applies: skills/bmad-story-automator/src/story_automator/commands/state.py:577, skills/bmad-story-automator/src/story_automator/commands/state.py:698

Severity: medium

Other Locations
  • skills/bmad-story-automator/src/story_automator/commands/state.py:577
  • skills/bmad-story-automator/src/story_automator/commands/state.py:698

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

elif arg == "--config-json" and idx + 1 < len(args):
config_json = args[idx + 1]
if config_file and file_exists(config_file):
config_json = read_text(config_file)

@augmentcode augmentcode Bot May 26, 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.

skills/bmad-story-automator/src/story_automator/commands/state.py:554 — cmd_build_run_policy() reads --config-file with read_text(config_file) without handling OSError, so an existing-but-unreadable config will likely raise and print a traceback instead of returning structured JSON. Consider catching read/stat failures and returning a specific config_file_unreadable-style error payload.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

print_json({"ok": False, "error": "invalid_set_argument", "argument": raw_update})
return 1
key, value = raw_update.split("=", 1)
updates[_normalize_progress_key(key)] = value

@augmentcode augmentcode Bot May 26, 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.

skills/bmad-story-automator/src/story_automator/commands/orchestrator.py:539 — _state_progress() writes value directly into a Markdown table cell; if it contains | or newlines it can corrupt the progress table and break future parsing/updates. Consider validating/sanitizing --set values to a safe single-line, no-pipe subset before updating the row.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@dickymoore dickymoore marked this pull request as draft May 26, 2026 08:43
@bma-d

bma-d commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Closing since worked on in #28

@bma-d bma-d closed this Jun 12, 2026
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.

2 participants