Skip to content

STO-402: define deterministic Squad runtime contract#23

Open
stone16 wants to merge 4 commits into
mainfrom
agent/hao/sto-402-squad-runtime-contract
Open

STO-402: define deterministic Squad runtime contract#23
stone16 wants to merge 4 commits into
mainfrom
agent/hao/sto-402-squad-runtime-contract

Conversation

@stone16

@stone16 stone16 commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Originating Multica issue: STO-402
Original author: @hao

Summary

Makes complex work enter Multica through one exact owning Squad; defines one idempotent parent-result comment plus verified typed metadata, Squad activity, and status order; uses native staged checkpoint graphs; and makes supporting-file rollout fail before contract activation. The final correction also closes active PR-sweep, PM, auto-harness, dual-evaluator, duplicate-trigger, and partial-rollout bypasses.

Why

Closes STO-402 and implements the accepted corrections from STO-398. Rejected head cb3bc5dcbaa1ee7c0c0971604e6fd62ba5657224 retained active callers that closed without the result contract, created unowned or directly assigned multi-lane children, recovered correlation markers from only one trigger thread, accepted one verdict for a dual gate, and discovered supporting-file failures after contract writes. Any one of those paths violates deterministic Squad ownership or closure.

Approach

The base STO-402 change keeps the mirrored company contract, workspace context, operating model, Squad Issue template, native stage validator, monitoring/recovery rules, recursive cancellation, honest fallback rule, and executable quick starts aligned. Correction round 2 changes only the affected callers/contracts/tests:

  • .github/scripts/pr-sweep.sh now recovers/posts one correlation-marked result, writes and verifies all five metadata keys, records Squad activity, and only then marks its review issue done. .github/workflows/pr-sweep.yml pins Multica CLI 0.4.11 plus the official release checksum because that is the first repository-tested caller version exposing metadata/activity.
  • agents/pm/skill.md assigns split children to one exact Squad UUID and copies the complete templates/squad-issue.md contract.
  • agents/orchestrator/skill.md makes result recovery parent-wide, records and reconciles two distinct Evaluator identities, and assigns auto-harness children to the parent's Squad.
  • templates/auto-harness.md consumes exact Squad ownership for checkpoint and E2E children while retaining validated stage / depends_on and todo / backlog arguments.
  • scripts/sync-multica.sh validates all existing supporting-file inventories before the first write, upserts required files before workspace/skill-body/agent/attachment activation, stops immediately on file failure, and rejects creation of a missing skill that already requires files because the API cannot write its file before creating its body.

Accepted choice: Preserve the existing architecture and close every active caller/failure-path gap in one author-produced head.

Rejected alternatives:

  • Approve the prior head because its original seven remediations pass; the six reproduced caller/failure paths bypass those general rules.
  • Reject dual_evaluator; the current roster has two Evaluator identities and the accepted contract explicitly requires that gate for high-risk work.
  • Continue creating a missing skill and attach its required file afterward; a failed upsert would expose an incomplete contract.
  • Modify or merge PR Codify Squad invocation fallback topology #22; it is another author's contradictory fallback proposal and remains a human merge gate.

Constraint: One bypass or one partially activated contract is enough to make the runtime non-deterministic.

Final correction round 2 — finding resolution

Branch: agent/hao/sto-402-squad-runtime-contract
Final immutable head: 89be1bab6a49a63ab6ef6d4148efcf398abad70e
Rejected head retained only for before-evidence: cb3bc5dcbaa1ee7c0c0971604e6fd62ba5657224

Finding Resolution
PR-sweep deterministic close .github/scripts/pr-sweep.sh:1015-1111 implements marker recovery/result → five verified metadata keys → Squad activity → status. tests/pr-sweep.test.sh:1088-1118 asserts order and parent-wide result reuse; :1663-1692 proves failures do not produce a terminal consensus or raw close.
PM exact-Squad/template splitting agents/pm/skill.md:162-229 resolves an owning Squad UUID, uses --assignee-id, and copies every Squad Issue section. tests/squad-runtime-contract.test.py:77-84 rejects the old empty-assignee/short-body path.
Parent-wide correlation recovery agents/orchestrator/skill.md:153 searches all parent comments before initial/retry writes and reuses a match from a different top-level trigger. .github/scripts/pr-sweep.sh:539-558 and tests/pr-sweep.test.sh:1108-1118 execute the same duplicate-trigger invariant.
Auto-harness Squad ownership agents/orchestrator/skill.md:213-227 and templates/auto-harness.md:142-188,220-239 assign checkpoint/E2E children to the parent's exact Squad using templates/squad-issue.md; the leader then activates Engineer/Evaluator lanes. tests/squad-runtime-contract.test.py:197-202,249-257 rejects direct Engineer assignment while retaining graph arguments.
Two-distinct-verdict dual evaluation agents/orchestrator/skill.md:70-79 records two expected Evaluator UUIDs, treats duplicate identity delivery as retry, waits for both verdicts, requires two PASS results, and routes either FAIL to the original executor. tests/squad-runtime-contract.test.py:260-268 locks those transitions.
Apply preflight / no partial rollout scripts/sync-multica.sh:685-809 validates all inventories before writes and runs supporting-file upserts before activation; :320-401 stops the file phase on error. tests/sync-multica.test.sh:297-334 proves missing-skill, unmanaged-file apply, and injected upsert failure paths have no workspace/skill-body/agent/attachment writes.

All seven prior remediations remain: the bounded serialized PR-sweep exception, lost-response recovery, specialized deterministic close, recursive descendant cancellation, exact fallback eligibility, executable quick starts, and producer → validator → consumer checkpoint graph preservation.

Rollout plan — not performed

  1. Require non-author Engineer and independent Evaluator approval on exactly 89be1bab6a49a63ab6ef6d4148efcf398abad70e.
  2. Require a human decision that PR Codify Squad invocation fallback topology #22 must not merge as a contradictory fallback contract.
  3. After merge and separate rollout authorization, run exact-mapped topology/content dry-runs from clean main == origin/main.
  4. Upsert the required Orchestrator supporting file first; only a successful file phase may activate workspace context, skill body, agent instructions, or attachment.
  5. Run fresh topology/content --verify, then exercise one disposable Squad result and both dual-evaluator identities.

Duplicate triggers use the same stable correlation ID and parent-wide marker lookup. One match reuses the original result comment UUID; more than one match stops closure for human repair. A changed PR head uses a new correlation and requires two new lane verdicts.

How I Tested

End-to-end and structural cases

Case Test file:line Assertion
PR-sweep close order and retry tests/pr-sweep.test.sh:1088 Result comment, verified five-key metadata, activity, then done; failed close emits no terminal sentinel.
Duplicate-trigger result recovery tests/pr-sweep.test.sh:1108 Existing result from another trigger is reused parent-wide; no second comment and no --thread lookup.
PM exact Squad split tests/squad-runtime-contract.test.py:77 Exact Squad UUID plus complete Squad Issue body; empty assignee is rejected.
Auto-harness graph + ownership tests/squad-runtime-contract.test.py:160 and :249 Stage 1 prerequisite and Stage 2 dependent preserve graph/create args and both belong to the owning Squad.
Dual-evaluator reconciliation tests/squad-runtime-contract.test.py:260 Two distinct author UUIDs and both verdicts are required; one PASS cannot close.
Unmanaged-file apply preflight tests/sync-multica.test.sh:307 Apply exits before every remote contract write.
Supporting-file upsert failure tests/sync-multica.test.sh:326 Upsert is attempted first; workspace, skill body, agent, and attachment remain untouched.
Missing skill with required file tests/sync-multica.test.sh:297 Apply fails before skill creation/activation because file-before-body cannot be guaranteed.
Original seven remediations tests/squad-runtime-contract.test.py:87-306 Fallback, marker, close order, graph validation, recovery, and recursive cancellation remain green.

Failing-before output on rejected head

The final structural test file was copied into a detached cb3bc5d worktree and run against that head:

$ CONTRACT_ROOT=<detached-cb3bc5d-worktree> python3 tests/squad-runtime-contract.test.py
PASS: test_mirrored_company_contract
PASS: test_pr_sweep_caller_compatibility
FAIL: test_pm_split_uses_exact_squad_contract:
PASS: test_fallback_eligibility_contract
FAIL: test_lost_response_result_idempotency:
PASS: test_final_result_schema_and_order
PASS: test_specialized_close_order
PASS: test_native_stage_contract
FAIL: test_checkpoint_plan_graph_contract:
FAIL: test_auto_harness_uses_squad_ownership:
FAIL: test_dual_evaluator_requires_two_distinct_verdicts:
PASS: test_monitoring_and_recovery_contract
PASS: test_recursive_descendant_cancellation
FAIL: 5 Squad runtime contract test(s)

Ryan and Evaluator-A independently reproduced the old apply path exiting 1 only after workspace update, skill update, agent update, and agent skills add; tests/sync-multica.test.sh:307-334 is the now-passing executable regression for both unmanaged inventory and injected upsert failure.

Passing output

$ python3 tests/squad-runtime-contract.test.py
PASS: test_mirrored_company_contract
PASS: test_pr_sweep_caller_compatibility
PASS: test_pm_split_uses_exact_squad_contract
PASS: test_fallback_eligibility_contract
PASS: test_lost_response_result_idempotency
PASS: test_final_result_schema_and_order
PASS: test_specialized_close_order
PASS: test_native_stage_contract
PASS: checkpoint graph cp-01 --stage 1 --status todo; cp-02 depends_on=cp-01 --stage 2 --status backlog
PASS: rejected malformed checkpoint graphs: zero entries, missing stage, missing dependency field, unknown dependency, self dependency, same-stage dependency, missing later dependency, skipped dependency stage
PASS: test_checkpoint_plan_graph_contract
PASS: test_auto_harness_uses_squad_ownership
PASS: test_dual_evaluator_requires_two_distinct_verdicts
PASS: test_monitoring_and_recovery_contract
PASS: test_recursive_descendant_cancellation
PASS: Squad runtime contract tests

$ python3 tests/readme-quickstart.test.py
PASS: README quick-start contract test executes as documented

$ env -u LC_ALL bash tests/sync-multica.test.sh
PASS: sync-multica desired-state tests

$ env -u LC_ALL python3 tests/sync-topology.test.py
PASS: topology desired-state tests

$ env -u LC_ALL bash tests/pr-sweep.test.sh
PASS: pr-sweep PR issue routing tests

