repo-harness 0.25.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -39
- package/agents/fleet/orchestrator.md +3 -2
- package/assets/herdr/github-events/filter.mjs +73 -0
- package/assets/herdr/github-events/worker.mjs +92 -0
- package/assets/herdr/github-events/wrangler.json +11 -0
- package/assets/herdr/webhook-notify/bot-event.mjs +35 -0
- package/assets/herdr/webhook-notify/notify.mjs +14 -13
- package/assets/reference-configs/agentic-development-flow.md +7 -2
- package/assets/reference-configs/external-tooling.md +22 -29
- package/assets/reference-configs/global-working-rules.md +1 -0
- package/assets/reference-configs/harness-overview.md +4 -2
- package/assets/reference-configs/herdr-notify.md +63 -6
- package/assets/reference-configs/hook-operations.md +2 -3
- package/assets/reference-configs/host-invariants.md +2 -3
- package/assets/skill-commands/AGENTS.md +1 -1
- package/assets/skill-commands/CLAUDE.md +1 -1
- package/assets/skill-commands/manifest.json +11 -30
- package/assets/skill-commands/repo-harness-architecture/references/worker.md +14 -5
- package/assets/skill-commands/repo-harness-ship/SKILL.md +2 -1
- package/assets/skill-version.json +2 -2
- package/assets/skills/repo-harness-issue-flow/SKILL.md +6 -1
- package/assets/skills/repo-harness-issue-flow/references/acceptor.md +6 -1
- package/assets/skills/repo-harness-issue-flow/references/board.md +35 -11
- package/assets/skills/repo-harness-issue-flow/references/events.md +117 -0
- package/assets/skills/repo-harness-issue-flow/references/orchestrator.md +191 -13
- package/assets/skills/repo-harness-issue-flow/references/replan.md +99 -0
- package/assets/skills/repo-harness-issue-flow/references/templates.md +76 -0
- package/assets/skills/repo-harness-issue-flow/references/worker.md +15 -0
- package/assets/skills/repo-harness-product/SKILL.md +2 -2
- package/assets/skills/repo-harness-test/references/authoring.md +4 -5
- package/assets/skills/repo-harness-test/references/verification-plan.md +0 -1
- package/assets/templates/helpers/capability-resolver.ts +4 -1
- package/assets/templates/runtime.gitignore +1 -0
- package/assets/workflow-contract.v1.json +3 -50
- package/cordis.patch.yml +1 -1
- package/dist/dsh/client.js +132 -0
- package/dist/dsh/package.json +21 -0
- package/dist/dsh/plugin.js +4526 -0
- package/dist/hook-entry.js +251 -200
- package/dist/oar-review-host.js +72 -65
- package/dist/operator-ui/assets/ArchitectureWorkspace-CY6MWVYK.js +7 -0
- package/dist/operator-ui/assets/{DocsPage-DV2HZUAM.js → DocsPage-DnPRp8Bo.js} +4 -4
- package/dist/operator-ui/assets/{abnfDiagram-VCTEODGH-Bjvx57sB.js → abnfDiagram-VCTEODGH-FrczBTcM.js} +1 -1
- package/dist/operator-ui/assets/architecture-7GRP2DOG-DJmhcRNc.js +1 -0
- package/dist/operator-ui/assets/{architectureDiagram-5GKGNRK7-DI0vCG--.js → architectureDiagram-5GKGNRK7-B7YjW5cP.js} +1 -1
- package/dist/operator-ui/assets/{blockDiagram-I7D4REHJ-BZ_YUsUS.js → blockDiagram-I7D4REHJ-VlgsJiAG.js} +1 -1
- package/dist/operator-ui/assets/{c4Diagram-7LVT6UL2-DH0Jtlli.js → c4Diagram-7LVT6UL2-D7skC_rA.js} +1 -1
- package/dist/operator-ui/assets/channel-CH26DhuI.js +1 -0
- package/dist/operator-ui/assets/{chunk-4HAMMTFA-tFJtpQE1.js → chunk-4HAMMTFA-CmMSCuUx.js} +1 -1
- package/dist/operator-ui/assets/{chunk-75Z2AOVW-CIdpTPCg.js → chunk-75Z2AOVW-C2Xq_mi9.js} +1 -1
- package/dist/operator-ui/assets/{chunk-DU6HZSFF-Bd07S2X4.js → chunk-DU6HZSFF-c1GQqTNL.js} +1 -1
- package/dist/operator-ui/assets/{chunk-F27PBJKO-DWRq64qg.js → chunk-F27PBJKO-mKGGg2lc.js} +1 -1
- package/dist/operator-ui/assets/{chunk-GMAD6QVW-Dl95AJFc.js → chunk-GMAD6QVW-BBvaMzz7.js} +1 -1
- package/dist/operator-ui/assets/{chunk-GVQU2GXP-C7OXmRjR.js → chunk-GVQU2GXP-Ciqkfb7x.js} +1 -1
- package/dist/operator-ui/assets/{chunk-IMKFNOWR-QL5B_aOs.js → chunk-IMKFNOWR-lPRrJwGG.js} +1 -1
- package/dist/operator-ui/assets/{chunk-L3NEJ4N5-ukfpnoE0.js → chunk-L3NEJ4N5-ZCELMmfj.js} +1 -1
- package/dist/operator-ui/assets/{chunk-OSK3NFVY-CnHEPnkn.js → chunk-OSK3NFVY-C2FSyex1.js} +1 -1
- package/dist/operator-ui/assets/{chunk-P2QGCYS3-BpS1hNgD.js → chunk-P2QGCYS3-BNCem-OE.js} +1 -1
- package/dist/operator-ui/assets/{chunk-POPQ4Y6H-CMPd1nz4.js → chunk-POPQ4Y6H-DLkj1nb5.js} +1 -1
- package/dist/operator-ui/assets/{chunk-PWAF6VOD-BX0WsbhE.js → chunk-PWAF6VOD-BPXpJW86.js} +1 -1
- package/dist/operator-ui/assets/{chunk-SHT3W25Y-BNEtOwXv.js → chunk-SHT3W25Y-C2LRo2LL.js} +1 -1
- package/dist/operator-ui/assets/{chunk-SVP7TREG-Bxc3jiKi.js → chunk-SVP7TREG-DzBTsX5k.js} +1 -1
- package/dist/operator-ui/assets/{chunk-TICWLB2K-DyFwShYo.js → chunk-TICWLB2K-Bcy59Hos.js} +1 -1
- package/dist/operator-ui/assets/classDiagram-ZZMXUADV-CmP13vv6.js +1 -0
- package/dist/operator-ui/assets/classDiagram-v2-VYDZK3BY-CmP13vv6.js +1 -0
- package/dist/operator-ui/assets/{cynefin-OW5HDTMX-B2H6A8Am.js → cynefin-OW5HDTMX-ClBj8Ulr.js} +1 -1
- package/dist/operator-ui/assets/{cynefinDiagram-5FMLGOSQ-nBu7H-dN.js → cynefinDiagram-5FMLGOSQ-Ds7Mibm4.js} +1 -1
- package/dist/operator-ui/assets/{dagre-GXQ25YYZ-B2in2DwM.js → dagre-GXQ25YYZ-BQdr4QZm.js} +1 -1
- package/dist/operator-ui/assets/{diagram-S7CK7UJ4-CVqDk_Fk.js → diagram-S7CK7UJ4-D2lmiWeD.js} +1 -1
- package/dist/operator-ui/assets/{diagram-UQ7AKVKN-Bhe0hBRp.js → diagram-UQ7AKVKN-O3oH4sVn.js} +1 -1
- package/dist/operator-ui/assets/{diagram-VSXAHHWV-DCmGVIr0.js → diagram-VSXAHHWV-ChWUSpJM.js} +1 -1
- package/dist/operator-ui/assets/{diagram-VX7I27RA-Bs6Vy86z.js → diagram-VX7I27RA-Ch69HZTd.js} +1 -1
- package/dist/operator-ui/assets/{diagram-Z3DM3KII-DM7HmIub.js → diagram-Z3DM3KII-BrawDVH6.js} +1 -1
- package/dist/operator-ui/assets/{ebnfDiagram-PWID7BFC-D2y4BOCF.js → ebnfDiagram-PWID7BFC-DmJK-kmd.js} +1 -1
- package/dist/operator-ui/assets/{erDiagram-RLTQ6QDP-SM1BNTfU.js → erDiagram-RLTQ6QDP-Q0HnvPDo.js} +1 -1
- package/dist/operator-ui/assets/eventmodeling-NTZA5JFV-BCV_9PCS.js +1 -0
- package/dist/operator-ui/assets/flowDiagram-HODETNUW-UuLvXIz-.js +1 -0
- package/dist/operator-ui/assets/{ganttDiagram-EL5Y4UJY-B2P50qAo.js → ganttDiagram-EL5Y4UJY-qvwdPHBY.js} +1 -1
- package/dist/operator-ui/assets/{gitGraph-4MIJSDKK-CAF_C8Dc.js → gitGraph-4MIJSDKK-Dx7BjZZV.js} +1 -1
- package/dist/operator-ui/assets/{gitGraphDiagram-WWUBYQGX-SInZ4rJX.js → gitGraphDiagram-WWUBYQGX-VMYWxpyb.js} +1 -1
- package/dist/operator-ui/assets/index-BRqR1RMk.js +25 -0
- package/dist/operator-ui/assets/index-DDZqieYX.css +2 -0
- package/dist/operator-ui/assets/{info-A6RAGUB7-Bllvf-34.js → info-A6RAGUB7-CWmAbV2v.js} +1 -1
- package/dist/operator-ui/assets/{infoDiagram-27XIBGKW-D8NT9zyX.js → infoDiagram-27XIBGKW-CbdlBmQQ.js} +1 -1
- package/dist/operator-ui/assets/{ishikawaDiagram-5VMMS53U-CE8D2a4x.js → ishikawaDiagram-5VMMS53U-DCFApDt3.js} +1 -1
- package/dist/operator-ui/assets/{journeyDiagram-3NMN7TZE-M29lG_I4.js → journeyDiagram-3NMN7TZE-JU9Lmrb8.js} +1 -1
- package/dist/operator-ui/assets/{kanban-definition-UXKFOSKX-uofpf--r.js → kanban-definition-UXKFOSKX-BaFyfuHa.js} +1 -1
- package/dist/operator-ui/assets/{line-O2iQnsVY.js → line-B0IEL5-x.js} +1 -1
- package/dist/operator-ui/assets/{mermaid-parser.core-Z8f9As5u.js → mermaid-parser.core-BY831mH1.js} +3 -3
- package/dist/operator-ui/assets/{mermaid.core-DlT9jDxk.js → mermaid.core-ButCc1lu.js} +4 -4
- package/dist/operator-ui/assets/{mindmap-definition-YA3MSWOX-DF-U4w3y.js → mindmap-definition-YA3MSWOX-BZ9lAvGW.js} +1 -1
- package/dist/operator-ui/assets/{packet-AYTQ26CC-BxumXMQA.js → packet-AYTQ26CC-B5-Y1eju.js} +1 -1
- package/dist/operator-ui/assets/{pegDiagram-XKGWAZYB-CEfYiEYk.js → pegDiagram-XKGWAZYB-Ahet4paP.js} +1 -1
- package/dist/operator-ui/assets/{pie-WAS4IAKB-dJWiJit9.js → pie-WAS4IAKB-CMEA1YN5.js} +1 -1
- package/dist/operator-ui/assets/{pieDiagram-E7YTZNPT-DNUW3YgV.js → pieDiagram-E7YTZNPT-BKoLuqEb.js} +1 -1
- package/dist/operator-ui/assets/{quadrantDiagram-AXDQQJYC-BywHKYmV.js → quadrantDiagram-AXDQQJYC-Ba5lcmOU.js} +1 -1
- package/dist/operator-ui/assets/{radar-RG4KPBEZ-DVXYXIk7.js → radar-RG4KPBEZ-DRKsFqgB.js} +1 -1
- package/dist/operator-ui/assets/{railroad-74A4TZTK-DUlxBsRj.js → railroad-74A4TZTK-UnJQj6WT.js} +1 -1
- package/dist/operator-ui/assets/railroad-abnf-HS5TGJTU-BfLADly0.js +1 -0
- package/dist/operator-ui/assets/railroad-ebnf-LZEXJU2U-Dctjf-fQ.js +1 -0
- package/dist/operator-ui/assets/railroad-peg-WCYAUIDC-DC2Nq5l8.js +1 -0
- package/dist/operator-ui/assets/{railroadDiagram-O6MQD6OU-BK5ZqcXN.js → railroadDiagram-O6MQD6OU-Ii3HCSET.js} +1 -1
- package/dist/operator-ui/assets/{requirementDiagram-BXWQKSXE-BPNZxdR4.js → requirementDiagram-BXWQKSXE-GiUPpmpF.js} +1 -1
- package/dist/operator-ui/assets/{sankeyDiagram-P5KCCOFB-A3wO6K53.js → sankeyDiagram-P5KCCOFB-CUfXBwpy.js} +1 -1
- package/dist/operator-ui/assets/{sequenceDiagram-WJ2MYXX4-DZH1qETK.js → sequenceDiagram-WJ2MYXX4-T3ZLlCgn.js} +1 -1
- package/dist/operator-ui/assets/{stateDiagram-D77RDMKH-BAxdK688.js → stateDiagram-D77RDMKH-D2AphR6j.js} +1 -1
- package/dist/operator-ui/assets/stateDiagram-v2-MP3YSRHH-DoOPJXWN.js +1 -0
- package/dist/operator-ui/assets/{swimlanes-42K2YHIH-CZCcKZu8.js → swimlanes-42K2YHIH-DNQbbl88.js} +1 -1
- package/dist/operator-ui/assets/swimlanesDiagram-VR7AAH4N-FdvvbV9Z.js +8 -0
- package/dist/operator-ui/assets/{timeline-definition-24CTP7MA-Bj5uQAgY.js → timeline-definition-24CTP7MA-Co0q_tCB.js} +1 -1
- package/dist/operator-ui/assets/{treeView-Q6P3EWNA-BEmjJl7z.js → treeView-Q6P3EWNA-B3AJbB6p.js} +1 -1
- package/dist/operator-ui/assets/{treemap-WGGIJYW6-KNjDwrtc.js → treemap-WGGIJYW6-_H9SWbfT.js} +1 -1
- package/dist/operator-ui/assets/{vennDiagram-4TSXK5OY-CQcrg6LI.js → vennDiagram-4TSXK5OY-CGfjaO6_.js} +1 -1
- package/dist/operator-ui/assets/{wardley-WFR3VGLG-DchAOldS.js → wardley-WFR3VGLG-NUDbyuOy.js} +1 -1
- package/dist/operator-ui/assets/{wardleyDiagram-VM6X3IG4-BRXjrmTb.js → wardleyDiagram-VM6X3IG4-COuGUrRm.js} +1 -1
- package/dist/operator-ui/assets/{xychartDiagram-S5SC5T6Z-BHTOn-Ft.js → xychartDiagram-S5SC5T6Z-DHG9QX-U.js} +1 -1
- package/dist/operator-ui/index.html +2 -2
- package/package.json +9 -11
- package/references/handoff.md +17 -19
- package/scripts/axr5-archctx-clean-room.ts +14 -2
- package/scripts/check-agent-tooling.sh +37 -31
- package/scripts/check-state-boundaries.ts +206 -18
- package/scripts/check-tarball-install-smoke.sh +3 -13
- package/scripts/contract-worktree-runtime.ts +6 -18
- package/scripts/lib/project-init-lib.sh +3 -5
- package/scripts/report-ci.ts +90 -18
- package/scripts/run-skill-routing-eval.ts +6 -10
- package/scripts/select-ci-coverage.ts +16 -11
- package/scripts/sync-codex-installed-copies.sh +1 -1
- package/scripts/test-file-durations.json +0 -26
- package/scripts/worktree-merge-lib.sh +1 -2
- package/src/cli/commands/adoption-plan.ts +14 -1
- package/src/cli/commands/bots.ts +0 -3
- package/src/cli/commands/doctor.ts +18 -172
- package/src/cli/commands/events.ts +174 -0
- package/src/cli/commands/global-runtime.ts +54 -85
- package/src/cli/commands/herdr.ts +1 -1
- package/src/cli/commands/init-hook.ts +9 -9
- package/src/cli/commands/init.ts +15 -54
- package/src/cli/commands/mcp.ts +10 -427
- package/src/cli/commands/operator.ts +0 -14
- package/src/cli/commands/publication.ts +4 -3
- package/src/cli/commands/retention.ts +18 -10
- package/src/cli/commands/review.ts +7 -9
- package/src/cli/commands/run.ts +1 -5
- package/src/cli/commands/setup-check-child.ts +2 -1
- package/src/cli/commands/setup-snapshot.ts +3 -3
- package/src/cli/commands/tools.ts +231 -0
- package/src/cli/commands/upgrade-registered.ts +63 -25
- package/src/cli/commands/upgrade.ts +39 -7
- package/src/cli/hook/mutation-bash.ts +6 -1
- package/src/cli/hook/mutation-guard.ts +49 -11
- package/src/cli/index.ts +42 -20
- package/src/cli/installer/configuration-ownership.ts +12 -3
- package/src/cli/installer/global-context.ts +27 -2
- package/src/cli/installer/install-profile.ts +1 -1
- package/src/cli/installer/uninstall.ts +1 -1
- package/src/cli/mcp/audit.ts +0 -42
- package/src/cli/mcp/auth.ts +30 -187
- package/src/cli/mcp/codegraph-adapter.ts +26 -24
- package/src/cli/mcp/doctor.ts +141 -0
- package/src/cli/mcp/fleet-tools.ts +4 -87
- package/src/cli/mcp/instructions.ts +4 -23
- package/src/cli/mcp/policy.ts +3 -77
- package/src/cli/mcp/server.ts +9 -149
- package/src/cli/mcp/tools.ts +6 -378
- package/src/cli/mcp/types.ts +1 -20
- package/src/core/architecture/module-view.ts +1 -10
- package/src/core/architecture/projection.ts +10 -1
- package/src/core/capabilities/ownership-blocker.ts +9 -1
- package/src/core/capabilities/registry.ts +3 -0
- package/src/core/fleet/admitted-task-message.ts +7 -6
- package/src/core/fleet/board.ts +8 -40
- package/src/core/fleet/task-message.ts +9 -15
- package/src/core/messages/task-message-error.ts +11 -1
- package/src/core/operator/admitted-task-activity.ts +1 -1
- package/src/core/operator/admitted-task-context.ts +2 -7
- package/src/core/operator/architecture.ts +19 -1
- package/src/core/operator/bot-access.ts +13 -115
- package/src/core/operator/fleet-snapshot.ts +2 -21
- package/src/core/publication/merge-readiness.ts +56 -0
- package/src/core/review/acceptance-receipt.ts +6 -0
- package/src/core/review/authority-context.ts +8 -0
- package/src/core/review/runner-port.ts +149 -0
- package/src/core/sessions/task-sessions.ts +1 -7
- package/src/core/setup/decode.ts +1 -1
- package/src/core/setup/projection.ts +1 -1
- package/src/core/setup/types.ts +3 -7
- package/src/core/skill-surface/projection-state.ts +10 -0
- package/src/dsh/bridge.ts +5 -4
- package/src/dsh/build.ts +71 -0
- package/src/dsh/client.tsx +99 -0
- package/src/dsh/guard-denials.ts +78 -0
- package/src/dsh/package.dist.json +21 -0
- package/src/dsh/plugin.ts +19 -3
- package/src/dsh/protocol.ts +16 -0
- package/src/effects/admission/admission-source.ts +3 -0
- package/src/effects/adoption/gitignore-plan.ts +9 -3
- package/src/effects/adoption/standard-plan.ts +93 -9
- package/src/effects/architecture/archctx-provider.ts +25 -2
- package/src/effects/architecture/model-reader.ts +2 -1
- package/src/effects/bot-registry.ts +18 -17
- package/src/effects/external-sources/binding.ts +7 -4
- package/src/effects/fleet/board.ts +4 -21
- package/src/effects/fleet/provider-feedback.ts +1 -1
- package/src/effects/fleet/task-inbox-layout-migration.ts +24 -10
- package/src/effects/fleet/task-inbox.ts +23 -39
- package/src/effects/host-skill-roots.ts +1 -1
- package/src/effects/locking/exclusive-directory-lock.ts +13 -0
- package/src/effects/operator/architecture.ts +15 -0
- package/src/effects/operator/bot-access.ts +8 -33
- package/src/effects/operator/execution-state.ts +3 -1
- package/src/effects/operator/server.ts +27 -438
- package/src/effects/operator/task-context.ts +0 -2
- package/src/effects/publication/merge-executor.ts +90 -17
- package/src/effects/publication/merge-readiness.ts +27 -8
- package/src/effects/review/acceptance-receipt.ts +2 -6
- package/src/effects/review/diff-fingerprint.ts +0 -6
- package/src/effects/review/generic-review.ts +59 -211
- package/src/effects/review/review-isolation.ts +1 -13
- package/src/effects/{review/oar-review-host.ts → review-runner/task-oar-host.ts} +4 -24
- package/src/effects/{review/pre-prompt-inbox-consumer.ts → review-runner/task-pre-prompt-inbox-consumer.ts} +2 -2
- package/src/effects/{review/pre-prompt-inbox.ts → review-runner/task-pre-prompt-inbox.ts} +4 -4
- package/src/effects/review-runner/task-review-runner.ts +209 -0
- package/src/effects/sessions/admitted-source.ts +2 -5
- package/src/effects/sessions/task-sessions.ts +3 -3
- package/src/effects/setup/pi-host-probe.ts +32 -0
- package/src/effects/state/coordination-worktree-topology.ts +171 -18
- package/src/effects/state/resolve-effective-state.ts +20 -17
- package/src/effects/terminal/herdr.ts +1 -1
- package/src/effects/terminal/native-task-session.ts +2 -1
- package/src/effects/terminal/task-session-admission.ts +72 -0
- package/src/effects/terminal/task-session-io.ts +24 -2
- package/src/effects/terminal/{task-session-reader.ts → task-session-record.ts} +76 -6
- package/src/effects/terminal/task-session.ts +25 -213
- package/src/effects/terminal/task-worktree-runtime.ts +25 -0
- package/src/effects/upgrade/legacy-inventory.ts +127 -7
- package/src/effects/upgrade/legacy-worktree-cleanup.ts +1 -1
- package/src/effects/upgrade/operator-decisions.ts +1 -0
- package/src/operator-web/AdmittedTaskContext.tsx +1 -2
- package/src/operator-web/App.tsx +4 -44
- package/src/operator-web/ArchitectureHistory.tsx +481 -0
- package/src/operator-web/ArchitectureWorkspace.tsx +16 -9
- package/src/operator-web/BotsPage.tsx +0 -45
- package/src/operator-web/RepositoryWorkspace.tsx +8 -87
- package/src/operator-web/app.css +109 -14
- package/src/operator-web/architecture-map-layout.ts +20 -8
- package/src/operator-web/bots.ts +1 -15
- package/src/operator-web/fixture.ts +2 -47
- package/src/operator-web/fixtures/bots.ts +6 -18
- package/src/operator-web/fixtures/index.ts +0 -3
- package/src/operator-web/fleet-api.ts +0 -40
- package/src/operator-web/i18n.ts +67 -216
- package/src/operator-web/types.ts +0 -107
- package/agents/engineers/profiles/verification-evals-checks.json +0 -17
- package/agents/engineers/profiles/workflow-engine-contract-assets.json +0 -17
- package/agents/engineers/sops/verification-evals-checks.md +0 -9
- package/agents/engineers/sops/workflow-engine-contract-assets.md +0 -9
- package/assets/skills/repo-harness-chatgpt/SKILL.md +0 -33
- package/assets/skills/repo-harness-chatgpt/references/bridge.md +0 -124
- package/assets/skills/repo-harness-chatgpt/references/consult.md +0 -92
- package/assets/skills/repo-harness-chatgpt/references/continue.md +0 -57
- package/assets/skills/repo-harness-chatgpt/references/delegate.md +0 -409
- package/assets/skills/repo-harness-chatgpt/references/orchestrate.md +0 -226
- package/assets/skills/repo-harness-chatgpt/references/read-back.md +0 -87
- package/assets/skills/repo-harness-chatgpt/references/setup.md +0 -199
- package/dist/dsh-plugin.js +0 -399
- package/dist/operator-ui/assets/ArchitectureWorkspace-BrUOPtga.js +0 -7
- package/dist/operator-ui/assets/architecture-7GRP2DOG-DwBb_elr.js +0 -1
- package/dist/operator-ui/assets/channel-CM1VQx9C.js +0 -1
- package/dist/operator-ui/assets/classDiagram-ZZMXUADV-DbQjXAzM.js +0 -1
- package/dist/operator-ui/assets/classDiagram-v2-VYDZK3BY-DbQjXAzM.js +0 -1
- package/dist/operator-ui/assets/eventmodeling-NTZA5JFV-BE74fbWW.js +0 -1
- package/dist/operator-ui/assets/flowDiagram-HODETNUW-Bv9uAODR.js +0 -1
- package/dist/operator-ui/assets/index-CPqSvndN.css +0 -2
- package/dist/operator-ui/assets/index-f-CSZ52F.js +0 -25
- package/dist/operator-ui/assets/railroad-abnf-HS5TGJTU-DNtifAEn.js +0 -1
- package/dist/operator-ui/assets/railroad-ebnf-LZEXJU2U-CYKwwuRu.js +0 -1
- package/dist/operator-ui/assets/railroad-peg-WCYAUIDC-DLC4ckY3.js +0 -1
- package/dist/operator-ui/assets/stateDiagram-v2-MP3YSRHH-0zIAKCg6.js +0 -1
- package/dist/operator-ui/assets/swimlanesDiagram-VR7AAH4N-Bkz-hKOF.js +0 -8
- package/docs/images/repo-harness-gptpro-cn.png +0 -0
- package/docs/images/repo-harness-gptpro.png +0 -0
- package/docs/repo-harness-chatgpt-browser-engine.md +0 -359
- package/scripts/codex-handoff-resume.sh +0 -65
- package/scripts/prepare-codex-handoff.sh +0 -58
- package/scripts/prepare-handoff.sh +0 -57
- package/scripts/recovery-view-cli.ts +0 -116
- package/src/cli/chatgpt-browser/binding.ts +0 -117
- package/src/cli/chatgpt-browser/engine.ts +0 -602
- package/src/cli/chatgpt-browser/file-policy.ts +0 -180
- package/src/cli/chatgpt-browser/native-provider.ts +0 -622
- package/src/cli/chatgpt-browser/oracle-provider.ts +0 -806
- package/src/cli/chatgpt-browser/oracle-session-evidence.ts +0 -128
- package/src/cli/chatgpt-browser/prompt-assembler.ts +0 -29
- package/src/cli/chatgpt-browser/secret-scan.ts +0 -139
- package/src/cli/chatgpt-browser/session-store.ts +0 -351
- package/src/cli/chatgpt-browser/types.ts +0 -212
- package/src/cli/chatgpt-skill/installer.ts +0 -131
- package/src/cli/chatgpt-skill/source.ts +0 -60
- package/src/cli/commands/chatgpt.ts +0 -440
- package/src/cli/commands/integration.ts +0 -218
- package/src/cli/mcp/coding-tools.ts +0 -645
- package/src/cli/mcp/coding-workspaces.ts +0 -734
- package/src/cli/mcp/herdr-tools.ts +0 -267
- package/src/cli/mcp/oauth.ts +0 -636
- package/src/cli/mcp/process-sessions.ts +0 -749
- package/src/cli/mcp/review-publish-tool.ts +0 -106
- package/src/cli/mcp/session-store.ts +0 -179
- package/src/cli/mcp/setup-ownership.ts +0 -60
- package/src/cli/mcp/setup.ts +0 -1419
- package/src/cli/mcp/transports/http.ts +0 -874
- package/src/cli/mcp/uninstall.ts +0 -119
- package/src/core/engineers/AGENTS.md +0 -27
- package/src/core/engineers/CLAUDE.md +0 -27
- package/src/core/engineers/agent-runtime-effect.ts +0 -603
- package/src/core/engineers/engineering-overlay.ts +0 -475
- package/src/core/engineers/principal-claim.ts +0 -164
- package/src/core/engineers/profile-binding.ts +0 -171
- package/src/core/engineers/scheduling.ts +0 -540
- package/src/core/fleet/task-reply.ts +0 -259
- package/src/core/integration/product-acceptance.ts +0 -371
- package/src/core/operator/organization-snapshot.ts +0 -147
- package/src/core/operator/planning-snapshot.ts +0 -92
- package/src/core/operator/repository-snapshot.ts +0 -12
- package/src/effects/engineers/agent-runtime-adapters/herdr-cli-agent.ts +0 -48
- package/src/effects/engineers/agent-runtime-effect-store.ts +0 -787
- package/src/effects/engineers/agent-runtime-feature.ts +0 -65
- package/src/effects/engineers/dependency-authority.ts +0 -636
- package/src/effects/engineers/engineering-overlay.ts +0 -80
- package/src/effects/engineers/scheduling.ts +0 -150
- package/src/effects/evidence/recovery-materializer.ts +0 -673
- package/src/effects/integration/product-acceptance.ts +0 -595
- package/src/effects/operator/repository-snapshot-worker.ts +0 -55
- package/src/effects/operator/repository-snapshot.ts +0 -149
- package/src/effects/profiles/profile-store.ts +0 -203
- package/src/operator-web/OrganizationSummary.tsx +0 -64
- package/src/operator-web/PlanningView.tsx +0 -48
package/README.md
CHANGED
|
@@ -145,9 +145,8 @@ bun test
|
|
|
145
145
|
|
|
146
146
|
### Success looks like this
|
|
147
147
|
|
|
148
|
-
Init writes repo-local files and
|
|
149
|
-
entry
|
|
150
|
-
`~/.codex/handoffs/`. It writes no install-managed host files. When the
|
|
148
|
+
Init writes repo-local files and one file under `HOME`: the repo registry
|
|
149
|
+
entry. It writes no install-managed host files. When the
|
|
151
150
|
required Herdr skill or the architecture projection preference is missing, init
|
|
152
151
|
reports a skipped step that names `repo-harness update`. repo-harness supplies tools and evidence; the Bot
|
|
153
152
|
decides what to schedule.
|
|
@@ -156,8 +155,8 @@ Apply ends with `=== Migration Report ===`, naming where generated hook behavior
|
|
|
156
155
|
comes from, the user-level `~/.claude/settings.json` and `~/.codex/hooks.json`
|
|
157
156
|
adapter target, the repo-local surfaces created or refreshed, and an
|
|
158
157
|
`--- External Tooling ---` readiness block. Stable intent then lives in
|
|
159
|
-
`docs/spec.md` and `docs/prds/`, task state in the GitHub issue
|
|
160
|
-
|
|
158
|
+
`docs/spec.md` and `docs/prds/`, task and resume state in the GitHub issue,
|
|
159
|
+
its claim comments and the PR. If the dry run looks wrong, stop and
|
|
161
160
|
read
|
|
162
161
|
[`hook-operations.md`](docs/reference-configs/hook-operations.md) first.
|
|
163
162
|
|
|
@@ -172,8 +171,6 @@ repo-harness upgrade decide --keep <path> # record an operator decision for a re
|
|
|
172
171
|
repo-harness upgrade --registered # preview project refresh for every registered repo; no writes
|
|
173
172
|
repo-harness uninstall --dry-run # preview owned user configuration cleanup
|
|
174
173
|
repo-harness uninstall # remove owned configuration; preserve user changes/history
|
|
175
|
-
repo-harness mcp uninstall --dry-run # preview independent MCP setup cleanup
|
|
176
|
-
repo-harness mcp uninstall --services-stopped # after stopping all MCP HTTP services
|
|
177
174
|
```
|
|
178
175
|
|
|
179
176
|
`update` and `setup check` print one leftover count. `update` does not apply
|
|
@@ -216,10 +213,9 @@ release line have no supported historical proof and remain report-only.
|
|
|
216
213
|
## Why repo-harness
|
|
217
214
|
|
|
218
215
|
- **File-backed sessions, not chat memory.** Separate Claude and Codex sessions
|
|
219
|
-
stay coordinated through the repo
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
changed files without re-deriving them.
|
|
216
|
+
stay coordinated through the repo and its GitHub issue and PR. A session can
|
|
217
|
+
end mid-task. The next one reads the issue, the latest claim status and the
|
|
218
|
+
PR, and resumes the exact next step without re-deriving it.
|
|
223
219
|
- **Token-lean by design.** Instead of grep-and-read loops that re-scan the repo
|
|
224
220
|
every session, the harness leans on a pre-built CodeGraph index for structural
|
|
225
221
|
queries and on progressive context loading: a stable ~12KB root context plus
|
|
@@ -237,7 +233,6 @@ In an adopted repo, the surface area is intentionally small:
|
|
|
237
233
|
| `docs/spec.md` and `docs/reference-configs/` | Shared standards and stable product intent that every agent session can read. |
|
|
238
234
|
| `docs/prds/` | Product intent and optional design briefs. |
|
|
239
235
|
| `tasks/lessons.md` | The one local lesson ledger. Task identity and history stay in the issue and PR. |
|
|
240
|
-
| `.ai/harness/handoff/` | Session journal and resumable status, derived from the issue, PR and repository state instead of chat memory. |
|
|
241
236
|
|
|
242
237
|
## Task Authority
|
|
243
238
|
|
|
@@ -265,7 +260,7 @@ callers while the contract lifecycle is removed.
|
|
|
265
260
|
| **Session handoff** | Record the issue, branch, evidence and next action so another agent can continue |
|
|
266
261
|
| **Progressive context loading** | A ~12KB stable root context plus ~1KB capability contracts loaded only for the files actually being touched |
|
|
267
262
|
| **CodeGraph integration** | Structural queries (callers, callees, definitions) answered from a pre-built index instead of repeated grep-and-read passes |
|
|
268
|
-
| **MCP planner sidecar** |
|
|
263
|
+
| **MCP planner sidecar** | A local MCP client reads real repo state over stdio and writes PRD artifacts, with no default source-code write access |
|
|
269
264
|
| **Claude + Codex alignment** | One user-level adapter contract, one workflow contract, and one set of repo-local artifacts shared by both hosts |
|
|
270
265
|
|
|
271
266
|
## How It Works
|
|
@@ -399,7 +394,7 @@ A dedicated linked checkout hosts one fleet `deep-reasoner` task-agent in the ad
|
|
|
399
394
|
|
|
400
395
|
### Bot merge
|
|
401
396
|
|
|
402
|
-
A local Herdr Bot
|
|
397
|
+
A local Herdr Bot runs `repo-harness publication merge` in its shell. A cloud-only Bot runs the same command in a sandbox that has repo-harness, a working `gh auth` and a checkout. It merges only when `publication.acceptance_merge` is `on` in the policy on the PR base, and it needs strict required checks and enforce_admins on the default branch. A Bot record does not grant merge permission. See [the control Bot boundary](docs/control-bot-boundary.md#bot-modes-and-merge).
|
|
403
398
|
|
|
404
399
|
## Hooks
|
|
405
400
|
|
|
@@ -461,7 +456,7 @@ Read committed architecture facts or export a module review prompt:
|
|
|
461
456
|
|
|
462
457
|
```bash
|
|
463
458
|
repo-harness module list --json
|
|
464
|
-
repo-harness module review-prompt capability.runtime-harness.
|
|
459
|
+
repo-harness module review-prompt capability.runtime-harness.task-agent-host --json
|
|
465
460
|
```
|
|
466
461
|
|
|
467
462
|
The prompt uses HEAD content. It reports uncommitted paths and their content
|
|
@@ -472,29 +467,19 @@ shards arrive. Diff mode requires both `--base <rev>` and `--head <rev>`.
|
|
|
472
467
|
|
|
473
468
|
## MCP Connector
|
|
474
469
|
|
|
475
|
-
As an optional sidecar, `repo-harness mcp` exposes workflow artifacts to
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
default source-code write access,
|
|
470
|
+
As an optional sidecar, `repo-harness mcp serve` exposes workflow artifacts to a
|
|
471
|
+
local MCP client over stdio through the default `planner` profile or the
|
|
472
|
+
`executor` profile. The client reads real repo state and writes PRDs under
|
|
473
|
+
`docs/prds/`. It has no default source-code write access, no shell and no runner. The
|
|
474
|
+
task owner directs an explicitly addressed Herdr agent to execute the task goal.
|
|
479
475
|
|
|
480
476
|
```bash
|
|
481
|
-
repo-harness mcp
|
|
482
|
-
repo-harness mcp
|
|
477
|
+
repo-harness mcp serve --repo . --profile planner
|
|
478
|
+
repo-harness mcp doctor --repo .
|
|
483
479
|
```
|
|
484
480
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
1. ChatGPT reads repo-harness workflow files through MCP.
|
|
489
|
-
2. ChatGPT writes a PRD with `write_prd_from_idea`.
|
|
490
|
-
3. ChatGPT lists existing PRDs under `docs/prds/` and reads the linked issue.
|
|
491
|
-
4. The task owner orders GitHub issues through `repo-harness-issue-flow` and
|
|
492
|
-
sends the issue Goal to an explicitly addressed Herdr agent.
|
|
493
|
-
|
|
494
|
-
General repo reader/writer tools, snapshot and index consistency, server
|
|
495
|
-
profiles, and the opt-in dev runner:
|
|
496
|
-
[`general-repo-mcp.md`](docs/reference-configs/general-repo-mcp.md). Direct-coding
|
|
497
|
-
profile: [`chatgpt-coding-mcp.md`](docs/reference-configs/chatgpt-coding-mcp.md).
|
|
481
|
+
General repo reader/writer tools, snapshot and index consistency, and server profiles:
|
|
482
|
+
[`general-repo-mcp.md`](docs/reference-configs/general-repo-mcp.md).
|
|
498
483
|
Index-stale, CodeGraph-down, and rollback operations:
|
|
499
484
|
[`general-repo-mcp-codegraph.md`](deploy/runbooks/general-repo-mcp-codegraph.md).
|
|
500
485
|
|
|
@@ -517,7 +502,7 @@ Agents read source artifacts before derived summaries:
|
|
|
517
502
|
| Current user prompt and referenced files | PR description |
|
|
518
503
|
| `AGENTS.md` / `CLAUDE.md` | Changed files and diff |
|
|
519
504
|
| The GitHub issue and PR | Verification Plan execution records and run trace |
|
|
520
|
-
| Latest
|
|
505
|
+
| Latest claim status comment on the issue | Residual risks and rollback |
|
|
521
506
|
If it disagrees with the issue, PR, checks, or handoff, the source artifacts win.
|
|
522
507
|
|
|
523
508
|
Runtime-heavy validators (Unity, browser E2E, mobile simulators, hardware rigs,
|
|
@@ -545,7 +530,6 @@ control context loading. They do not add a host permission boundary.
|
|
|
545
530
|
| `repo-harness-ship` | Bot | Explicit publication and cleanup decisions |
|
|
546
531
|
| `obsidian-memory` | Bot | Explicit memory recall or persistence |
|
|
547
532
|
| `repo-harness-cross-review` | Bot | Generic review; direct advisory runtime retired |
|
|
548
|
-
| `repo-harness-chatgpt` | Bot | Explicit integration mode and advisory decisions |
|
|
549
533
|
| `repo-harness-setup` | Worker | Assigned install, migration, repair or scaffold |
|
|
550
534
|
| `repo-harness-test` | Worker | Source tests and real fixtures |
|
|
551
535
|
| `repo-harness-architecture` | Worker | Assigned model, projection or diagram work |
|
|
@@ -612,7 +596,6 @@ dependencies.
|
|
|
612
596
|
| [herdr](https://herdr.dev/) | Required peer-terminal runtime: notification dispatch, peer collaboration, and hosting the persistent acceptance reviewer | Externally installed binary, checksum-pinned in `.ai/harness/policy.json`; replaces the retired tmux runtime |
|
|
613
597
|
| [`reverse-skill-router`](https://github.com/zhaoxuya520/reverse-skill) | Routes reverse-engineering and security tasks to specialist playbooks | Recommended explicit-only Skill (`--with-reverse-skill`); not profile-selected because upstream's target-mention authorization assumption requires independent scope review |
|
|
614
598
|
| CodeGraph (`@colbymchenry/codegraph`) | Symbol-aware navigation, impact tracing, and readiness checks for this self-host repo | Dev dependency in this repo; generated repos stay global-MCP-first unless policy opts in |
|
|
615
|
-
| [Oracle](https://github.com/steipete/oracle) by [Peter Steinberger](https://x.com/steipete) (`@steipete/oracle`, MIT) | Default GPT Pro / ChatGPT Web browser consult engine that the `chatgpt-browser` Oracle provider shells out to for `gptpro` consults | Externally-resolved binary (`--oracle-bin`, `REPO_HARNESS_ORACLE_BIN`, `node_modules/.bin`, or `PATH`); never auto-downloaded, and a missing binary is a hard `ORACLE_NOT_INSTALLED` failure |
|
|
616
599
|
| OpenAI Codex | Primary execution agent for repo-local implementation, verification, and GitHub contributor attribution when a commit materially includes Codex-authored work | External agent runtime; attribution is an explicit commit trailer, not hidden hook automation |
|
|
617
600
|
|
|
618
601
|
### GitHub Contributor Attribution
|
|
@@ -629,8 +612,8 @@ repo-harness commit scripts or hooks unless that repo adopts the same policy.
|
|
|
629
612
|
|
|
630
613
|
## Current Release
|
|
631
614
|
|
|
632
|
-
- npm package: `repo-harness@0.25.
|
|
633
|
-
- Generated workflow stamp: `repo-harness@0.25.
|
|
615
|
+
- npm package: `repo-harness@0.25.1`
|
|
616
|
+
- Generated workflow stamp: `repo-harness@0.25.1+template@0.25.1`
|
|
634
617
|
- GitHub repository: `Ancienttwo/repo-harness`
|
|
635
618
|
- Release notes and history: [`docs/CHANGELOG.md`](docs/CHANGELOG.md)
|
|
636
619
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orchestrator
|
|
3
3
|
description: Dispatch-only issue-flow coordinator. Suggested model: Opus at xhigh effort. The Claude entry runs with `claude --agent orchestrator`; other hosts load the issue-flow skill's orchestrator mode. Reads archimap and capability docs, splits issues, dispatches work, and follows PRs and CI. Never edits product code, reviews its own dispatched PRs, or dispatches subagents.
|
|
4
|
-
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
4
|
+
tools: ["Read", "Grep", "Glob", "Bash", "TaskCreate", "TaskUpdate", "TaskList", "TaskGet"]
|
|
5
5
|
model: opus
|
|
6
6
|
effort: xhigh
|
|
7
7
|
---
|
|
@@ -16,8 +16,9 @@ You may:
|
|
|
16
16
|
- Read code and docs with Read, Grep and Glob.
|
|
17
17
|
- Run read-only checks with Bash. Examples: `git status`, `git log`, `gh issue view`, `gh pr view`, `gh pr checks`.
|
|
18
18
|
- Create issues and comments with `gh issue create --body-file -` and `gh issue comment --body-file -`. Send the body on standard input. Do not write the body to a file.
|
|
19
|
-
- Dispatch work with `herdr agent prompt
|
|
19
|
+
- Dispatch work with `herdr agent prompt`. Each dispatch names the issue, the file scope, the verification command and the forbidden areas.
|
|
20
20
|
- Follow open PRs and CI. Report each result to the issue.
|
|
21
|
+
- Keep worker notices in a triage queue with TaskCreate, TaskUpdate, TaskList and TaskGet. Follow `references/orchestrator.md` §8.1 of `repo-harness-issue-flow`: answer the owner first, then take one queue item at a time by priority.
|
|
21
22
|
|
|
22
23
|
You must not:
|
|
23
24
|
- Edit product code, tests or configuration.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// GitHub event filter of the events Worker. The Worker entry can export only handlers (workerd),
|
|
2
|
+
// so the rules live in this module.
|
|
3
|
+
|
|
4
|
+
// The comment headers of assets/skills/repo-harness-issue-flow/references/templates.md.
|
|
5
|
+
export const PROTOCOL_HEADERS = [
|
|
6
|
+
'repo-harness issue claim', 'repo-harness issue claim status', 'repo-harness boundary question',
|
|
7
|
+
'repo-harness scope change', 'repo-harness decision', 'repo-harness plan', 'repo-harness handoff',
|
|
8
|
+
'repo-harness acceptance claim', 'repo-harness acceptance record', 'repo-harness review reply',
|
|
9
|
+
'repo-harness unblocked', 'repo-harness integration status',
|
|
10
|
+
];
|
|
11
|
+
export const REQUIRED_CHECK = 'Required / CI';
|
|
12
|
+
|
|
13
|
+
function pullRequest(payload) {
|
|
14
|
+
const pull = payload.pull_request;
|
|
15
|
+
return { number: pull.number, url: pull.html_url, head_sha: pull.head.sha };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const protocolHeader = (body) => {
|
|
19
|
+
const header = (body ?? '').split(/\r?\n/, 1)[0].trim();
|
|
20
|
+
return PROTOCOL_HEADERS.includes(header) ? header : null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// One GitHub delivery gives one bot event or null. `debounce` names the PR whose later pushes replace this one.
|
|
24
|
+
export function classify(name, payload, orchestratorLogin) {
|
|
25
|
+
const action = payload.action;
|
|
26
|
+
// GitHub logins are case-insensitive. The orchestrator must not wake itself with its own issues, comments or reviews.
|
|
27
|
+
const byOrchestrator = payload.sender?.login?.toLowerCase() === orchestratorLogin.toLowerCase();
|
|
28
|
+
switch (name) {
|
|
29
|
+
case 'issue_comment': {
|
|
30
|
+
const header = action === 'created' && !byOrchestrator ? protocolHeader(payload.comment.body) : null;
|
|
31
|
+
return header && { kind: 'issue.comment', data: { number: payload.issue.number, url: payload.comment.html_url, header } };
|
|
32
|
+
}
|
|
33
|
+
case 'issues':
|
|
34
|
+
if (action !== 'opened' || byOrchestrator) return null;
|
|
35
|
+
return { kind: payload.issue.title.startsWith('[CI repair]') ? 'issue.ci_repair' : 'issue.opened',
|
|
36
|
+
data: { number: payload.issue.number, url: payload.issue.html_url } };
|
|
37
|
+
case 'pull_request_review': {
|
|
38
|
+
const review = payload.review;
|
|
39
|
+
// GitHub wraps each single review comment and thread reply in an empty `commented` review; those arrive as review comments.
|
|
40
|
+
if (action !== 'submitted' || byOrchestrator || (review.state.toLowerCase() === 'commented' && !review.body)) return null;
|
|
41
|
+
return { kind: 'pr.review', data: { ...pullRequest(payload), url: review.html_url } };
|
|
42
|
+
}
|
|
43
|
+
case 'pull_request_review_comment': {
|
|
44
|
+
if (action !== 'created' || byOrchestrator) return null;
|
|
45
|
+
const url = payload.comment.html_url;
|
|
46
|
+
if (!payload.comment.in_reply_to_id) return { kind: 'pr.review_thread', data: { ...pullRequest(payload), url } };
|
|
47
|
+
// A reply belongs to an existing thread. Only a protocol reply, such as `review reply`, is a notice.
|
|
48
|
+
const header = protocolHeader(payload.comment.body);
|
|
49
|
+
return header && { kind: 'pr.review_reply', data: { ...pullRequest(payload), url, header } };
|
|
50
|
+
}
|
|
51
|
+
case 'pull_request':
|
|
52
|
+
if (action === 'closed') return { kind: payload.pull_request.merged ? 'pr.merged' : 'pr.closed', data: pullRequest(payload) };
|
|
53
|
+
if (action === 'synchronize') {
|
|
54
|
+
return { kind: 'pr.pushed', data: pullRequest(payload), debounce: `pr:${payload.repository.id}:${payload.pull_request.number}` };
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
case 'check_run': {
|
|
58
|
+
const run = payload.check_run;
|
|
59
|
+
// The job runs only for pull requests; other runs report it as skipped. The other jobs of a run are dropped.
|
|
60
|
+
if (action !== 'completed' || run.name !== REQUIRED_CHECK || run.conclusion === 'skipped') return null;
|
|
61
|
+
return { kind: 'ci.pr', data: { pull_requests: run.pull_requests.map((pull) => pull.number), url: run.html_url,
|
|
62
|
+
head_sha: run.head_sha, conclusion: run.conclusion } };
|
|
63
|
+
}
|
|
64
|
+
case 'workflow_run': {
|
|
65
|
+
const run = payload.workflow_run;
|
|
66
|
+
// `Required / CI` does not run on push. A cancelled run has no result.
|
|
67
|
+
if (action !== 'completed' || run.event !== 'push' || run.head_branch !== payload.repository.default_branch || run.conclusion === 'cancelled') return null;
|
|
68
|
+
return { kind: 'ci.main', data: { branch: run.head_branch, workflow: run.name, url: run.html_url, head_sha: run.head_sha, conclusion: run.conclusion } };
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// GitHub App webhook receiver. It filters GitHub events in code and sends a short bot event
|
|
2
|
+
// to the Bot routine webhook. It never calls a GitHub API and makes no decision.
|
|
3
|
+
// `repo-harness events install` stages this directory and ../webhook-notify/bot-event.mjs in the same
|
|
4
|
+
// layout, and wrangler bundles them.
|
|
5
|
+
import { botEvent } from '../webhook-notify/bot-event.mjs';
|
|
6
|
+
import { classify } from './filter.mjs';
|
|
7
|
+
|
|
8
|
+
const DEBOUNCE_SECONDS = 60;
|
|
9
|
+
const DELIVERY_TTL_SECONDS = 7 * 24 * 60 * 60;
|
|
10
|
+
const MARK_TTL_SECONDS = 24 * 60 * 60;
|
|
11
|
+
const MAX_BODY_BYTES = 1024 * 1024;
|
|
12
|
+
const SEND_TIMEOUT_MS = 5_000;
|
|
13
|
+
const DELIVERY_PATTERN = /^[\w-]{1,128}$/;
|
|
14
|
+
const encoder = new TextEncoder();
|
|
15
|
+
|
|
16
|
+
function hexBytes(hex) {
|
|
17
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
18
|
+
for (let index = 0; index < bytes.length; index++) bytes[index] = parseInt(hex.slice(index * 2, index * 2 + 2), 16);
|
|
19
|
+
return bytes;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function signatureValid(secret, header, body) {
|
|
23
|
+
const match = /^sha256=([0-9a-f]{64})$/.exec(header ?? '');
|
|
24
|
+
if (!match) return false;
|
|
25
|
+
const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']);
|
|
26
|
+
return crypto.subtle.verify('HMAC', key, hexBytes(match[1]), body);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function sendToBot(env, event) {
|
|
30
|
+
const response = await fetch(env.BOT_WEBHOOK_URL, {
|
|
31
|
+
method: 'POST', redirect: 'manual', signal: AbortSignal.timeout(SEND_TIMEOUT_MS),
|
|
32
|
+
headers: { 'content-type': 'application/json', authorization: `Bearer ${env.BOT_WEBHOOK_KEY}`, 'x-webhook-key': env.BOT_WEBHOOK_KEY },
|
|
33
|
+
body: JSON.stringify(event),
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) throw new Error(`Bot webhook returned HTTP ${response.status}.`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// KV is eventually consistent between locations. A stale read can repeat an event; it never drops one.
|
|
39
|
+
const wasSent = async (env, delivery) => await env.EVENTS_STATE.get(`delivery:${delivery}`) !== null;
|
|
40
|
+
|
|
41
|
+
async function deliver(env, { delivery, event, debounce, at }) {
|
|
42
|
+
if (await wasSent(env, delivery)) return 'duplicate';
|
|
43
|
+
if (debounce && Number(await env.EVENTS_STATE.get(debounce)) > at) return 'superseded';
|
|
44
|
+
await sendToBot(env, event);
|
|
45
|
+
// The Bot has the event. A failed mark write must not make the caller send it again.
|
|
46
|
+
try { await env.EVENTS_STATE.put(`delivery:${delivery}`, '1', { expirationTtl: DELIVERY_TTL_SECONDS }); }
|
|
47
|
+
catch { console.error(`Delivery ${delivery} was sent, but its dedupe mark was not written.`); }
|
|
48
|
+
return 'sent';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const reply = (status, text) => new Response(text, { status });
|
|
52
|
+
|
|
53
|
+
export default {
|
|
54
|
+
async fetch(request, env) {
|
|
55
|
+
if (!env.GITHUB_WEBHOOK_SECRET || !env.BOT_WEBHOOK_URL || !env.BOT_WEBHOOK_KEY || !env.ORCHESTRATOR_LOGIN) return reply(500, 'Worker config is missing.');
|
|
56
|
+
if (request.method !== 'POST') return reply(405, 'POST only.');
|
|
57
|
+
const body = await request.arrayBuffer();
|
|
58
|
+
if (body.byteLength > MAX_BODY_BYTES) return reply(413, 'Payload is too large.');
|
|
59
|
+
if (!await signatureValid(env.GITHUB_WEBHOOK_SECRET, request.headers.get('x-hub-signature-256'), body)) return reply(401, 'Invalid signature.');
|
|
60
|
+
const delivery = request.headers.get('x-github-delivery') ?? '';
|
|
61
|
+
const name = request.headers.get('x-github-event') ?? '';
|
|
62
|
+
if (!DELIVERY_PATTERN.test(delivery) || !name) return reply(400, 'Missing GitHub delivery headers.');
|
|
63
|
+
let payload;
|
|
64
|
+
try { payload = JSON.parse(new TextDecoder().decode(body)); } catch { return reply(400, 'Invalid JSON.'); }
|
|
65
|
+
const match = classify(name, payload, env.ORCHESTRATOR_LOGIN);
|
|
66
|
+
if (!match) return reply(204, null);
|
|
67
|
+
const at = Date.now();
|
|
68
|
+
const event = botEvent({ source: 'github', repository: payload.repository.name, kind: match.kind, ts: new Date(at).toISOString(), data: match.data });
|
|
69
|
+
if (match.debounce) {
|
|
70
|
+
if (await wasSent(env, delivery)) return reply(200, 'duplicate');
|
|
71
|
+
// Each push moves the PR mark forward. The queued copy sends only when no later push arrived.
|
|
72
|
+
// Queue first: a failed mark write then repeats the older push instead of dropping this one.
|
|
73
|
+
await env.EVENTS_QUEUE.send({ delivery, at, event, debounce: match.debounce }, { delaySeconds: DEBOUNCE_SECONDS });
|
|
74
|
+
await env.EVENTS_STATE.put(match.debounce, String(at), { expirationTtl: MARK_TTL_SECONDS });
|
|
75
|
+
return reply(202, 'queued');
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
return reply(200, await deliver(env, { delivery, at, event }));
|
|
79
|
+
} catch {
|
|
80
|
+
// GitHub records the failed delivery for a redelivery, and the queue retries it now.
|
|
81
|
+
await env.EVENTS_QUEUE.send({ delivery, at, event });
|
|
82
|
+
return reply(502, 'Bot delivery failed.');
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
async queue(batch, env) {
|
|
87
|
+
for (const message of batch.messages) {
|
|
88
|
+
try { await deliver(env, message.body); message.ack(); }
|
|
89
|
+
catch { message.retry(); }
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo-harness-github-events",
|
|
3
|
+
"main": "worker.mjs",
|
|
4
|
+
"compatibility_date": "2025-09-01",
|
|
5
|
+
"workers_dev": true,
|
|
6
|
+
"kv_namespaces": [{ "binding": "EVENTS_STATE" }],
|
|
7
|
+
"queues": {
|
|
8
|
+
"producers": [{ "binding": "EVENTS_QUEUE", "queue": "repo-harness-github-events" }],
|
|
9
|
+
"consumers": [{ "queue": "repo-harness-github-events", "max_retries": 10, "retry_delay": 60 }]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// The one bot event envelope. Herdr notify and the GitHub event Worker both send it, so it
|
|
2
|
+
// stays plain ESM with no dependency and no Node-only API.
|
|
3
|
+
export const BOT_EVENT_PROTOCOL = 'repo-harness.bot-event/v1';
|
|
4
|
+
export const NAME_PATTERN = /^[\w.-]{1,128}$/;
|
|
5
|
+
|
|
6
|
+
const SOURCES = ['herdr', 'github'];
|
|
7
|
+
const KIND_PATTERN = /^[a-z]+(\.[a-z_]+)+$/;
|
|
8
|
+
|
|
9
|
+
function isPlainObject(value) {
|
|
10
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
11
|
+
const prototype = Object.getPrototypeOf(value);
|
|
12
|
+
return prototype === Object.prototype || prototype === null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isIsoTimestamp(value) {
|
|
16
|
+
return typeof value === 'string' && !Number.isNaN(Date.parse(value)) && new Date(value).toISOString() === value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function assertBotEvent(value) {
|
|
20
|
+
const checks = [
|
|
21
|
+
['protocol', value?.protocol === BOT_EVENT_PROTOCOL],
|
|
22
|
+
['source', SOURCES.includes(value?.source)],
|
|
23
|
+
['repository', value?.repository === null || (typeof value?.repository === 'string' && NAME_PATTERN.test(value.repository))],
|
|
24
|
+
['kind', typeof value?.kind === 'string' && KIND_PATTERN.test(value.kind)],
|
|
25
|
+
['ts', isIsoTimestamp(value?.ts)],
|
|
26
|
+
['data', isPlainObject(value?.data)],
|
|
27
|
+
];
|
|
28
|
+
const invalid = checks.find(([, valid]) => !valid);
|
|
29
|
+
if (invalid) throw new Error(`invalid bot event: ${invalid[0]}`);
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function botEvent({ source, repository, kind, ts, data }) {
|
|
34
|
+
return assertBotEvent({ protocol: BOT_EVENT_PROTOCOL, source, repository, kind, ts, data });
|
|
35
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Adapted from ~/herdr-plugins/webhook-notify. Config and identity come from Herdr.
|
|
2
2
|
import { constants, closeSync, fchmodSync, fstatSync, mkdirSync, openSync, readSync, readdirSync, rmdirSync, existsSync, lstatSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { systemWorktreeRoot } from './worktree-location.mjs';
|
|
4
|
+
import { NAME_PATTERN, botEvent } from './bot-event.mjs';
|
|
4
5
|
import { createHash, randomUUID } from 'node:crypto';
|
|
5
6
|
import { hostname, tmpdir } from 'node:os';
|
|
6
7
|
import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
@@ -63,7 +64,6 @@ function isTemporary(path, managedRoot) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
const ID_PATTERN = /^[\w.:@/-]{1,128}$/;
|
|
66
|
-
const NAME_PATTERN = /^[\w.-]{1,128}$/;
|
|
67
67
|
|
|
68
68
|
function readIdentityFile(path) {
|
|
69
69
|
const stat = lstatSync(path);
|
|
@@ -75,12 +75,12 @@ function readIdentityFile(path) {
|
|
|
75
75
|
// repo-harness task-agent session that owns this pane. A value that cannot be read, or
|
|
76
76
|
// that two open sessions both claim, is left out: this notice never guesses a task.
|
|
77
77
|
// Herdr's repo_key is a path. It only matches the session's repository_id here and never
|
|
78
|
-
// leaves this function; the
|
|
78
|
+
// leaves this function; the bot event names the repository by Herdr's repo_name.
|
|
79
79
|
function taskIdentity(data, context, session) {
|
|
80
80
|
const key = context.worktree?.repo_key;
|
|
81
81
|
const repoKey = typeof key === 'string' && key.length <= 1024 && !/[\u0000-\u001f]/.test(key) ? key : undefined;
|
|
82
82
|
const name = context.worktree?.repo_name;
|
|
83
|
-
const identity = {
|
|
83
|
+
const identity = { repository: typeof name === 'string' && NAME_PATTERN.test(name) ? name : null };
|
|
84
84
|
const root = context.worktree?.repo_root;
|
|
85
85
|
if (typeof root !== 'string' || !isAbsolute(root)) return identity;
|
|
86
86
|
try {
|
|
@@ -133,21 +133,22 @@ export async function notify(env = process.env, send = fetch, options = {}) {
|
|
|
133
133
|
if (!config.WEBHOOK_URL || !config.WEBHOOK_KEY) throw new Error('Bot webhook config is missing.');
|
|
134
134
|
|
|
135
135
|
const now = Date.now();
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
const { repository, ...task } = taskIdentity(data, context, config.NOTIFY_SESSION);
|
|
137
|
+
const fields = {
|
|
138
|
+
host: hostname(), session: config.NOTIFY_SESSION, pane_id: data.pane_id, workspace_id: data.workspace_id,
|
|
139
139
|
agent: data.agent ?? null, display_agent: data.display_agent ?? null, title: data.title ?? null,
|
|
140
140
|
state_labels: data.state_labels ?? null, workspace_label: context.workspace_label ?? null,
|
|
141
|
-
tab_label: context.tab_label ?? null, ...
|
|
141
|
+
tab_label: context.tab_label ?? null, ...task,
|
|
142
142
|
};
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
143
|
+
const envelope = botEvent({ source: 'herdr', repository, kind: `agent.${data.agent_status}`, ts: new Date(now).toISOString(), data: fields });
|
|
144
|
+
const trace = [repository && `repo ${repository}`, fields.task && `task ${fields.task}`,
|
|
145
|
+
fields.request_id && `request ${fields.request_id}`].filter(Boolean).join(' · ');
|
|
146
|
+
const where = [fields.workspace_label, fields.tab_label].filter(Boolean).join(' / ') || fields.workspace_id;
|
|
147
|
+
const text = `Herdr ${data.agent_status}: ${fields.display_agent || fields.agent || 'agent'} @ ${where}` +
|
|
148
|
+
(fields.title ? `\n${fields.title}` : '') + `\npane ${fields.pane_id} · ${fields.host}` +
|
|
148
149
|
(trace ? `\n${trace}` : '');
|
|
149
150
|
const targets = [
|
|
150
|
-
{ channel: 'WEBHOOK', url: config.WEBHOOK_URL, body:
|
|
151
|
+
{ channel: 'WEBHOOK', url: config.WEBHOOK_URL, body: envelope,
|
|
151
152
|
headers: { authorization: `Bearer ${config.WEBHOOK_KEY}`, 'x-webhook-key': config.WEBHOOK_KEY } },
|
|
152
153
|
{ channel: 'SLACK', url: config.SLACK_WEBHOOK_URL,
|
|
153
154
|
body: { text: text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>') } },
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
2. Open a branch; isolate a worktree when concurrent edits overlap. Preserve unrelated work.
|
|
10
10
|
3. Make small, bounded commits. Ordinary tasks live in the PR description: goal, changes, verification, risk and rollback.
|
|
11
11
|
4. Freeze the candidate and verify once: typecheck plus affected tests. Reviewers and closeout consume the same evidence. Reopen acceptance only for blocking defects or changed inputs that affect the result. Record non-blocking improvements separately; do not change the frozen candidate for them.
|
|
12
|
-
5. A model may squash-merge into main only when the current task explicitly authorizes main publication, the branch contains the current main tip, the required checks pass on that exact head, and GitHub has no outstanding change requests or unresolved review threads. An explicit no-merge instruction always wins. The next merge does not wait for the main push CI of the previous merge. Pending main push CI is not an extra acceptance gate. Read its status before the next merge; when it fails, the next merge is the revert or the fix. Each PR still meets its own exact-head and current-main requirements. Record the GitHub merge SHA and parent SHA. Record `git revert --no-edit <squash-commit>`. Do not create rollback tags.
|
|
12
|
+
5. A model may squash-merge into main only when the current task explicitly authorizes main publication, the branch contains the current main tip, the required checks pass on that exact head, and GitHub has no outstanding change requests or unresolved review threads that a person started. A thread that a review bot (a GitHub App account such as Codex or Copilot) started is advisory and does not block the merge. An explicit no-merge instruction always wins. The next merge does not wait for the main push CI of the previous merge. Pending main push CI is not an extra acceptance gate. Read its status before the next merge; when it fails, the next merge is the revert or the fix. Each PR still meets its own exact-head and current-main requirements. Record the GitHub merge SHA and parent SHA. Record `git revert --no-edit <squash-commit>`. Do not create rollback tags.
|
|
13
13
|
6. Run the full suite daily, automatically open a repair task on failure, and produce the daily merge/check/rollback report. Run the [Lessons Retro](#lessons-retro) in the same nightly window.
|
|
14
14
|
7. Use the [Report SOP](#report-sop) for formal progress, phase and final reports to the user, including the daily user summary. Raw automated CI reports are evidence inputs; they do not replace that summary and do not require this format.
|
|
15
15
|
|
|
@@ -93,7 +93,7 @@ An internal PR uses Daily Flow step 5 and the main-merge boundary in [Four opera
|
|
|
93
93
|
An external PR never uses the internal flow. A worker produces the ready-for-GO bundle from `references/pr-verification.md`, whose hazard scan uses the [change hazard list](#change-hazards). The PR merges only after automated checks pass and the repository owner gives an explicit GO for the reviewed head SHA. Merge with `gh pr merge <pr> --squash --match-head-commit <reviewed-sha>`. A new head SHA needs a new bundle and a new GO.
|
|
94
94
|
|
|
95
95
|
## Four operation boundaries
|
|
96
|
-
- Main merge requires explicit current-task authorization, current automated checks, no outstanding change requests or unresolved review threads, exact head/base and conflict safety.
|
|
96
|
+
- Main merge requires explicit current-task authorization, current automated checks, no outstanding change requests or unresolved review threads that a person started, exact head/base and conflict safety.
|
|
97
97
|
- Only merged, clean, inactive worktrees/branches may be deleted automatically; other deletion requires the user.
|
|
98
98
|
- Credentials, permissions, sandbox/write grants and confirmation-bypass settings require user approval of the exact change.
|
|
99
99
|
- Release and production effects require user approval of the exact artifact and operation.
|
|
@@ -138,6 +138,10 @@ The diff sets the tier. The author does not: a human change and a model change w
|
|
|
138
138
|
|
|
139
139
|
Review follows the `repo-harness-issue-flow` skill, [references/acceptor.md](../../assets/skills/repo-harness-issue-flow/references/acceptor.md). The tier selects the depth: no independent review for Low, one fresh-context review for Medium, and the gatekeeper plus one cross-model review for High, one round each. The Acceptor SOP owns the round, findings and publish steps.
|
|
140
140
|
|
|
141
|
+
Low accept-seat skip: a Low PR whose `Required / CI` is SUCCESS on the PR head and whose PR body holds the author verification evidence (the commands and their outcomes) takes no accept seat and no acceptance record. Do not dispatch a Codex, Herdr or OAR accept seat for it. `Required / CI` and that evidence are the proof surface. A Low PR that lacks either condition is not eligible to merge until both hold. Medium and High keep the full Acceptor SOP.
|
|
142
|
+
|
|
143
|
+
Worked example (docs-only Low path): the PR edits `docs/bot-onboarding.md` only. The author runs one check command and records the command and its outcome (exit 0) in the PR body. `Required / CI` is SUCCESS on the PR head. The PR needs no reviewer, and it is eligible to merge with no accept seat and no acceptance record.
|
|
144
|
+
|
|
141
145
|
Rules for every tier:
|
|
142
146
|
- The reviewer reads the current diff only. A defect in code the diff did not touch is a non-blocking note; open an issue for it, do not add a finding.
|
|
143
147
|
- From the second round, the reviewer reads only the hunks that changed after the previous round. The three-round limit stays.
|
|
@@ -145,6 +149,7 @@ Rules for every tier:
|
|
|
145
149
|
- A low tier adds no review. A new test file or a rebase does not raise the tier.
|
|
146
150
|
- Changing implementation and test assertions together does not raise the tier. Within the tier's existing review, check whether assertions preserve the intended behavior and whether removed or weakened coverage has a valid requirement-based reason. At Low, the author performs this check in self-review. Record the reason for each assertion change in the PR; never change assertions only to make a test pass. Do not dispatch a separate test-review gate.
|
|
147
151
|
- A parent, coordinator or merge session reuses recorded acceptance when the reviewed diff, relevant base context, verification inputs and environment still match, and the review meets the current tier. The PR records the reviewed revision or diff, commands, results and finding dispositions. A change of session or reviewer is not a reason to repeat acceptance.
|
|
152
|
+
- A batch integration PR (`repo-harness-issue-flow`, [references/orchestrator.md](../../assets/skills/repo-harness-issue-flow/references/orchestrator.md) §9.3) reuses the acceptance record of each member when every member merged without conflict and the batch adds no commit of its own. It needs no new review round. A Low member has no acceptance record to reuse. Required checks on the batch head still apply.
|
|
148
153
|
- After a change, verify the affected behavior and review the changed hunks with their affected context. Retain valid evidence for unchanged scope; add only missing tier coverage. A rebase alone does not require a new full review, but changed base behavior or conflict resolution can invalidate affected evidence. Reuse never substitutes for required checks on the current head or the current-main merge requirement.
|
|
149
154
|
- A downstream repository maps its own release surfaces, for example public API, wire format, DDL/SQL and permissions, to the High tier.
|
|
150
155
|
|
|
@@ -131,7 +131,7 @@ then `repo-harness uninstall --recover-interrupted` to apply it. This explicit
|
|
|
131
131
|
recovery restores the recorded fragments even if they were edited after interruption;
|
|
132
132
|
sibling fields remain. The target must include every affected host.
|
|
133
133
|
|
|
134
|
-
Package-manager globals, the official Codex plugin,
|
|
134
|
+
Package-manager globals, the official Codex plugin, the MCP config,
|
|
135
135
|
archives and runtime history remain. Repository unadoption and package removal are
|
|
136
136
|
separate operations; this command does not enumerate other repositories or remove
|
|
137
137
|
third-party packages. Remove the CLI package only after configuration cleanup.
|
|
@@ -308,31 +308,18 @@ updates skills.
|
|
|
308
308
|
|
|
309
309
|
### Waza
|
|
310
310
|
|
|
311
|
-
|
|
311
|
+
Every host uses one command. The `codex` agent writes the staging copy in
|
|
312
|
+
`~/.agents/skills`:
|
|
312
313
|
|
|
313
314
|
```bash
|
|
314
|
-
bunx skills add tw93/Waza -g -a
|
|
315
|
+
bunx skills add tw93/Waza -g -a codex -s think hunt check health -y
|
|
315
316
|
```
|
|
316
317
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
bunx skills add tw93/Waza -g -a claude-code -s think hunt check health -y
|
|
321
|
-
```
|
|
318
|
+
Then `repo-harness install` links the host skill roots to the staging copy.
|
|
322
319
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
After installing or updating through the skills CLI, verify Codex has its own
|
|
326
|
-
runtime copy:
|
|
320
|
+
Verify that the Codex skills and shared rules match the staging copy:
|
|
327
321
|
|
|
328
322
|
```bash
|
|
329
|
-
for d in think hunt check health; do
|
|
330
|
-
rsync -a --delete ~/.agents/skills/$d/ ~/.codex/skills/$d/
|
|
331
|
-
done
|
|
332
|
-
mkdir -p ~/.codex/rules
|
|
333
|
-
for f in anti-patterns.md chinese.md durable-context.md english.md; do
|
|
334
|
-
cp ~/.agents/rules/$f ~/.codex/rules/$f
|
|
335
|
-
done
|
|
336
323
|
for d in think hunt check health; do
|
|
337
324
|
diff -qr ~/.agents/skills/$d ~/.codex/skills/$d
|
|
338
325
|
done
|
|
@@ -388,11 +375,12 @@ boundary explicit:
|
|
|
388
375
|
| Capability | Owner | Required for |
|
|
389
376
|
|---|---|---|
|
|
390
377
|
| `herdr` | user install (herdr.dev) | required at the version pinned in `.ai/harness/policy.json#external_tooling.herdr`; peer terminals and persistent task reviewer hosting |
|
|
378
|
+
| `herdr_core` (`hc`) | user install (Herdr.app or a herdr-core release) | optional, at least the version pinned in `.ai/harness/policy.json#external_tooling.herdr_core`; persistent terminals and agent messaging; no repo-harness automation uses it yet |
|
|
391
379
|
| `bun` | repo-harness | repo-harness-owned global installs, local dependency install, tests, and runtime execution |
|
|
392
380
|
| `bash` | repo-harness | helper scripts, migration, setup checks, and contract verification wrappers; Git-for-Windows Bash is the Windows platform contract |
|
|
393
381
|
| `npm` | npm registry | registry readbacks, publish gates, and opt-in update checks; not repo-harness-owned global install repair |
|
|
394
382
|
| `npx` / `skills_cli` | external Skills CLI | Waza and Mermaid skill bootstrap/update commands |
|
|
395
|
-
| `rsync` | platform filesystem |
|
|
383
|
+
| `rsync` | platform filesystem | installed-copy runtime mirroring |
|
|
396
384
|
| `symlink` | platform filesystem | link-mode aliases; copy mode is the fallback |
|
|
397
385
|
|
|
398
386
|
`.ai/harness/policy.json#external_tooling.herdr` is the single herdr pin: it owns
|
|
@@ -420,9 +408,20 @@ The persistent reviewer still requires POSIX process groups: use macOS/Linux or
|
|
|
420
408
|
WSL. Native Windows review lifecycle support is not implied by Herdr support.
|
|
421
409
|
Admitted task sessions start only in a Herdr pane, so they and their Task Inbox and operator diff consumers are POSIX-only; on Windows, session start fails closed with `herdr_endpoint_platform_unsupported`.
|
|
422
410
|
Drain old tmux reviewers with the previous repo-harness version before upgrading.
|
|
423
|
-
Rebind endpoints explicitly as `herdr-cli-agent`; old adapter policy, capabilities
|
|
424
|
-
and live session metadata are not translated. The self-host runtime remains off.
|
|
425
411
|
No runtime or collaboration path automatically falls back to tmux.
|
|
412
|
+
|
|
413
|
+
herdr-core (`hc`) is a separate product with its own pin. It has persistent
|
|
414
|
+
terminals and a JSON-RPC API, and it has built-in remote host access
|
|
415
|
+
(`hc machine`, `hc run --on <machine>`). It has no sessions, panes,
|
|
416
|
+
workspaces or plugins. `check-agent-tooling.sh` reports it as the optional
|
|
417
|
+
`runtime_capabilities.herdr_core`; `setup check` projects `runtime.herdr_core`.
|
|
418
|
+
`hc --version` must report at least the `min_version` at
|
|
419
|
+
`.ai/harness/policy.json#external_tooling.herdr_core`. CI does not install hc.
|
|
420
|
+
The two checks are independent: `hc` never satisfies `runtime.herdr`, the
|
|
421
|
+
`herdr` skill or strict readiness. The transport, task sessions,
|
|
422
|
+
`review --launch herdr`, operator collectors, the `herdr notify` plugin, the
|
|
423
|
+
`herdr` skill, doctor and CI stay classic-only. No runtime falls back to the
|
|
424
|
+
other.
|
|
426
425
|
The native protected-helper tool contract below remains a separate boundary.
|
|
427
426
|
|
|
428
427
|
The policy is Bun-first, not Bun-only. Repo-harness-owned install/repair commands
|
|
@@ -676,13 +675,7 @@ boundary for untrusted repositories.
|
|
|
676
675
|
|
|
677
676
|
```bash
|
|
678
677
|
bunx skills update
|
|
679
|
-
|
|
680
|
-
rsync -a --delete ~/.agents/skills/$d/ ~/.codex/skills/$d/
|
|
681
|
-
done
|
|
682
|
-
mkdir -p ~/.codex/rules
|
|
683
|
-
for f in anti-patterns.md chinese.md durable-context.md english.md; do
|
|
684
|
-
cp ~/.agents/rules/$f ~/.codex/rules/$f
|
|
685
|
-
done
|
|
678
|
+
repo-harness install
|
|
686
679
|
for d in think hunt check health; do
|
|
687
680
|
diff -qr ~/.agents/skills/$d ~/.codex/skills/$d
|
|
688
681
|
done
|
|
@@ -96,6 +96,7 @@ When a task requires broad research, repo archaeology, multi-source synthesis, o
|
|
|
96
96
|
- Submit peer messages with `herdr agent prompt` to an explicit agent target. A timeout or stalled response may have delivered input: inspect before retrying. Submission and lifecycle status are not task ACK or acceptance.
|
|
97
97
|
- For a task-owned collaborator, use the herdr skill in the explicitly identified session: start the agent in its own pane, send requests with `herdr agent prompt`, and keep the pane through the task so advisor/gatekeeper processes survive individual owner turns. A linked checkout is grouped under its primary repository workspace.
|
|
98
98
|
- Herdr pane layout: put at most 3 panes side by side in one tab. Split with `--direction right` only; never split down, even when the herdr skill suggests it for a narrow pane. When the tab is full, create a new tab.
|
|
99
|
+
- For issue-flow work, follow the orchestrator, advisor and worker topology, the pane cleanup and the herdr-core (`HC_TERMINAL_ID`) commands in [Herdr Dispatch](https://github.com/Ancienttwo/repo-harness/blob/main/docs/reference-configs/herdr-notify.md#herdr-dispatch). With both `HC_TERMINAL_ID` and `HERDR_ENV=1` set, the multiplexers are nested: refuse.
|
|
99
100
|
- Agents may inspect each other's history with `herdr agent read <name> --source recent-unwrapped` in the explicit session. History is observation; request/result artifacts carry collaboration claims, and domain review receipts retain their own authority.
|
|
100
101
|
- After the whole task completes, close the panes you created with `herdr pane close`. Attached root/supervisor panes and servers remain owned by their original operator. Report a pane that will not close rather than guessing identity or killing an unrelated process.
|
|
101
102
|
- Missing or unusable herdr stops terminal collaboration with a clear error. Do not fall back to tmux or nest terminal multiplexers. Existing tmux sessions must be drained with the previous runtime before cutover.
|
|
@@ -64,7 +64,8 @@ context is valid and records `model_relation` in the receipt.
|
|
|
64
64
|
- Review: an acceptor returns one `AcceptanceReviewResult`. The session
|
|
65
65
|
that runs the round publishes it with
|
|
66
66
|
`repo-harness review publish --pr <n> --receipt <path>`. The merge
|
|
67
|
-
executor refuses an unresolved review thread.
|
|
67
|
+
executor refuses an unresolved review thread that a person started. A
|
|
68
|
+
thread that a review bot (a GitHub App account) started is advisory.
|
|
68
69
|
- Merge: `repo-harness publication merge` runs only when
|
|
69
70
|
`publication.acceptance_merge` is `on` on the PR base. Otherwise the
|
|
70
71
|
owner merges.
|
|
@@ -78,7 +79,8 @@ context is valid and records `model_relation` in the receipt.
|
|
|
78
79
|
## Boundaries
|
|
79
80
|
|
|
80
81
|
- Main merge requires current-task authorization, passing checks on the
|
|
81
|
-
exact head, no unresolved review threads
|
|
82
|
+
exact head, no unresolved review threads that a person started and a
|
|
83
|
+
current base. Review bot threads are advisory.
|
|
82
84
|
- Delete automatically only merged, clean, unowned worktrees and branches.
|
|
83
85
|
Ask the user for every other deletion.
|
|
84
86
|
- Credentials, permissions, sandbox grants and confirmation bypass need
|