$ bash checkpoint-probes.sh ./
HAPPY PASS: parallel Stage 1, join in Stage 2, chain to Stage 3
FAILURE PASS: invalid JSON/object/stage/ID/dependency/DoD rejected
WEIRD PASS: unordered entries, Unicode/RTL/combining/long ID and 1,001-stage chain normalized

$ bash -n .github/scripts/pr-sweep.sh scripts/sync-multica.sh tests/pr-sweep.test.sh tests/sync-multica.test.sh && python3 -m py_compile <all Python callers/tests> && python3 -m json.tool <deployment and Squad manifests> && cmp -s AGENTS.md CLAUDE.md && git diff --check
PASS: shell syntax, Python compile, JSON parse, mirror, diff check

Caller/runtime and read-only live evidence

$ multica version
multica 0.4.11 (commit: b0bae3f95, built: 2026-07-24T20:01:46Z)
go: go1.26.1, os/arch: darwin/arm64

selected local runtime: Codex (stometas-MacBook-Pro.local)
runtime version: codex-cli 0.144.1
runtime metadata cli_version: 0.4.11

PR-sweep caller after merge: Multica 0.4.11 pinned at .github/workflows/pr-sweep.yml:113
official linux-amd64 release digest: sha256:b6069f1b1413bc5aaebfa23e44a376647426b70d181ae79ee1e65c8120150f7d

Exact-mapped read-only topology plan/verify did not guess or write. Both reported the same drift before failing closed on an existing unmanaged extra Growth member (Hao): Orchestrator runtime,model; Evaluator-A runtime; Evaluator-B runtime; Delivery Engineer roles differ; every reported Squad definition was up to date. Automatic member removal remains intentionally forbidden.

$ SYNC_AGENT_ORCHESTRATOR=Leilei scripts/sync-multica.sh --agent orchestrator
DRY RUN (no changes made). Re-run with --apply to execute.
workspace     context     stometaverse                         would update
orchestrator  skill       Orchestrator Skill                   would update
orchestrator  skill-file  scripts/validate-checkpoint-plan.py  would create
orchestrator  agent       Leilei                               up-to-date
orchestrator  attachment  Leilei                               attached

$ SYNC_AGENT_ORCHESTRATOR=Leilei scripts/sync-multica.sh --verify --agent orchestrator
workspace     context     stometaverse                         drift
orchestrator  skill       Orchestrator Skill                   drift
orchestrator  skill-file  scripts/validate-checkpoint-plan.py  missing
orchestrator  agent       Leilei                               up-to-date
orchestrator  attachment  Leilei                               attached
error: 3 drift item(s) remain — remote Multica state does not match this repository.
<exit 1; expected before authorized rollout>

PR #22 is still open/ready at 659d08f4f8f284cb66cb6cd7824f9c6f5d0bf8bc and was not modified. PR #23 is open/ready/mergeable at the final SHA. No --apply, live issue/agent/workspace/skill/topology mutation, merge, deployment, or rollout occurred.

Rollback Plan

Revert with git revert <merge-commit>. If a later separately authorized content rollout occurred, sync from the reverted clean main and run fresh --verify. Maximum blast radius is single feature (Squad orchestration/review automation contracts). Time-to-rollback is under one minute before rollout or one content-sync cycle after rollout. No schema/data/dependency migration exists.

Out of Scope

  • No live Multica workspace, agent, skill, supporting-file, attachment, issue, or topology mutation.
  • No merge, release, deployment, or automatic provider/runtime fallback.
  • No generic workflow engine, new service/API/dependency, sixth Squad, or roster redesign.
  • No modification, close, or merge of PR Codify Squad invocation fallback topology #22; it remains an explicit unresolved human merge gate.
  • Existing live topology drift and the unmanaged extra Growth member are reported, not auto-removed.
  • Backend enforcement of Squad DoD/state transitions remains outside this repository-contract change.

Summary by CodeRabbit

  • New Features
    • Introduced a formal Squad Issue contract template with deterministic result metadata and correlation.
    • Added native staged child work with dependency barriers, freshness-based stall detection, and task-first cancellation.
    • Strengthened Orchestrator close-out and consolidated result delivery with verified metadata ordering.
  • Bug Fixes
    • Prevented unsynchronized or unsupported fallback leaders from being routed or propagated.
    • Hardened PR sweep review closure to be deterministic and idempotent.
  • Documentation
    • Updated English and Chinese guides to reflect the revised run workflow, templates, and repository checks.
  • Tests
    • Added/expanded contract, topology, README quick-start, and workflow tests.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR formalizes single-Squad ownership and issue contracts, adds deterministic staged execution and parent-result handling, rejects unsynchronized fallback leaders, updates Auto-Harness barriers, synchronizes supporting files, and adds documentation plus regression tests.

Changes

Squad runtime contract

Layer / File(s) Summary
Owning Squad and issue contract
AGENTS.md, CLAUDE.md, templates/*, workspace-context.md, README*, docs/operating-model.md, agents/pm/skill.md
Complex work uses one owning Squad by UUID and the Squad Issue contract; direct-agent routing and fallback identities are constrained.
Deterministic execution and recovery
agents/orchestrator/skill.md, .github/scripts/pr-sweep.sh, AGENTS.md, CLAUDE.md, workspace-context.md, tests/pr-sweep.test.sh
Parent closure posts or recovers one consolidated result, verifies metadata, records activity, and changes status only in order, with evaluator, recovery, and cancellation rules.
Native staged child and E2E flow
agents/orchestrator/files/scripts/validate-checkpoint-plan.py, agents/orchestrator/skill.md, templates/auto-harness.md
Checkpoint graphs are validated before child creation; native barriers gate E2E promotion and dispatch.
Supporting-file synchronization
scripts/sync-multica.sh, tests/sync-multica.test.sh
Role supporting files are inventoried, synchronized before activation, and rejected on unmanaged, missing, or failed writes.
Topology enforcement and contract tests
scripts/sync-topology.py, tests/*, .github/workflows/pr-sweep.yml
Fallback topology fields are rejected, CLI pinning is updated, and repository contracts and failure paths are tested.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant OwningSquad
  participant ChildIssues
  participant Orchestrator
  participant ParentIssue
  Caller->>OwningSquad: assign issue by UUID
  OwningSquad->>ChildIssues: create validated staged work
  ChildIssues->>Orchestrator: emit eligible barrier wake
  Orchestrator->>ParentIssue: post or recover consolidated result
  Orchestrator->>ParentIssue: verify metadata and update status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.58% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: defining a deterministic Squad runtime contract.
✨ 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 agent/hao/sto-402-squad-runtime-contract

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.

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

🤖 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 `@agents/orchestrator/skill.md`:
- Around line 183-186: Update the cancellation procedure to traverse the
complete descendant issue graph, replacing the subjective “relevant children”
scope with every child and descendant. Enumerate active tasks for each
discovered issue, cancel every active task, and verify none remain queued,
dispatched, running, waiting, or deferred across the full graph before setting
any issue status to cancelled.
- Around line 153-158: Update the parent close sequence in steps 1–4 to be
idempotent when command responses are lost: before retrying comment or metadata
writes, look up an existing authoritative result comment using the
correlation_id and parent comment thread. If found, reuse its comment UUID and
continue with metadata verification/activity/status steps without posting
another result; only create a new comment when no matching result exists.

In `@templates/auto-harness.md`:
- Line 193: Update the shell-command fenced code block in auto-harness.md to
specify the bash language identifier, changing the opening fence to bash while
preserving the block’s commands and closing fence.

In `@templates/squad-issue.md`:
- Around line 63-65: Use one deterministic fallback rule across all contract
surfaces: require a separate Orchestrator identity deployed in every affected
Squad and validated by a fresh topology verify. Update templates/squad-issue.md
lines 63-65 and workspace-context.md line 105 to include this requirement;
retain the stronger wording in AGENTS.md line 67, apply identical wording in
CLAUDE.md line 67, and verify AGENTS.md and CLAUDE.md are byte-identical with
cmp -s.

In `@tests/squad-runtime-contract.test.py`:
- Around line 79-98: Add assertions to
test_monitoring_recovery_and_cancellation_contract that verify orchestrator
contains the documented requirements to record both caller-configured and
runtime Multica CLI versions and to depend only on fields verified on both
sides. Use the repository’s exact documented wording and preserve the existing
command and recovery-order assertions.
🪄 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: becf2ef1-5adc-40c7-b1db-d87a0387651b

📥 Commits

Reviewing files that changed from the base of the PR and between 8f4b3e8 and 2b23a5d.

📒 Files selected for processing (12)
  • AGENTS.md
  • CLAUDE.md
  • README.en.md
  • README.md
  • agents/orchestrator/skill.md
  • docs/operating-model.md
  • scripts/sync-topology.py
  • templates/auto-harness.md
  • templates/squad-issue.md
  • tests/squad-runtime-contract.test.py
  • tests/sync-topology.test.py
  • workspace-context.md

Comment thread agents/orchestrator/skill.md Outdated
Comment thread agents/orchestrator/skill.md Outdated
Comment thread templates/auto-harness.md Outdated
Comment thread templates/squad-issue.md Outdated
Comment thread tests/squad-runtime-contract.test.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b23a5d5fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread workspace-context.md
## Dispatch & DoD
## Squad Entry, Dispatch & DoD

Assign a complex or multi-role goal to one exact owning Squad by UUID; do not have an external caller fan it out to several agents. A direct-agent path is allowed only when the work is trivial, single-owner, low-risk, has no cross-profession dependency, and needs no independent gate. Use `templates/squad-issue.md` for the Issue body.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reconcile PR-sweep with Squad-only routing

For the existing multi-role PR review flow, .github/scripts/pr-sweep.sh:923 and :978 still reassign one issue directly among Engineer, Evaluator, and Orchestrator identities, while agents/orchestrator/skill.md:244 directly dispatches rework to the author. This new higher-precedence rule forbids that path because the flow has multiple professions and an independent gate, so deployed agents receive incompatible instructions on every non-approve review outcome. Either migrate PR-sweep issues to an owning Squad or define an explicit compatibility exception.

AGENTS.md reference: AGENTS.md:L61-L65

Useful? React with 👍 / 👎.

Comment thread README.en.md Outdated
tests/sync-topology.test.py
tests/sync-multica.test.sh
tests/pr-sweep.test.sh
tests/squad-runtime-contract.test.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make the new runtime-contract test executable

In a fresh checkout, this newly documented command exits with Permission denied because tests/squad-runtime-contract.test.py was added with mode 100644, despite its shebang and direct invocation here. Consequently, users and test runners following the quick-start commands cannot execute the new regression suite unless they know to invoke python3 manually; set the executable bit or document the interpreter explicitly.

Useful? React with 👍 / 👎.

@stone16

stone16 commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

Verdict: request-changes

Reviewed immutable head 2b23a5d5fec85370669e7239d6ee1533b5861e76 against base 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153. Immediately before posting:

$ gh pr view 23 --repo stone16/multica-agent-team --json headRefOid,state,isDraft,mergeable --jq '{headRefOid,state,isDraft,mergeable}'
{"headRefOid":"2b23a5d5fec85370669e7239d6ee1533b5861e76","isDraft":false,"mergeable":"MERGEABLE","state":"OPEN"}

Findings

  1. P1 / major — the new Squad-only entry rule contradicts the live PR-sweep route. The higher-precedence contract says complex or multi-role work must be assigned to one exact Squad and that the first unmet direct-agent condition requires Squad assignment (AGENTS.md:61-65; mirrored in CLAUDE.md:61-65 and injected by workspace-context.md:80-84). PR review is explicitly a multi-profession, independent-gate flow, but the unchanged sweep reassigns its issue directly to the Engineer/Evaluator lane and later directly to the Orchestrator (.github/scripts/pr-sweep.sh:899-950, especially :923; .github/scripts/pr-sweep.sh:957-980, especially :978). The Orchestrator procedure then directly dispatches rework to the author (agents/orchestrator/skill.md:227-244). Agents therefore receive incompatible instructions on every review run. Smallest acceptable fix: either migrate the PR-sweep review issue to one exact owning Squad or add a narrow, explicit compatibility exception to every higher-precedence contract surface and protect it with a regression test; do not leave the contradiction implicit.

  2. P1 / major — the promised single authoritative result is not idempotent after an ambiguous comment response. The close path posts the result and relies on the returned UUID (agents/orchestrator/skill.md:151-154), but its recovery clause merely says not to post a second result (agents/orchestrator/skill.md:158). If the server stores the comment and the client loses the response, the leader has neither the UUID nor a deterministic lookup marker, so it cannot know whether to retry or which comment to put in squad_result_comment_id. This violates the one-result invariant defined at agents/orchestrator/skill.md:137-149. Smallest acceptable fix: include a correlation-bound result marker in the authoritative comment, require a thread/comment lookup before retrying the write, reuse a matching comment UUID, and add a lost-response regression assertion.

  3. P1 / major — auto-harness still bypasses the new deterministic close sequence. State 5 requires all completed plans to execute result comment → verified metadata → Squad activity → status (agents/orchestrator/skill.md:81, :137-158), yet the specialized auto-harness path still instructs the leader to close the parent directly after retro (agents/orchestrator/skill.md:225), and the consumed harness template repeats the direct done transition (templates/auto-harness.md:207-227). An auto-harness parent can therefore finish without the required result index. Smallest acceptable fix: route retro completion through the Deterministic Parent Close Sequence in both files and assert that no specialized close path directly sets the parent terminal status.

  4. P1 / major — “full cancellation” can leave descendant tasks running. The cancellation procedure enumerates only the parent and subjective “relevant children,” then marks the same subset cancelled (agents/orchestrator/skill.md:179-188). Native work may be a nested child graph (agents/orchestrator/skill.md:124-135), so an omitted child/descendant task can continue behind a terminal-looking parent. Smallest acceptable fix: recursively enumerate the complete descendant graph with issue children, cancel and re-check every active task across it, and only then change statuses; add a contract test that rejects “relevant children” as the cancellation boundary.

  5. P2 / moderate — fallback eligibility differs across directly consumed contracts. The company contract requires a separate Orchestrator deployed in every affected Squad (AGENTS.md:67; CLAUDE.md:67), while the Squad Issue template only requires an identity that “belongs to the Squad” (templates/squad-issue.md:63-65). The injected workspace context omits the separate-Orchestrator restriction too (workspace-context.md:103-105). Because callers and leaders may consume those lower surfaces directly, the weaker wording could admit an ordinary Squad member as a fallback. Align all surfaces to the stronger rule and extend tests/squad-runtime-contract.test.py:27-41 beyond presence-only checks.

  6. P2 / moderate — the documented new test cannot be run as shown. Both quick starts invoke tests/squad-runtime-contract.test.py directly (README.md:62-75; README.en.md:89-102), but the file is mode 100644 (tests/squad-runtime-contract.test.py:1). Reproduction:

$ git ls-tree -l HEAD tests/squad-runtime-contract.test.py
100644 blob 74484ff6c41fb2c2a108282dfbee830a739277e9    4074 tests/squad-runtime-contract.test.py
$ ./tests/squad-runtime-contract.test.py
zsh: permission denied: ./tests/squad-runtime-contract.test.py
<exit 126>

Set the executable bit or document python3 tests/squad-runtime-contract.test.py in both READMEs.

Reviewed-file coverage

Read the complete diff and surrounding context for all 12 changed files: AGENTS.md, CLAUDE.md, README.en.md, README.md, agents/orchestrator/skill.md, docs/operating-model.md, scripts/sync-topology.py, templates/auto-harness.md, templates/squad-issue.md, tests/squad-runtime-contract.test.py, tests/sync-topology.test.py, and workspace-context.md. I also read the affected unchanged callers/exports in .github/scripts/pr-sweep.sh, .github/workflows/pr-sweep.yml, agents/engineer/skill.md, agents/evaluator/skill.md, the Squad manifests/instructions, and canonical bodies/diffs for PRs #22 and #23.

PR #22 remains open/ready at 659d08f4f8f284cb66cb6cd7824f9c6f5d0bf8bc and still proposes the contradictory declared fallback. PR #23 honestly supersedes that behavior on its own branch, but both PRs must not merge as independent contracts.

Verification re-run locally

$ python3 tests/squad-runtime-contract.test.py
PASS: Squad runtime contract tests

$ env -u LC_ALL python3 tests/sync-topology.test.py
PASS: topology desired-state tests

$ env -u LC_ALL bash tests/sync-multica.test.sh
PASS: sync-multica desired-state tests

$ env -u LC_ALL bash tests/pr-sweep.test.sh
PASS: pr-sweep PR issue routing tests

$ cmp -s AGENTS.md CLAUDE.md && python3 -m json.tool deployments/agents.json >/dev/null && for f in squads/*/squad.json; do python3 -m json.tool "$f" >/dev/null || exit; done && python3 -m py_compile scripts/sync-topology.py tests/sync-topology.test.py tests/squad-runtime-contract.test.py
PASS: mirror, JSON parse, Python compile

$ <local Markdown link resolution check>
PASS: local Markdown links resolve

$ git diff --check 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153..2b23a5d5fec85370669e7239d6ee1533b5861e76
<no output; exit 0>

$ <credential/private-key/local-path scan of the complete diff>
PASS: no credential-like tokens, private keys, or local-path artifacts in diff

The focused suites passing does not clear findings 1–5: tests/squad-runtime-contract.test.py:43-104 checks required phrases/order in the general Orchestrator section but does not exercise PR-sweep routing, specialized auto-harness close-out, ambiguous comment-response recovery, full descendant cancellation, or exact fallback eligibility.

Read-only sync reproduction matched the PR body:

$ <exact runtime/agent mappings> scripts/sync-topology.py
summary mode=plan drift=3

$ <same mappings> scripts/sync-topology.py --verify
error: 3 topology drift item(s) remain
<exit 1>

$ SYNC_AGENT_ORCHESTRATOR=Leilei scripts/sync-multica.sh --agent orchestrator
DRY RUN (no changes made). Re-run with --apply to execute.
workspace     context     stometaverse        would update
orchestrator  skill       Orchestrator Skill  would update

$ SYNC_AGENT_ORCHESTRATOR=Leilei scripts/sync-multica.sh --verify --agent orchestrator
workspace     context     stometaverse        drift
orchestrator  skill       Orchestrator Skill  drift
error: 2 drift item(s) remain — remote Multica state does not match this repository.
<exit 1>

No apply, branch edit, push, merge, deployment, or live workspace mutation was performed.

PR template, rollback, and scope assessment

The canonical PR body is ready-for-review and structurally complete:

preamble=1 author=1 summary=1 why=1 approach=1 tested=1 rollback=1 out_of_scope=1

Its rollback section states git revert <merge-commit>, maximum blast radius “single feature,” and time-to-rollback under one minute before rollout or one content-sync cycle afterward. The 12-file diff is within STO-402’s stated repository-contract/test scope, introduces no dependency or service, and contains no credentials or runtime-local paths. The body correctly distinguishes PR contents from live rollout and reports the expected pre-rollout sync drift.

Accepted choice: Request changes on this SHA before either independent gate can approve it.

Rejected alternatives:

  • Approve because the focused tests pass; they do not cover the contradictory live callers and specialized close path cited above.
  • Block the proposal entirely; the chosen architecture is viable and the defects are bounded contract/test corrections.

Constraint: STO-402 requires one internally consistent, deterministic Squad runtime contract, while this head still contains active paths that bypass Squad ownership, duplicate or omit final results, and leave cancellation scope ambiguous.

Re-run all verification after these findings are fixed.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8fd67e81a0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread AGENTS.md
5. A member returns a mention-free delivery addressing every evidence item. The current Squad leader verifies it and chooses the next transition.
6. Use one Evaluator for ordinary independent verification. Use both Evaluators only for high-risk, irreversible, security-sensitive, or explicitly dual-lens work. They receive independent pre-verdict contexts and do not coordinate until both verdicts exist.
7. Close only when the acceptance criteria are evidenced. Promote durable results to the Project ledger and record unresolved risks explicitly.
7. Close only when the acceptance criteria are evidenced. Post one consolidated parent result, index it with the required result metadata, record Squad activity, and only then change parent status. Promote durable results to the Project ledger and record unresolved risks explicitly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Cover PR-sweep's direct close in the exception

When both review lanes approve, .github/scripts/pr-sweep.sh:987-998 marks the review issue done directly, without a consolidated result comment, the five metadata keys, or Squad activity. Fresh evidence in this target is that the added PR-sweep compatibility paragraph exempts only its direct assignments, so the approve path still violates the newly mandatory close sequence on every successful sweep; either migrate that close path or explicitly define its alternative result contract.

AGENTS.md reference: AGENTS.md:L118-L120

Useful? React with 👍 / 👎.

Comment thread AGENTS.md
Assign complex or multi-role work to one exact owning Squad by UUID, not to several individual agents. Squad membership is a capability roster, not an instruction to activate everybody. For every run, the Orchestrator selects the smallest sufficient set of roles and states the distinct output expected from each activated member.

An Issue has exactly one owning Squad at a time. Other Squads may be consulted through a child Issue or explicit mention. Transfer ownership only through an artifact-backed handoff with acceptance criteria; do not make `Discovery -> Experience -> Delivery -> Growth -> Reliability` an automatic waterfall.
An Issue has exactly one owning Squad at a time, and its body uses `templates/squad-issue.md` as the execution and result contract. Other Squads may be consulted through a bounded child Issue or an artifact-backed mention that states the exact question and return artifact. Transfer ownership only through an artifact-backed handoff with acceptance criteria; do not make `Discovery -> Experience -> Delivery -> Growth -> Reliability` an automatic waterfall.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Migrate PM-created children to the Squad contract

When PM wraps a discussion issue, agents/pm/skill.md:154-188 still instructs it to create each child unassigned and with only Outcome, Source, and Acceptance Criteria. Those children therefore have neither an exact owning Squad nor the required Squad Issue body fields such as correlation and result contract, contradicting this new unconditional Issue invariant; update that workflow or narrowly exempt these children.

AGENTS.md reference: AGENTS.md:L61-L65

Useful? React with 👍 / 👎.

Comment thread agents/orchestrator/skill.md Outdated

Required order:

1. Post or recover one consolidated result comment on the parent issue. Derive `sha256:<correlation-hash>` from the caller-provided `correlation_id` and include exactly one inert marker as the final line of the result body: `<!-- squad-result: sha256:<correlation-hash> -->`. Never place the raw correlation value in this marker. Before the initial write and before every retry, search the trigger thread with `multica issue comment list <parent-issue-id> --thread <trigger-comment-id> --full --output json` for that exact marker. One match means the authoritative comment already exists: reuse that comment UUID and do not post. Zero matches means post once with `multica issue comment add <parent-issue-id> --parent <trigger-comment-id> --content-file <file> --output json` and capture its UUID. If the response is lost or ambiguous, perform the exact marker lookup before retrying. More than one exact marker match is an invariant violation: stop, preserve both IDs, and escalate without changing metadata or status. The comment states outcome, evidence/artifact links, deviations, rollout state, rollback, residual risks, and next owner.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Search the entire parent for an existing result

When recovery is triggered by a different comment—for example, a caller retries with the same stable correlation ID after losing the first response—this lookup searches only the new trigger thread, so it cannot see the authoritative result posted under the original trigger and will post a duplicate. That breaks the one-result invariant and can later trip the multiple-marker escalation; deduplicate by the correlation-hash marker across all parent comments rather than only the current trigger thread.

AGENTS.md reference: AGENTS.md:L132-L136

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb3bc5dcba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread agents/orchestrator/skill.md Outdated
1. Validate every proposed child carries all four suggested DoD fields: `outcome`, `evidence`, `verification`, `max_rounds`. Any entry missing a field, or a plan with zero entries, is malformed → rework dispatch back to the proposing Engineer naming the missing fields; this counts against that step's `max_rounds`. Do not create any children from a malformed plan.
2. For a valid plan, create ONE child issue per entry (`multica issue create` with the entry's title and self-contained body, parented to the triggering issue), assigned to an Engineer instance — instance-neutral; either takes fresh work. Label every child at creation — `harness:cp` for each checkpoint-plan child, `harness:e2e` for the e2e-plan child — creating the label in the workspace first if it does not exist yet. Step 6 selects checkpoint children BY the `harness:cp` label, so an unlabeled child is invisible to the E2E hand-off and stalls the parent permanently.
1. For `[auto-harness: checkpoint-plan]`, extract the authoritative fenced JSON array exactly into `./checkpoint-plan.json` with the file-write tool, locate this skill's supporting file `scripts/validate-checkpoint-plan.py`, then run `python3 <skill-dir>/scripts/validate-checkpoint-plan.py ./checkpoint-plan.json` before creating any child. Never substitute a same-named script from the target repository. The validator rejects zero entries; missing/invalid IDs, titles, bodies, stages, dependency lists, or DoD fields; duplicate/unknown/self/same-or-later-stage dependencies; Stage 1 dependencies; later stages without dependencies; and stages that are not one greater than their latest dependency stage. Any rejection is malformed → create zero children and rework-dispatch the exact error to the proposing Engineer; this counts against that step's `max_rounds`. For `[auto-harness: e2e-plan]`, retain the single-child four-field DoD validation because its eligibility is established only after the checkpoint barrier closes.
2. For a valid plan, create ONE child issue per entry (`multica issue create` with the entry's title and self-contained body, parented to the triggering issue), assigned to an Engineer instance — instance-neutral; either takes fresh work. Before writing each checkpoint description file, prepend the validated `Checkpoint ID: <id>`, `Stage: <N>`, and `Depends on: <comma-separated IDs | none>` header so dependency identities survive child creation. Label every child at creation — `harness:cp` for each checkpoint-plan child, `harness:e2e` for the e2e-plan child — creating the label in the workspace first if it does not exist yet. For checkpoints, use the validator output verbatim: `--stage <validated stage> --status <validated status>`; the validator emits exact `--stage 1 --status todo` arguments for Stage 1 and `--stage <N> --status backlog` for every later stage. An unlabeled child remains invalid because the label identifies its harness role; stage/status controls its runnable frontier.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route auto-harness children through their owning Squad

For every nontrivial auto-harness checkpoint, this creates the child assigned directly to an Engineer even though the child subsequently requires an independent Evaluator gate. Such a child fails the direct-agent fast-path criteria and has no exact owning Squad or templates/squad-issue.md contract, so the newly deployed auto-harness workflow contradicts the repository's mandatory routing model; create these children under the parent’s owning Squad and let its leader activate the Engineer lane.

AGENTS.md reference: AGENTS.md:L63-L65

Useful? React with 👍 / 👎.

CHECKPOINT_ID = re.compile(r"cp-[0-9]+")
REQUIRED_FIELDS = {"id", "title", "stage", "depends_on", "body", "suggested_dod"}
REQUIRED_DOD_FIELDS = {"outcome", "evidence", "verification", "max_rounds"}
VERIFICATION_LEVELS = {"self", "evaluator", "dual_evaluator", "human"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add a dual-evaluator return transition

When a checkpoint selects verification: dual_evaluator, this validator accepts it, but the Orchestrator state machine at agents/orchestrator/skill.md:71-79 defines dispatch and return transitions only for a single evaluator; it has no state that records both independent verdicts and waits to reconcile them. Consequently a high-risk checkpoint can either stall after delivery or follow the generic Evaluator PASS branch and be marked done after only the first verdict, defeating the required dual gate; add explicit two-verdict state handling or reject this value until that exists.

AGENTS.md reference: AGENTS.md:L118-L120

Useful? React with 👍 / 👎.

Comment thread scripts/sync-multica.sh
local_paths+=("${local_file#${files_root}/}")
done < <(find "$files_root" -type f ! -path '*/__pycache__/*' ! -name '*.pyc' -print | LC_ALL=C sort)

if ! python3 - "$remote_json" "${local_paths[@]}" > "$WORK_DIR/unmanaged-skill-files-$role" << 'PY'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preflight unmanaged skill files before writing

When --apply encounters an existing remote supporting file absent locally, this check runs only inside sync_skill_files, after the main loop has already called sync_workspace_context and potentially updated the skill content; the script then continues to update agent instructions and attachments before exiting with an error. I reproduced this with the test fixture's unmanaged-file scenario and observed all four writes before the failure, so the claimed fail-closed desired-state check can leave a partially applied deployment; move this validation into the preflight phase before any remote write.

Useful? React with 👍 / 👎.

@stone16

stone16 commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

Verdict: request-changes

Reviewed immutable head cb3bc5dcbaa1ee7c0c0971604e6fd62ba5657224 against base 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153. I read the complete 16-file diff, each changed file in surrounding context, the affected unchanged callers, the canonical PR body, and open PR #22.

Findings

  1. P1 / major — PR-sweep still bypasses the mandatory parent-result contract on approval. The new company contract makes result comment → verified five-key metadata index → Squad activity → status mandatory for closure (AGENTS.md:118-120; mirrored in CLAUDE.md:118-120). The compatibility exception covers direct lane assignments only (AGENTS.md:67; agents/orchestrator/skill.md:229-233), while the unchanged approve path directly runs multica issue update ... --status done (.github/scripts/pr-sweep.sh:987-998, especially :993) with none of the required result steps. The new compatibility test asserts the two direct assignment callers but not this direct close (tests/squad-runtime-contract.test.py:60-75). Smallest acceptable fix: route the approve path through the deterministic result close or explicitly define and test a complete PR-sweep-specific alternative result contract.

  2. P1 / major — the unconditional exact-Squad Issue invariant leaves the PM discussion-split caller invalid. Every Issue must now have exactly one owning Squad and use templates/squad-issue.md (AGENTS.md:61-65). The unchanged PM wrap-up flow still creates children without a Squad/assignee and with only Outcome, Source, and Acceptance Criteria, then explicitly leaves assignee empty (agents/pm/skill.md:154-188). Those children have neither exact Squad ownership nor correlation/result/work-graph contract fields. Smallest acceptable fix: migrate these children to the owning-Squad template and assignment path, or add a narrow exception whose ownership and close behavior are explicit and tested.

  3. P1 / major — correlation-based result recovery is still scoped to one trigger thread, so a retry under a new trigger can duplicate the authoritative result. The contract promises exactly one result payload (agents/orchestrator/skill.md:137-149), but lookup searches only --thread <trigger-comment-id> (agents/orchestrator/skill.md:151-158, especially :153). If the caller retries the same stable correlation after losing the first response but the retry is a different top-level trigger comment, the new lookup cannot see the earlier marker and posts again. The test checks marker/reuse phrases, not parent-wide discovery (tests/squad-runtime-contract.test.py:99-116). Smallest acceptable fix: search all comments belonging to the parent Issue for the exact hash marker before every initial/retry write, retain the requested trigger as the parent only for a genuinely new result, and test same-correlation recovery from a second trigger thread.

  4. P1 / major — auto-harness checkpoint and E2E children are still assigned directly to an Engineer despite requiring an independent gate. The direct-agent fast path excludes work that needs an independent gate (AGENTS.md:63-65), yet the Orchestrator creates checkpoint children assigned to an Engineer (agents/orchestrator/skill.md:211-226, especially :214) and the consumed template supplies direct Engineer assignment for both checkpoint and E2E children (templates/auto-harness.md:145-168, :220-236). The example DoDs require Evaluator verification (templates/auto-harness.md:114-140, :210-217), so these are nontrivial multi-lane Issues with no exact owning Squad or Squad Issue body. Smallest acceptable fix: create them under the parent's exact owning Squad using the Squad Issue contract and let the leader activate Engineer/Evaluator lanes; extend the graph test beyond stage arguments to assert ownership and body shape.

  5. P1 / major — dual_evaluator is accepted without a two-verdict state transition. The validator accepts dual_evaluator (agents/orchestrator/files/scripts/validate-checkpoint-plan.py:11-14), and the DoD table says to dispatch both independently (agents/orchestrator/skill.md:87-104). The state machine only dispatches verification: evaluator and its only Evaluator return transition can close on one PASS (agents/orchestrator/skill.md:70-79). A dual-gated checkpoint can therefore stall or be accepted after the first verdict. Smallest acceptable fix: add explicit state that records both independent verdicts for the same step/head and reconciles only after both exist, with pass/fail/disagreement tests; alternatively reject dual_evaluator until that state exists.

  6. P2 / moderate — unmanaged supporting-file detection happens after remote writes in --apply. preflight_apply_resources checks mappings/ambiguity but not remote supporting files (scripts/sync-multica.sh:678-723). Main then writes workspace state before entering role sync (scripts/sync-multica.sh:740-758); only inside sync_skill_files does it detect an unmanaged remote file (scripts/sync-multica.sh:320-355). The added test covers dry-run only (tests/sync-multica.test.sh:283-292). I reran its fixture with --apply: it exited 1 only after recording workspace update, skill update, agent update, and agent skills add. Smallest acceptable fix: preflight every existing skill's supporting-file set before the first remote mutation and add an apply-mode assertion that the calls log contains zero write operations on failure.

Seven-remediation regression

The requested correction round is present and reproducible:

  • Prior finding 1: direct PR-sweep lane assignment now has a bounded compatibility exception (AGENTS.md:67; agents/orchestrator/skill.md:229-233), but finding 1 above covers the still-unhandled direct-close caller.
  • Prior finding 2: same-trigger lost-response marker lookup/reuse is present (agents/orchestrator/skill.md:151-158), but finding 3 covers the parent-wide retry gap.
  • Prior finding 3: auto-harness retro now routes through deterministic close (agents/orchestrator/skill.md:225-227; templates/auto-harness.md:238-258).
  • Prior finding 4: cancellation recursively discovers/rechecks the complete graph and changes status deepest-first (agents/orchestrator/skill.md:179-190).
  • Prior finding 5: fallback eligibility uses the same separate-Orchestrator/every-affected-Squad/fresh-verify rule (AGENTS.md:69; workspace-context.md:107; templates/squad-issue.md:65).
  • Prior finding 6: both quick starts use python3, and the executable quick-start test passes (README.md:74; README.en.md:101; tests/readme-quickstart.test.py:1-31).
  • Prior finding 7: checkpoint producer carries stage/depends_on, the validator rejects malformed graphs before child creation, and the consumer preserves IDs and exact stage/status (templates/auto-harness.md:98-168; agents/orchestrator/files/scripts/validate-checkpoint-plan.py:27-114; agents/orchestrator/skill.md:211-215). Happy path and eight malformed paths pass (tests/squad-runtime-contract.test.py:160-228). Findings 4-5 above concern the post-validation dispatch/state contract, not loss of the graph fix.

Reviewed-file and affected-caller coverage

Changed files read completely: AGENTS.md, CLAUDE.md, README.en.md, README.md, agents/orchestrator/files/scripts/validate-checkpoint-plan.py, agents/orchestrator/skill.md, docs/operating-model.md, scripts/sync-multica.sh, scripts/sync-topology.py, templates/auto-harness.md, templates/squad-issue.md, tests/readme-quickstart.test.py, tests/squad-runtime-contract.test.py, tests/sync-multica.test.sh, tests/sync-topology.test.py, and workspace-context.md.

Affected unchanged callers/exports read: .github/scripts/pr-sweep.sh, .github/workflows/pr-sweep.yml, agents/pm/skill.md, agents/engineer/skill.md, agents/evaluator/skill.md, deployment/Squad manifests, and the auto-harness child/retro flow. The 16-file count and +957/-57 numstat match the PR.

Verification re-run locally

$ git rev-parse HEAD
cb3bc5dcbaa1ee7c0c0971604e6fd62ba5657224

$ python3 tests/squad-runtime-contract.test.py
PASS: test_mirrored_company_contract
PASS: test_pr_sweep_caller_compatibility
PASS: test_fallback_eligibility_contract
PASS: test_lost_response_result_idempotency
PASS: test_final_result_schema_and_order
PASS: test_specialized_close_order
PASS: test_native_stage_contract
PASS: checkpoint graph cp-01 --stage 1 --status todo; cp-02 depends_on=cp-01 --stage 2 --status backlog
PASS: rejected malformed checkpoint graphs: zero entries, missing stage, missing dependency field, unknown dependency, self dependency, same-stage dependency, missing later dependency, skipped dependency stage
PASS: test_checkpoint_plan_graph_contract
PASS: test_monitoring_and_recovery_contract
PASS: test_recursive_descendant_cancellation
PASS: Squad runtime contract tests

$ python3 tests/readme-quickstart.test.py
PASS: README quick-start contract test executes as documented

$ env -u LC_ALL bash tests/sync-multica.test.sh
PASS: sync-multica desired-state tests

$ env -u LC_ALL python3 tests/sync-topology.test.py
PASS: topology desired-state tests

$ env -u LC_ALL bash tests/pr-sweep.test.sh
PASS: pr-sweep PR issue routing tests

$ bash -n scripts/sync-multica.sh
<no output; exit 0>
$ python3 -m py_compile agents/orchestrator/files/scripts/validate-checkpoint-plan.py scripts/sync-topology.py
<no output; exit 0>
$ cmp -s AGENTS.md CLAUDE.md
<no output; exit 0>
$ python3 -m json.tool agents/orchestrator/files/auto-harness.json >/dev/null
<no output; exit 0>
$ git diff --check 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153..HEAD
<no output; exit 0>

Focused probes for uncovered behavior:

$ <inspect dual-evaluator validator/state-machine surfaces>
validator_accepts_dual_evaluator= True
state2_dispatches_dual_evaluator= False
state3_returns_dual_evaluator= False

$ <inspect exact-Squad affected callers and result lookup>
marker_lookup_scope=trigger_thread
parent_wide_marker_lookup= False
company_requires_exact_squad= True
pm_wrap_assigns_squad= False
pm_wrap_uses_squad_template= False
sweep_direct_done= True
harness_direct_engineer_assignment= True

$ env -u LC_ALL bash -c '<run unmanaged-file fixture in --apply mode and print write calls>'
exit=1
workspace update workspace-test --context-stdin
skill update skill-orchestrator --content-file agents/orchestrator/skill.md
agent update agent-orchestrator --instructions desired personality
agent skills add agent-orchestrator --skill-ids skill-orchestrator

No branch edit, push, merge, deployment, or live Multica mutation was performed. Generated __pycache__ directories were removed; git status --short is empty.

PR body, rollback, scope, and PR #22

Canonical body checks pass:

originating=1 author=1 summary=1 why=1 approach=1 tested=1 rollback=1 out_of_scope=1
rollback_blast_radius=True rollback_time=True
markdown_links=PASS diff_secret_scan=PASS

The rollback plan states git revert <merge-commit>, maximum blast radius, and time-to-rollback. The 16 changed files are within STO-402's contract/validator/sync/test scope; there is no new dependency, service, credential, or live rollout. PR #22 remains open and ready at 659d08f4f8f284cb66cb6cd7824f9c6f5d0bf8bc, overlaps the same fallback/contract surfaces, and proposes the contradictory fallback topology. That remains a human merge-order/content gate, not a reason to skip this technical verdict.

Accepted choice: Request changes on this immutable head before STO-402 advances.

Rejected alternatives:

  • Approve because all focused suites pass; they do not exercise the six affected-caller and apply-failure paths reproduced above.
  • Block the proposal; the architecture and all seven prior remediations are viable, and the remaining defects are bounded contract/caller/test corrections.
  • Defer the technical verdict until PR Codify Squad invocation fallback topology #22 is resolved; its semantic conflict is a separate human merge gate.

Constraint: STO-402 requires one internally consistent Squad runtime contract, but this head still has active paths that bypass exact Squad ownership, deterministic result closure, dual-gate reconciliation, or pre-write failure safety.

Re-run the full suite and the six focused regressions after correction.

@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 (2)
scripts/sync-multica.sh (2)

341-343: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Quote the prefix inside ${var#...} (SC2295).

${files_root} is expanded as a glob pattern here. Role names are currently metachar-free so behavior is unaffected, but the same construct repeats at Lines 408 and 759 and is flagged by shellcheck.

♻️ Proposed fix (apply at Lines 342, 408, 759)
-    local_paths+=("${local_file#${files_root}/}")
+    local_paths+=("${local_file#"$files_root"/}")
🤖 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 `@scripts/sync-multica.sh` around lines 341 - 343, Update the local_paths
prefix removal in the loops around local_file and the equivalent occurrences
near the other reported locations to quote the files_root prefix within the
parameter expansion, preventing it from being interpreted as a glob pattern
while preserving the existing relative-path behavior.

Source: Linters/SAST tools


345-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unmanaged-inventory check is duplicated verbatim in preflight_skill_files.

Lines 345-359 and Lines 762-774 run the same embedded Python and the same failure semantics, differing only in the log prefix. Extract one helper so the fail-closed rule cannot drift between the preflight and the apply phase.

🤖 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 `@scripts/sync-multica.sh` around lines 345 - 359, Extract the duplicated
embedded-Python unmanaged-file validation and its shared failure behavior from
the preflight and apply paths into one helper, then have both callers invoke it
with their role, remote inventory, and managed paths. Preserve the existing
fail-closed return status, diagnostic output, row recording, and error counting
while allowing each phase to supply its distinct log prefix.
🤖 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 `@agents/orchestrator/skill.md`:
- Line 154: Update the metadata verification instructions in the issue-closing
workflow to validate allowed squad_verdict values, require squad_next_owner to
be the exact Squad name or “none,” and confirm squad_result_comment_id matches
the recovered or newly posted authoritative comment UUID. Perform all required
metadata checks before recording activity or changing status, and block status
changes if any validation fails.

In `@agents/pm/skill.md`:
- Around line 207-208: Define dual_evaluator in the PM DoD grammar and specify
its completion semantics, including two independent verdicts and deterministic
disagreement resolution, before permitting it in the Verification options.
Ensure the workflow has an explicit closure outcome for every dual_evaluator
request.
- Around line 162-164: Add a required exact owning-Squad decision to the Change
Proposal template and require it before the child-creation flow in the relevant
instructions. Ensure each independently created Issue resolves exactly one
owning Squad UUID from that proposal before writing the issue body from
templates/squad-issue.md.
- Line 167: Update both fenced code blocks in the skill document to include
language identifiers: use sh for the command block and markdown for the body
template, including the additionally referenced fence.

In `@docs/operating-model.md`:
- Line 57: The PR-sweep exception description in docs/operating-model.md at
lines 57-57 must state that it still follows the complete deterministic close
contract: authoritative result, metadata, activity, and status. In
agents/orchestrator/skill.md at lines 229-231, update the script-owned issue
workflow so it verifies the result and metadata before marking the issue done.
- Line 25: Resolve the Orchestrator’s cross-profession dependency for the retro
contract. In docs/operating-model.md at line 25, either define an explicit
allowed shared-template boundary or require the contract to be inline; in
agents/orchestrator/skill.md at lines 225-227, remove the direct Engineer
harness-procedure reference by embedding or relocating the retro format within
the Orchestrator bundle.

In `@templates/auto-harness.md`:
- Line 261: Reconcile Step 4 with the “No auto-harness path changes the parent
status directly” rule: either move the in_review transition to the CEO flow or
explicitly limit the rule to post-in_review terminal transitions. Update the
related contract assertion in squad-runtime-contract.test.py so it also catches
the lowercase Step 4 wording, preserving the intended ownership of parent status
changes.

In `@tests/pr-sweep.test.sh`:
- Around line 1093-1102: Strengthen the parent-result close-path assertions in
tests/pr-sweep.test.sh at lines 1093-1102, 1112-1118, and 1684-1686: add shared
checks covering all five metadata values/types, squad_result_comment_id,
squad_next_owner, unchanged correlation_id, result-comment linkage, and recorded
activity. Ensure each path verifies result → metadata → activity → status
ordering; apply the complete indexing assertions to the recovered and
inconclusive compensating close-outs as well.

In `@tests/sync-multica.test.sh`:
- Around line 17-24: The assert_no_contract_writes helper must also reject
“skill files upsert” operations so missing-skill preflight checks detect all
forbidden writes. Add this assertion while preserving a separate helper that
allows the intentional failed upsert scenario, and update the relevant preflight
test to use the stricter helper.

---

Nitpick comments:
In `@scripts/sync-multica.sh`:
- Around line 341-343: Update the local_paths prefix removal in the loops around
local_file and the equivalent occurrences near the other reported locations to
quote the files_root prefix within the parameter expansion, preventing it from
being interpreted as a glob pattern while preserving the existing relative-path
behavior.
- Around line 345-359: Extract the duplicated embedded-Python unmanaged-file
validation and its shared failure behavior from the preflight and apply paths
into one helper, then have both callers invoke it with their role, remote
inventory, and managed paths. Preserve the existing fail-closed return status,
diagnostic output, row recording, and error counting while allowing each phase
to supply its distinct log prefix.
🪄 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: 4bc8a33e-8c60-47a0-a66e-6afd68f788dd

📥 Commits

Reviewing files that changed from the base of the PR and between 2b23a5d and 89be1ba.

📒 Files selected for processing (18)
  • .github/scripts/pr-sweep.sh
  • .github/workflows/pr-sweep.yml
  • AGENTS.md
  • CLAUDE.md
  • README.en.md
  • README.md
  • agents/orchestrator/files/scripts/validate-checkpoint-plan.py
  • agents/orchestrator/skill.md
  • agents/pm/skill.md
  • docs/operating-model.md
  • scripts/sync-multica.sh
  • templates/auto-harness.md
  • templates/squad-issue.md
  • tests/pr-sweep.test.sh
  • tests/readme-quickstart.test.py
  • tests/squad-runtime-contract.test.py
  • tests/sync-multica.test.sh
  • workspace-context.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • templates/squad-issue.md

Required order:

1. Post or recover one consolidated result comment on the parent issue. Derive `sha256:<correlation-hash>` from the caller-provided `correlation_id` and include exactly one inert marker as the final line of the result body: `<!-- squad-result: sha256:<correlation-hash> -->`. Never place the raw correlation value in this marker. Before the initial write and before every retry, search all comments on the parent with `multica issue comment list <parent-issue-id> --full --output json` for that exact marker; never scope recovery to the requested trigger thread. One match means the authoritative comment already exists—even when it belongs to a different top-level trigger after a duplicate caller retry: reuse that comment UUID and do not post. Zero matches means post once with `multica issue comment add <parent-issue-id> --parent <trigger-comment-id> --content-file <file> --output json` and capture its UUID. The requested trigger is only the parent for a genuinely new result, never the lookup boundary. If the response is lost or ambiguous, perform the same parent-wide marker lookup before retrying. More than one exact marker match is an invariant violation: stop, preserve both IDs, and escalate without changing metadata or status. The comment states outcome, evidence/artifact links, deviations, rollout state, rollback, residual risks, and next owner.
2. Write and verify all five metadata keys with `multica issue metadata set`, using `--type string` for IDs/verdict/owner/correlation and `--type bool` for evidence completeness; then read them back with `multica issue metadata list <parent-id> --output json`. If any key is absent, mistyped, or the correlation value differs, do not change status.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate metadata semantics and result linkage before closing.

The verification step checks only presence, type, and correlation. It must also reject invalid squad_verdict values, ensure squad_next_owner is the exact Squad or none, and verify that squad_result_comment_id equals the recovered or newly posted authoritative comment UUID before activity/status changes.

Based on learnings, required result metadata must be verified before recording activity or changing status.

🧰 Tools
🪛 SkillSpector (2.3.11)

[warning] 340: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[error] 153: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))


[error] 233: [P2] Hidden Instructions: Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Remediation: Audit all comments and invisible characters. Remove any instructions that direct the agent to perform unauthorized actions. Use plain, reviewable content.

(Prompt Injection (P2))

🤖 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 `@agents/orchestrator/skill.md` at line 154, Update the metadata verification
instructions in the issue-closing workflow to validate allowed squad_verdict
values, require squad_next_owner to be the exact Squad name or “none,” and
confirm squad_result_comment_id matches the recovered or newly posted
authoritative comment UUID. Perform all required metadata checks before
recording activity or changing status, and block status changes if any
validation fails.

Source: Learnings

Comment thread agents/pm/skill.md
Comment on lines +162 to +164
For each genuinely independent item, first resolve the exact owning Squad UUID
from the accepted change proposal. Write its body from
`templates/squad-issue.md` (do not substitute the shorter discussion summary),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Require ownership in the Change Proposal before splitting.

The Change Proposal template at Lines 130-152 has no owning-Squad field, so compliant proposals cannot deterministically provide the owner this flow requires. Add a required exact owning-Squad decision before child creation.

Based on learnings, each Issue must have exactly one owning Squad.

🧰 Tools
🪛 SkillSpector (2.3.11)

[info] 29: [EA3] Scope Creep: Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Remediation: Limit the skill's scope to its documented purpose. Remove instructions that enable the agent to perform actions outside its stated functionality.

(Excessive Agency (EA3))

🤖 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 `@agents/pm/skill.md` around lines 162 - 164, Add a required exact owning-Squad
decision to the Change Proposal template and require it before the
child-creation flow in the relevant instructions. Ensure each independently
created Issue resolves exactly one owning Squad UUID from that proposal before
writing the issue body from templates/squad-issue.md.

Source: Learnings

Comment thread agents/pm/skill.md
`templates/squad-issue.md` (do not substitute the shorter discussion summary),
then run:

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language identifiers to both fenced blocks.

These fences trigger markdownlint MD040; use sh for the command block and markdown for the body template.

Also applies to: 182-182

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 167-167: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 SkillSpector (2.3.11)

[info] 29: [EA3] Scope Creep: Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Remediation: Limit the skill's scope to its documented purpose. Remove instructions that enable the agent to perform actions outside its stated functionality.

(Excessive Agency (EA3))

🤖 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 `@agents/pm/skill.md` at line 167, Update both fenced code blocks in the skill
document to include language identifiers: use sh for the command block and
markdown for the body template, including the additionally referenced fence.

Source: Linters/SAST tools

Comment thread agents/pm/skill.md
Comment on lines +207 to +208
## Verification
<self | evaluator | dual_evaluator | human>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Define dual_evaluator completion semantics before allowing it.

This new value is absent from the PM DoD grammar and has no two-independent-verdict or disagreement-resolution path. A child can therefore request verification that the workflow cannot deterministically close.

🧰 Tools
🪛 SkillSpector (2.3.11)

[info] 29: [EA3] Scope Creep: Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Remediation: Limit the skill's scope to its documented purpose. Remove instructions that enable the agent to perform actions outside its stated functionality.

(Excessive Agency (EA3))

🤖 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 `@agents/pm/skill.md` around lines 207 - 208, Define dual_evaluator in the PM
DoD grammar and specify its completion semantics, including two independent
verdicts and deterministic disagreement resolution, before permitting it in the
Verification options. Ensure the workflow has an explicit closure outcome for
every dual_evaluator request.

Comment thread docs/operating-model.md
| `.github/workflows/pr-sweep.yml` + `.github/scripts/pr-sweep.sh` + `tests/pr-sweep.test.sh` | Automated PR review chain. See "PR-Sweep Automation" | One Multica review issue per PR |

Each profession is two files. No shared skills, no cross-file referencesevery rule an agent needs is duplicated into that agent's `skill.md`. Duplication is the price of self-containment; we accept it.
Each profession owns its `personality.md`, `skill.md`, and any supporting files under `agents/<role>/files/`. No shared skills or cross-profession references: every rule and executable an agent needs belongs to that profession's skill bundle. Duplication is the price of self-containment; we accept it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Resolve the cross-profession skill dependency.

The repository now requires self-contained profession bundles, but the Orchestrator still depends on the Engineer's harness procedure for the retro contract.

  • docs/operating-model.md#L25-L25: define an allowed shared-template boundary or require the contract to be inline.
  • agents/orchestrator/skill.md#L225-L227: remove the direct Engineer-procedure dependency by embedding or relocating the retro format.
📍 Affects 2 files
  • docs/operating-model.md#L25-L25 (this comment)
  • agents/orchestrator/skill.md#L225-L227
🤖 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/operating-model.md` at line 25, Resolve the Orchestrator’s
cross-profession dependency for the retro contract. In docs/operating-model.md
at line 25, either define an explicit allowed shared-template boundary or
require the contract to be inline; in agents/orchestrator/skill.md at lines
225-227, remove the direct Engineer harness-procedure reference by embedding or
relocating the retro format within the Orchestrator bundle.

Source: Coding guidelines

Comment thread docs/operating-model.md

Keep a direct-agent fast path only for work that is trivial, single-owner, low-risk, has no cross-profession dependency, and needs no independent gate. If any condition is false, the external caller assigns the owning Squad and lets its leader compose the lanes; it does not fan one goal out to several individual agents.

The checked-in PR-sweep is one narrow compatibility exception: it reuses one dedicated, serialized review issue and assigns that issue directly, one lane at a time, to the non-author Engineer, Evaluator, and Orchestrator. `.github/scripts/pr-sweep.sh` preserves the issue identity, ordered lanes, immutable head SHA, and Orchestrator-routed rework. This is not a reusable exception for other external callers or multi-role workflows.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Require the PR-sweep exception to preserve full closure semantics.

The exception is explicit about routing but not about completing the authoritative result → metadata → activity → status sequence.

  • docs/operating-model.md#L57-L57: state that the exception still requires the complete deterministic close contract.
  • agents/orchestrator/skill.md#L229-L231: require the script-owned issue to verify the result and metadata before marking it done.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~57-~57: The official name of this software platform is spelled with a capital “H”.
Context: ... Engineer, Evaluator, and Orchestrator. .github/scripts/pr-sweep.sh preserves the issu...

(GITHUB)

📍 Affects 2 files
  • docs/operating-model.md#L57-L57 (this comment)
  • agents/orchestrator/skill.md#L229-L231
🤖 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/operating-model.md` at line 57, The PR-sweep exception description in
docs/operating-model.md at lines 57-57 must state that it still follows the
complete deterministic close contract: authoritative result, metadata, activity,
and status. In agents/orchestrator/skill.md at lines 229-231, update the
script-owned issue workflow so it verifies the result and metadata before
marking the issue done.

Comment thread templates/auto-harness.md
per existing convention there.

Set parent status `in_review`. The CEO then runs its Retro close-out step: after the retro delivery passes the DoD check, the CEO closes the parent (`done`). Stop.
Keep the parent in `in_review`; do not change status here. The CEO then runs its Retro close-out step: after the retro delivery passes the DoD check, the CEO runs the Orchestrator skill's Deterministic Parent Close Sequence (correlation marker lookup/result comment → verified metadata → Squad activity → status). No auto-harness path changes the parent status directly. Stop.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

"No auto-harness path changes the parent status directly" contradicts Step 4.

Line 190 still instructs the assignee to "set parent status in_review" after posting the checkpoint plan, which is exactly an auto-harness path changing parent status. Reconcile the two: either scope this sentence to terminal transitions ("no auto-harness path closes or transitions the parent after in_review") or move the Step 4 transition to the CEO. Note the contract test only forbids the capitalized Set parent status \in_review` (tests/squad-runtime-contract.test.py` Line 151), so the lowercase Step 4 wording slips through — worth aligning the assertion too.

🤖 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 `@templates/auto-harness.md` at line 261, Reconcile Step 4 with the “No
auto-harness path changes the parent status directly” rule: either move the
in_review transition to the CEO flow or explicitly limit the rule to
post-in_review terminal transitions. Update the related contract assertion in
squad-runtime-contract.test.py so it also catches the lowercase Step 4 wording,
preserving the intended ownership of parent status changes.

Comment thread tests/pr-sweep.test.sh
Comment on lines +1093 to +1102
assert_comment_count "$tmp/captures" 1
assert_update_count "$tmp/captures" 1
assert_contains "$tmp/captures/issue-comment-1.md" "PR review accepted after two independent approvals."
assert_contains "$tmp/captures/issue-comment-1.md" "<!-- squad-result: sha256:"
assert_contains "$tmp/captures/metadata-squad_verdict.value" "delivered"
assert_contains "$tmp/captures/metadata-squad_evidence_complete.value" "true"
assert_contains "$tmp/captures/squad-activity.args" "squad activity 11111111-1111-1111-1111-000000000001 action"
assert_line_before "$tmp/captures/multica-calls.log" "issue comment add" "issue metadata set"
assert_line_before "$tmp/captures/multica-calls.log" "issue metadata list" "squad activity"
assert_line_before "$tmp/captures/multica-calls.log" "squad activity" "issue update 11111111-1111-1111-1111-000000000001 --status done"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the complete parent-result contract on every close path.

These tests cover only selected metadata fields, so regressions omitting squad_result_comment_id, squad_next_owner, or unchanged correlation_id can still mark the issue done. Add a shared assertion for all five verified fields, result-comment linkage, activity, and result → metadata → activity → status ordering.

  • tests/pr-sweep.test.sh#L1093-L1102: assert all five metadata values/types after the normal approve close-out.
  • tests/pr-sweep.test.sh#L1112-L1118: assert recovered results are fully indexed, verified, recorded as activity, and only then closed.
  • tests/pr-sweep.test.sh#L1684-L1686: assert the inconclusive compensating close-out also writes the complete result index.
📍 Affects 1 file
  • tests/pr-sweep.test.sh#L1093-L1102 (this comment)
  • tests/pr-sweep.test.sh#L1112-L1118
  • tests/pr-sweep.test.sh#L1684-L1686
🤖 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/pr-sweep.test.sh` around lines 1093 - 1102, Strengthen the
parent-result close-path assertions in tests/pr-sweep.test.sh at lines
1093-1102, 1112-1118, and 1684-1686: add shared checks covering all five
metadata values/types, squad_result_comment_id, squad_next_owner, unchanged
correlation_id, result-comment linkage, and recorded activity. Ensure each path
verifies result → metadata → activity → status ordering; apply the complete
indexing assertions to the recovered and inconclusive compensating close-outs as
well.

Comment on lines +17 to +24
assert_no_contract_writes() {
local file="$1"
! grep -Fq 'workspace update' "$file" || fail "failure path allowed a workspace write"
! grep -Fq 'skill update' "$file" || fail "failure path allowed a skill-body write"
! grep -Fq 'skill create' "$file" || fail "failure path allowed a skill-body create"
! grep -Fq 'agent update' "$file" || fail "failure path allowed an agent write"
! grep -Fq 'agent skills add' "$file" || fail "failure path allowed an attachment write"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include supporting-file upserts in the no-write preflight assertion.

assert_no_contract_writes omits skill files upsert, so the missing-skill preflight test at Line 304 would miss a forbidden supporting-file write. Use a stricter helper there; keep a separate helper for the intentional failed upsert scenario.

🤖 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/sync-multica.test.sh` around lines 17 - 24, The
assert_no_contract_writes helper must also reject “skill files upsert”
operations so missing-skill preflight checks detect all forbidden writes. Add
this assertion while preserving a separate helper that allows the intentional
failed upsert scenario, and update the relevant preflight test to use the
stricter helper.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89be1bab6a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if isinstance(data, dict):
data = data.get("comments") or data.get("items") or data.get("data") or []
for item in data:
if marker in (item.get("content") or item.get("body") or ""):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject untrusted result-marker matches

When a PR contains prompt-injection text that causes either review lane to repeat the predictable marker—its hash input is fully derivable from the public owner, PR number, SHA, and verdict—this parent-wide substring search accepts that member comment as the authoritative result. One injected marker makes metadata point to a review delivery instead of the required consolidated result, while two markers permanently block closure; recovery must authenticate the automation-authored result rather than trust marker presence in arbitrary comments.

AGENTS.md reference: AGENTS.md:L132-L134

Useful? React with 👍 / 👎.

Comment thread scripts/sync-multica.sh
Comment on lines +700 to +702
elif [[ -z "$match" && -d "agents/$role/files" ]]; then
log "[preflight] $role skill '$skill_name' is missing but has required supporting files; cannot safely create and activate it before those files exist."
errors=$((errors + 1))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Allow fresh skills with supporting files to bootstrap

On a fresh workspace where the mapped agents exist but Orchestrator Skill does not, --apply now always aborts here because the repository contains agents/orchestrator/files/. This makes the documented create-when-absent path—and the dry-run plan saying the file would be created after the skill—impossible to apply; create the still-unattached skill during the pre-activation phase, upload its supporting files, and only then update or attach the active contract.

Useful? React with 👍 / 👎.

Comment thread agents/pm/skill.md
Comment on lines +175 to +178
Preserve `spec` versus `impl` as a title/body classification until a caller
explicitly supplies the workspace's label UUID; the current CLI does not expose
a label-name flag on `issue create`. Do not invent or paste an unverified label
argument.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the label required by the product-review trigger

For an implementation child created by this wrap-up flow, recording impl only in its title or body leaves it without the label required by the PM trigger at lines 41 and 233. Consequently the generated child cannot later satisfy the documented “product review of an impl-label issue” transition; after creation, resolve the label UUID and use the separate label-add command, or change the downstream trigger to consume the preserved classification.

Useful? React with 👍 / 👎.

@stone16

stone16 commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

Verdict: request-changes

Reviewed immutable head 89be1bab6a49a63ab6ef6d4148efcf398abad70e against base 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153. I read the complete 20-file diff, all changed files in surrounding context, the affected callers, the canonical PR body, and open PR #22.

Finding

  1. P1 / major — the new PR-sweep close cannot record Squad activity in its actual GitHub Actions execution context, so every approve path remains permanently non-terminal. The close helper invokes multica squad activity and refuses to set done or write the GitHub consensus sentinel if that command fails (.github/scripts/pr-sweep.sh:1015-1024, :1096-1111, :1139-1167). But the review issue is created and continually reassigned to individual agents (.github/scripts/pr-sweep.sh:626-635, :948-956, :1005-1011), while the pinned Multica v0.4.11 endpoint accepts activity only when the issue is assigned to a Squad, the caller is that Squad's leader, and X-Task-ID identifies a task belonging to the issue (multica-ai/multica@v0.4.11, server/internal/handler/squad.go:908-940). The scheduled workflow authenticates with a PAT and has neither MULTICA_AGENT_ID nor MULTICA_TASK_ID (.github/workflows/pr-sweep.yml:26-65, :128-147), so it cannot satisfy any of those runtime checks. The repository test stub accepts every activity call unconditionally (tests/pr-sweep.test.sh:799-803) and therefore masks the incompatibility. Reproduction against the pinned source:
workflow_has_agent_task_context=no
review_issue_create_assignment=632:    --assignee "$assignee" \
squad_activity_call=1096:  if ! multica squad activity "$issue_id" "$activity" --reason "$result_summary" --output json >/dev/null; then

v0.4.11 handler:
if !issue.AssigneeType.Valid || issue.AssigneeType.String != "squad" ...
    "issue is not assigned to a squad"
if actorType != "agent" || actorID != uuidToString(squad.LeaderID) ...
    "only the squad leader agent can record evaluations"
taskID := r.Header.Get("X-Task-ID")
... "task does not belong to issue"

Smallest acceptable fix: do not claim the direct-agent PR-sweep exception implements the Squad-leader close sequence with this endpoint. Either (a) migrate the review Issue to an exact owning Squad and execute the activity step from a real leader task before terminal close, or (b) define a PR-sweep-specific audited activity/result primitive that is callable from CI and add an integration-shaped test enforcing the pinned endpoint's assignment/actor/task requirements. Do not merely skip the activity call: AGENTS.md:120 and agents/orchestrator/skill.md:151-158 make that step mandatory.

Because correction round 2 exhausted the automated author cap, this terminal non-approve verdict requires human escalation rather than a third author round.

Thirteen-remediation regression

The original seven remediations remain present and green: bounded serialized PR-sweep assignment, parent-result marker recovery, specialized deterministic close, recursive descendant cancellation, exact fallback eligibility, executable README quick starts, and producer → validator → consumer checkpoint graph preservation (AGENTS.md:61-69, :120-138; agents/orchestrator/skill.md:137-188, :211-240; templates/auto-harness.md:98-188; agents/orchestrator/files/scripts/validate-checkpoint-plan.py:27-114).

Five of the six terminal corrections are also valid:

  • PM split children resolve an exact Squad and use the complete Squad Issue body (agents/pm/skill.md:154-229; tests/squad-runtime-contract.test.py:77-84).
  • Result lookup is parent-wide and handles a different top-level trigger (agents/orchestrator/skill.md:151-158; tests/squad-runtime-contract.test.py:109-131).
  • Checkpoint/E2E children use the parent's exact Squad while retaining validated graph arguments (agents/orchestrator/skill.md:211-227; templates/auto-harness.md:145-188, :222-239; tests/squad-runtime-contract.test.py:175-257).
  • Dual evaluation records two expected author UUIDs and cannot close from one PASS (agents/orchestrator/skill.md:70-79; tests/squad-runtime-contract.test.py:260-268).
  • Supporting-file apply order passes all three zero-activation paths: missing skill, unmanaged inventory, and injected upsert failure (scripts/sync-multica.sh:320-401, :685-809; tests/sync-multica.test.sh:297-334).

The sixth correction—PR-sweep deterministic close—is structurally ordered but not executable against the pinned API for the finding above.

Changed-file and affected-caller coverage

Read completely: .github/scripts/pr-sweep.sh, .github/workflows/pr-sweep.yml, AGENTS.md, CLAUDE.md, both READMEs, the Orchestrator validator/skill, PM skill, operating model, content/topology sync scripts, auto-harness and Squad Issue templates, all five changed test files, and workspace-context.md (20 files; +1402/-110).

Affected context inspected: Engineer/Evaluator skills, deployment and five Squad manifests, Multica CLI v0.4.11 client/header behavior, and the v0.4.11 Squad activity handler. No LLM call, new dependency, concurrency primitive, or unrelated abstraction was added.

Verification re-run

$ git rev-parse HEAD
89be1bab6a49a63ab6ef6d4148efcf398abad70e

$ python3 tests/squad-runtime-contract.test.py
PASS: test_mirrored_company_contract
PASS: test_pr_sweep_caller_compatibility
PASS: test_pm_split_uses_exact_squad_contract
PASS: test_fallback_eligibility_contract
PASS: test_lost_response_result_idempotency
PASS: test_final_result_schema_and_order
PASS: test_specialized_close_order
PASS: test_native_stage_contract
PASS: checkpoint graph cp-01 --stage 1 --status todo; cp-02 depends_on=cp-01 --stage 2 --status backlog
PASS: rejected malformed checkpoint graphs: zero entries, missing stage, missing dependency field, unknown dependency, self dependency, same-stage dependency, missing later dependency, skipped dependency stage
PASS: test_checkpoint_plan_graph_contract
PASS: test_auto_harness_uses_squad_ownership
PASS: test_dual_evaluator_requires_two_distinct_verdicts
PASS: test_monitoring_and_recovery_contract
PASS: test_recursive_descendant_cancellation
PASS: Squad runtime contract tests

$ python3 tests/readme-quickstart.test.py
PASS: README quick-start contract test executes as documented
$ env -u LC_ALL bash tests/sync-multica.test.sh
PASS: sync-multica desired-state tests
$ env -u LC_ALL python3 tests/sync-topology.test.py
PASS: topology desired-state tests
$ env -u LC_ALL bash tests/pr-sweep.test.sh
PASS: pr-sweep PR issue routing tests
$ bash checkpoint-probes.sh ./
HAPPY PASS: parallel Stage 1, join in Stage 2, chain to Stage 3
FAILURE PASS: invalid JSON/object/stage/ID/dependency/DoD rejected
WEIRD PASS: unordered entries, Unicode/RTL/combining/long ID and 1,001-stage chain normalized
$ bash -n .github/scripts/pr-sweep.sh scripts/sync-multica.sh tests/pr-sweep.test.sh tests/sync-multica.test.sh
bash_syntax_exit=0
$ python3 -m py_compile <all changed Python callers/tests>
py_compile_exit=0
$ python3 -m json.tool <deployment and Squad manifests>
json_exit=0
$ cmp -s AGENTS.md CLAUDE.md
mirror_exit=0
$ git diff --check 8f4b3e850f86aaf5f8ba839d20a26900cfa9c153..HEAD
diff_check_exit=0

Independent zero-activation traces:

scenario=create exit=1
contract_writes=0
skill_file_upserts=0
error: 1 resource mapping error(s) found before apply. No remote writes were attempted.
scenario=unmanaged-file exit=1
contract_writes=0
skill_file_upserts=0
error: 1 resource mapping error(s) found before apply. No remote writes were attempted.
scenario=upsert-failure exit=1
contract_writes=0
skill_file_upserts=1
error: supporting-file phase failed before contract activation; no workspace, skill-body, agent, or attachment writes were attempted.

Read-only live content checks reported workspace/skill drift and the validator missing; dry-run exited 0 and verify exited 1 with exactly three drift items. Exact-mapped topology dry-run exited 0 with three agent drift items; verify exited 1 with the same three. No apply or live mutation was performed.

PR body, scope, rollback, and PR #22

Canonical body validation passes:

originating=1 author=1 summary=1 why=1 approach=1 tested=1 rollback=1 out_of_scope=1
rollback_blast_radius=True rollback_time=True
markdown_links=PASS diff_secret_scan=PASS

The rollback plan uses git revert <merge-commit>, names single-feature blast radius, and gives under-one-minute/one-content-sync-cycle recovery. The 20-file diff is scoped to STO-402's contracts, callers, validator, sync, and tests. PR #22 remains open/ready at 659d08f4f8f284cb66cb6cd7824f9c6f5d0bf8bc with contradictory fallback surfaces; it remains a separate human merge gate.

Accepted choice: Request changes and escalate this terminal finding to the human.

Rejected alternatives:

  • Approve because repository suites pass; their activity stub does not model the pinned server's Squad-assignment, leader-identity, or task-ownership checks.
  • Remove only the activity call; that would violate the mandatory close contract.
  • Authorize another automated correction; correction round 2 exhausted the issue cap.

Constraint: A terminal PR-sweep close must execute against Multica v0.4.11, but its CI-owned direct-agent issue cannot satisfy that version's Squad-leader activity endpoint.

@stone16 stone16 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Verdict: request changes.

Standards

  • [P1] Runtime instructions depend on repository files that are not in the profession bundle. agents/orchestrator/skill.md:214 requires the deployed Orchestrator to build children from templates/squad-issue.md, while docs/operating-model.md:25 requires profession bundles to be self-contained and the Orchestrator supporting files contain only the validator. A valid checkpoint/E2E trigger therefore depends on a target-repository file the agent is not guaranteed to have. Inline the contract or ship it as an Orchestrator supporting file and test the deployed bundle.
  • [P1] The retro close-out has the same cross-profession hole. agents/orchestrator/skill.md:227 delegates the parent retro format to the Engineer's harness procedure. The Orchestrator cannot reliably construct/verify that DoD from its own bundle, so a completed E2E child can leave the parent permanently in review. Move the retro schema and acceptance semantics into the Orchestrator contract.
  • [P2] The accepted Change Proposal cannot supply the required owner. agents/pm/skill.md:162-164 requires the exact owning Squad to come from the accepted proposal, but the proposal template at :129-152 has no owning-Squad field. Add and validate that decision before splitting.

Spec

  • [P1] PR-sweep cannot execute its claimed activity→status close path. Review issues are created/reassigned to individual agents at .github/scripts/pr-sweep.sh:632, :954, and :1009, then :1096 calls multica squad activity. Multica 0.4.11 rejects that endpoint unless the issue is assigned to a Squad and the authenticated actor is that Squad's leader with an X-Task-ID belonging to the issue. GitHub Actions has neither leader-agent nor task context, so the approve path will stop before done/consensus. The stub at tests/pr-sweep.test.sh:799-802 always succeeds and masks this.
  • [P1] Result recovery trusts an unauthenticated, predictable marker. .github/scripts/pr-sweep.sh:547-558 accepts any comment containing a marker derived from public PR data. Prompt-injected review output can therefore be selected as the authoritative result (or two copies can permanently block closure). Authenticate the automation-authored result instead of matching arbitrary comment text.
  • [P2] Split implementation Issues lose the label required by their downstream trigger. agents/pm/skill.md:175-178 preserves impl only in title/body, but the product-review route at :41 and :231-233 still requires an impl label. Resolve the label UUID and call multica issue label add, or change the downstream classifier.

All declared repository tests pass in an isolated worktree, but they do not exercise these production contracts.

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.

1 participant