@azure-id/orc 0.55.0
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/CHANGELOG.md +2017 -0
- package/README-id.md +521 -0
- package/README.md +485 -0
- package/bin/build-agents.js +86 -0
- package/bin/cli.js +29050 -0
- package/bin/mockrun-catalog.js +267 -0
- package/bin/onboarding-content.js +172 -0
- package/bin/pricing.json +200 -0
- package/bin/providers.json +437 -0
- package/bin/ui.js +95 -0
- package/bin/verify-contracts.js +3277 -0
- package/bin/verify-package.js +498 -0
- package/bin/webui/api.js +1163 -0
- package/bin/webui/app.html +198 -0
- package/bin/webui/css/00-tokens.css +92 -0
- package/bin/webui/css/01-base.css +42 -0
- package/bin/webui/css/02-shell.css +103 -0
- package/bin/webui/css/03-components.css +462 -0
- package/bin/webui/css/04-motion.css +91 -0
- package/bin/webui/css/05-tour.css +100 -0
- package/bin/webui/css/06-responsive.css +108 -0
- package/bin/webui/css/panels/boundary.css +26 -0
- package/bin/webui/css/panels/challenge.css +151 -0
- package/bin/webui/css/panels/crosslink.css +194 -0
- package/bin/webui/css/panels/docs.css +254 -0
- package/bin/webui/css/panels/experiment.css +23 -0
- package/bin/webui/css/panels/extra.css +536 -0
- package/bin/webui/css/panels/flow.css +177 -0
- package/bin/webui/css/panels/handoff.css +67 -0
- package/bin/webui/css/panels/knowledge.css +86 -0
- package/bin/webui/css/panels/learn.css +154 -0
- package/bin/webui/css/panels/maintenance.css +55 -0
- package/bin/webui/css/panels/mockrun.css +268 -0
- package/bin/webui/css/panels/overview.css +100 -0
- package/bin/webui/css/panels/pact.css +43 -0
- package/bin/webui/css/panels/runs.css +105 -0
- package/bin/webui/css/panels/settings.css +227 -0
- package/bin/webui/css/panels/stats.css +87 -0
- package/bin/webui/fixtures/boundary.js +92 -0
- package/bin/webui/fixtures/challenge.js +825 -0
- package/bin/webui/fixtures/crosslink.js +31 -0
- package/bin/webui/fixtures/docs.js +982 -0
- package/bin/webui/fixtures/extra.js +1934 -0
- package/bin/webui/fixtures/flow.js +81 -0
- package/bin/webui/fixtures/handoff.js +35 -0
- package/bin/webui/fixtures/index.js +486 -0
- package/bin/webui/fixtures/knowledge.js +291 -0
- package/bin/webui/fixtures/maintenance.js +42 -0
- package/bin/webui/fixtures/mockrun.js +36 -0
- package/bin/webui/fixtures/pact.js +111 -0
- package/bin/webui/fixtures/runs.js +109 -0
- package/bin/webui/fixtures/settings.js +78 -0
- package/bin/webui/fixtures/shell.js +48 -0
- package/bin/webui/fixtures/stats.js +104 -0
- package/bin/webui/i18n/TERMS.md +134 -0
- package/bin/webui/i18n/en/banner.json +29 -0
- package/bin/webui/i18n/en/boundary.json +20 -0
- package/bin/webui/i18n/en/challenge.json +106 -0
- package/bin/webui/i18n/en/common.json +69 -0
- package/bin/webui/i18n/en/crosslink.json +69 -0
- package/bin/webui/i18n/en/docs.json +175 -0
- package/bin/webui/i18n/en/experiment.json +17 -0
- package/bin/webui/i18n/en/extra.json +313 -0
- package/bin/webui/i18n/en/flow.json +30 -0
- package/bin/webui/i18n/en/handoff.json +37 -0
- package/bin/webui/i18n/en/knowledge.json +141 -0
- package/bin/webui/i18n/en/learn.json +16 -0
- package/bin/webui/i18n/en/maintenance.json +52 -0
- package/bin/webui/i18n/en/mockrun.json +19 -0
- package/bin/webui/i18n/en/nav.json +19 -0
- package/bin/webui/i18n/en/overview.json +89 -0
- package/bin/webui/i18n/en/pact.json +36 -0
- package/bin/webui/i18n/en/runs.json +51 -0
- package/bin/webui/i18n/en/settings.json +49 -0
- package/bin/webui/i18n/en/stats.json +69 -0
- package/bin/webui/i18n/en/tour.json +33 -0
- package/bin/webui/i18n/id/banner.json +29 -0
- package/bin/webui/i18n/id/boundary.json +20 -0
- package/bin/webui/i18n/id/challenge.json +106 -0
- package/bin/webui/i18n/id/common.json +70 -0
- package/bin/webui/i18n/id/crosslink.json +69 -0
- package/bin/webui/i18n/id/docs.json +175 -0
- package/bin/webui/i18n/id/experiment.json +17 -0
- package/bin/webui/i18n/id/extra.json +313 -0
- package/bin/webui/i18n/id/flow.json +30 -0
- package/bin/webui/i18n/id/handoff.json +37 -0
- package/bin/webui/i18n/id/knowledge.json +141 -0
- package/bin/webui/i18n/id/learn.json +16 -0
- package/bin/webui/i18n/id/maintenance.json +52 -0
- package/bin/webui/i18n/id/mockrun.json +19 -0
- package/bin/webui/i18n/id/nav.json +19 -0
- package/bin/webui/i18n/id/overview.json +89 -0
- package/bin/webui/i18n/id/pact.json +36 -0
- package/bin/webui/i18n/id/runs.json +51 -0
- package/bin/webui/i18n/id/settings.json +49 -0
- package/bin/webui/i18n/id/stats.json +69 -0
- package/bin/webui/i18n/id/tour.json +33 -0
- package/bin/webui/js/00-core.js +115 -0
- package/bin/webui/js/01-i18n.js +149 -0
- package/bin/webui/js/02-ui.js +211 -0
- package/bin/webui/js/03-md.js +286 -0
- package/bin/webui/js/04-router.js +51 -0
- package/bin/webui/js/05-banners.js +172 -0
- package/bin/webui/js/06-edit.js +183 -0
- package/bin/webui/js/90-tour.js +488 -0
- package/bin/webui/js/91-shortcuts.js +126 -0
- package/bin/webui/js/99-boot.js +118 -0
- package/bin/webui/js/panels/boundary.js +104 -0
- package/bin/webui/js/panels/challenge.js +781 -0
- package/bin/webui/js/panels/crosslink.js +654 -0
- package/bin/webui/js/panels/docs.js +1338 -0
- package/bin/webui/js/panels/experiment.js +98 -0
- package/bin/webui/js/panels/extra.js +3011 -0
- package/bin/webui/js/panels/flow.js +297 -0
- package/bin/webui/js/panels/handoff.js +169 -0
- package/bin/webui/js/panels/knowledge.js +890 -0
- package/bin/webui/js/panels/learn.js +220 -0
- package/bin/webui/js/panels/maintenance.js +235 -0
- package/bin/webui/js/panels/mockrun.js +227 -0
- package/bin/webui/js/panels/overview.js +447 -0
- package/bin/webui/js/panels/pact.js +189 -0
- package/bin/webui/js/panels/runs.js +416 -0
- package/bin/webui/js/panels/settings.js +573 -0
- package/bin/webui/js/panels/stats.js +378 -0
- package/bin/webui/serve.js +557 -0
- package/mock-run/INDEX.md +106 -0
- package/mock-run/a-normal-day.md +587 -0
- package/mock-run/context-combiner.md +100 -0
- package/mock-run/extra-recovery.md +330 -0
- package/mock-run/extra-slots.md +177 -0
- package/mock-run/media/README.md +43 -0
- package/mock-run/orc-aftermath.md +392 -0
- package/mock-run/orc-boundary.md +356 -0
- package/mock-run/orc-brainstorm.md +177 -0
- package/mock-run/orc-budget.md +534 -0
- package/mock-run/orc-challenge-council.md +262 -0
- package/mock-run/orc-challenge.md +416 -0
- package/mock-run/orc-cli.md +200 -0
- package/mock-run/orc-diy.md +129 -0
- package/mock-run/orc-doc.md +448 -0
- package/mock-run/orc-explain.md +86 -0
- package/mock-run/orc-export.md +423 -0
- package/mock-run/orc-extra.md +392 -0
- package/mock-run/orc-fast.md +106 -0
- package/mock-run/orc-grill.md +151 -0
- package/mock-run/orc-handoff.md +480 -0
- package/mock-run/orc-pact.md +421 -0
- package/mock-run/orc-pattern.md +112 -0
- package/mock-run/orc-plan.md +108 -0
- package/mock-run/orc-pr-setup.md +126 -0
- package/mock-run/orc-quick.md +113 -0
- package/mock-run/orc-route.md +93 -0
- package/mock-run/orc-ui.md +125 -0
- package/mock-run/orc-ultra.md +103 -0
- package/mock-run/orc.md +157 -0
- package/mock-run/the-example-project.md +55 -0
- package/package.json +39 -0
- package/templates/agents/MODEL-MAPPING.md +168 -0
- package/templates/agents/orc-advisor-fable-5.md +50 -0
- package/templates/agents/orc-advisor-opus-5-xhigh.md +56 -0
- package/templates/agents/orc-analyst-fable-5.md +115 -0
- package/templates/agents/orc-analyze-mini-opus-5-med.md +60 -0
- package/templates/agents/orc-analyze-mini-sonnet-5-high.md +58 -0
- package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -0
- package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -0
- package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -0
- package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -0
- package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -0
- package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -0
- package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -0
- package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -0
- package/templates/agents/orc-claude-writer-opus-4-8-high.md +53 -0
- package/templates/agents/orc-claude-writer-opus-5-med.md +55 -0
- package/templates/agents/orc-context-combiner-opus-5-high.md +88 -0
- package/templates/agents/orc-doc-checker-opus-5-low.md +108 -0
- package/templates/agents/orc-doc-writer-opus-5-med.md +134 -0
- package/templates/agents/orc-executor-haiku-4-5.md +113 -0
- package/templates/agents/orc-executor-opus-4-7-high.md +114 -0
- package/templates/agents/orc-executor-opus-4-7-med.md +114 -0
- package/templates/agents/orc-executor-opus-4-8-high.md +114 -0
- package/templates/agents/orc-executor-opus-5-high.md +114 -0
- package/templates/agents/orc-executor-opus-5-low.md +114 -0
- package/templates/agents/orc-executor-opus-5-med.md +114 -0
- package/templates/agents/orc-executor-sonnet-4-6-high.md +114 -0
- package/templates/agents/orc-executor-sonnet-4-6-med.md +114 -0
- package/templates/agents/orc-executor-sonnet-5-high.md +114 -0
- package/templates/agents/orc-judge-fable-5.md +79 -0
- package/templates/agents/orc-judge-opus-5-xhigh.md +85 -0
- package/templates/agents/orc-learn-writer-opus-5-low.md +73 -0
- package/templates/agents/orc-pattern-codifier-opus-5-med.md +65 -0
- package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +63 -0
- package/templates/agents/orc-planner-fable-5.md +152 -0
- package/templates/agents/orc-planner-mini-opus-5-med.md +69 -0
- package/templates/agents/orc-planner-mini-sonnet-5-high.md +67 -0
- package/templates/agents/orc-planner-opus-5-med.md +160 -0
- package/templates/agents/orc-retro-opus-5-med.md +73 -0
- package/templates/agents/orc-retro-sonnet-5-high.md +72 -0
- package/templates/agents/orc-reviewer-fable-5.md +57 -0
- package/templates/agents/orc-reviewer-opus-5-med.md +60 -0
- package/templates/agents/orc-scout-opus-5-low.md +40 -0
- package/templates/agents/orc-scout-sonnet-4-6-high.md +39 -0
- package/templates/agents/orc-system-analyst-opus-5-high.md +120 -0
- package/templates/agents/orc-test-author-opus-5-med.md +71 -0
- package/templates/agents/orc-trace-writer-haiku-4-5.md +107 -0
- package/templates/agents/orc-verifier-opus-5-med.md +69 -0
- package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +79 -0
- package/templates/agents/orc-wiki-scanner-opus-5-med.md +81 -0
- package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +106 -0
- package/templates/commands/orc-aftermath.md +49 -0
- package/templates/commands/orc-analyze.md +21 -0
- package/templates/commands/orc-boundary.md +46 -0
- package/templates/commands/orc-brainstorm.md +51 -0
- package/templates/commands/orc-budget.md +54 -0
- package/templates/commands/orc-challenge.md +58 -0
- package/templates/commands/orc-claude.md +14 -0
- package/templates/commands/orc-diy.md +13 -0
- package/templates/commands/orc-doc.md +128 -0
- package/templates/commands/orc-explain.md +20 -0
- package/templates/commands/orc-export.md +46 -0
- package/templates/commands/orc-fast.md +15 -0
- package/templates/commands/orc-grill.md +40 -0
- package/templates/commands/orc-handoff.md +52 -0
- package/templates/commands/orc-learn.md +17 -0
- package/templates/commands/orc-mini.md +12 -0
- package/templates/commands/orc-pact.md +44 -0
- package/templates/commands/orc-pattern.md +15 -0
- package/templates/commands/orc-plan.md +22 -0
- package/templates/commands/orc-poly.md +21 -0
- package/templates/commands/orc-pr-driver.md +30 -0
- package/templates/commands/orc-pr-setup.md +31 -0
- package/templates/commands/orc-quick.md +33 -0
- package/templates/commands/orc-retro.md +17 -0
- package/templates/commands/orc-route.md +41 -0
- package/templates/commands/orc-ultra.md +17 -0
- package/templates/commands/orc-verify.md +11 -0
- package/templates/commands/orc-wiki.md +42 -0
- package/templates/commands/orc.md +16 -0
- package/templates/hooks/orc-effort-guard.js +178 -0
- package/templates/hooks/orc-statusline.js +305 -0
- package/templates/hooks/orc-trace.js +471 -0
- package/templates/hooks/orc-update-lib.js +125 -0
- package/templates/skills/_shared/README.md +50 -0
- package/templates/skills/_shared/detecting-artifacts.md +90 -0
- package/templates/skills/_shared/drift-recovery.md +98 -0
- package/templates/skills/_shared/extra-dispatch.md +1051 -0
- package/templates/skills/_shared/fable5-override.md +56 -0
- package/templates/skills/_shared/fallback-handoff.md +42 -0
- package/templates/skills/_shared/gh-stack-commands.md +65 -0
- package/templates/skills/_shared/gotchas.md +177 -0
- package/templates/skills/_shared/interview.md +144 -0
- package/templates/skills/_shared/lane-suspend.md +82 -0
- package/templates/skills/_shared/opus5-only.md +131 -0
- package/templates/skills/_shared/pr-templates.md +106 -0
- package/templates/skills/_shared/read-ladder.md +54 -0
- package/templates/skills/_shared/return-validation.md +145 -0
- package/templates/skills/_shared/smoke-gate.md +28 -0
- package/templates/skills/_shared/stack-plan.md +135 -0
- package/templates/skills/_shared/untrusted-input.md +63 -0
- package/templates/skills/context-combiner/SKILL.md +187 -0
- package/templates/skills/context-combiner/schemas/combined-report.md +78 -0
- package/templates/skills/context-combiner/schemas/combined-requirement-spec.md +87 -0
- package/templates/skills/orc/README.md +150 -0
- package/templates/skills/orc/SKILL.md +526 -0
- package/templates/skills/orc/config.md +389 -0
- package/templates/skills/orc/examples/full-run-mock.md +73 -0
- package/templates/skills/orc/references/analyst-gates.md +124 -0
- package/templates/skills/orc/references/effort-and-mode.md +224 -0
- package/templates/skills/orc/references/house-rules.md +20 -0
- package/templates/skills/orc/references/intake.md +120 -0
- package/templates/skills/orc/references/log-protocol.md +39 -0
- package/templates/skills/orc/references/pattern-gate.md +89 -0
- package/templates/skills/orc/references/plan-handoff.md +84 -0
- package/templates/skills/orc/references/preflight-report.md +220 -0
- package/templates/skills/orc/references/security-checklist.md +39 -0
- package/templates/skills/orc/references/stop-and-resume.md +160 -0
- package/templates/skills/orc/references/trace-protocol.md +314 -0
- package/templates/skills/orc/references/ultra-mode.md +123 -0
- package/templates/skills/orc/references/wave-grouping.md +121 -0
- package/templates/skills/orc/references/wiki-consult.md +177 -0
- package/templates/skills/orc/schemas/checkpoint.md +122 -0
- package/templates/skills/orc/schemas/intent-spec.md +42 -0
- package/templates/skills/orc/schemas/planning-output.md +279 -0
- package/templates/skills/orc/subskills/orc-checkpoint/SKILL.md +55 -0
- package/templates/skills/orc/subskills/orc-execution/SKILL.md +72 -0
- package/templates/skills/orc/subskills/orc-execution/core.md +151 -0
- package/templates/skills/orc/subskills/orc-execution/subagent.md +13 -0
- package/templates/skills/orc/subskills/orc-planner/SKILL.md +264 -0
- package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -0
- package/templates/skills/orc/subskills/orc-pr/SKILL.md +51 -0
- package/templates/skills/orc/subskills/orc-pr/pr.md +22 -0
- package/templates/skills/orc/subskills/orc-pr/stack-gate.md +108 -0
- package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +76 -0
- package/templates/skills/orc/subskills/orc-review-verify/core.md +135 -0
- package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -0
- package/templates/skills/orc/subskills/orc-testgen/SKILL.md +45 -0
- package/templates/skills/orc/subskills/orc-testgen/core.md +59 -0
- package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -0
- package/templates/skills/orc-advisor/SKILL.md +60 -0
- package/templates/skills/orc-aftermath/SKILL.md +136 -0
- package/templates/skills/orc-aftermath/references/report.md +95 -0
- package/templates/skills/orc-analyze/SKILL.md +220 -0
- package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -0
- package/templates/skills/orc-analyze/references/branching.md +51 -0
- package/templates/skills/orc-analyze/references/deep-mode.md +27 -0
- package/templates/skills/orc-analyze/references/thin-input.md +77 -0
- package/templates/skills/orc-analyze/schemas/report-audit.md +83 -0
- package/templates/skills/orc-analyze/schemas/report-prose.md +63 -0
- package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -0
- package/templates/skills/orc-analyze/schemas/requirement-spec.md +77 -0
- package/templates/skills/orc-analyze-mini/SKILL.md +112 -0
- package/templates/skills/orc-analyze-mini/examples/quick-analysis-mock.md +31 -0
- package/templates/skills/orc-boundary/SKILL.md +208 -0
- package/templates/skills/orc-boundary/references/card.md +78 -0
- package/templates/skills/orc-boundary/references/gate.md +113 -0
- package/templates/skills/orc-brainstorm/SKILL.md +339 -0
- package/templates/skills/orc-brainstorm/references/brainstorm-doc.md +133 -0
- package/templates/skills/orc-brainstorm/references/lenses.md +152 -0
- package/templates/skills/orc-budget/SKILL.md +225 -0
- package/templates/skills/orc-budget/references/corpus.md +87 -0
- package/templates/skills/orc-challenge/README.md +142 -0
- package/templates/skills/orc-challenge/SKILL.md +255 -0
- package/templates/skills/orc-challenge/examples/code-module.md +110 -0
- package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -0
- package/templates/skills/orc-challenge/examples/tsd-two-iterations.md +213 -0
- package/templates/skills/orc-challenge/references/conservation.md +107 -0
- package/templates/skills/orc-challenge/references/council.md +315 -0
- package/templates/skills/orc-challenge/references/cycle-state.md +185 -0
- package/templates/skills/orc-challenge/references/dimensions.md +121 -0
- package/templates/skills/orc-challenge/references/fix-brief.md +130 -0
- package/templates/skills/orc-challenge/references/intake.md +171 -0
- package/templates/skills/orc-challenge/references/kinds.md +44 -0
- package/templates/skills/orc-challenge/references/plain-english.md +98 -0
- package/templates/skills/orc-challenge/references/rubric.md +109 -0
- package/templates/skills/orc-challenge/references/sealed-slice.md +97 -0
- package/templates/skills/orc-challenge/references/verdict-doc.md +154 -0
- package/templates/skills/orc-claude/SKILL.md +199 -0
- package/templates/skills/orc-claude/examples/claude-run-mock.md +65 -0
- package/templates/skills/orc-claude/references/refresh.md +76 -0
- package/templates/skills/orc-claude/references/template.md +109 -0
- package/templates/skills/orc-diy/README.md +142 -0
- package/templates/skills/orc-diy/SKILL.md +70 -0
- package/templates/skills/orc-diy/references/blocks/analyze.md +24 -0
- package/templates/skills/orc-diy/references/blocks/execution.md +42 -0
- package/templates/skills/orc-diy/references/blocks/extra.md +55 -0
- package/templates/skills/orc-diy/references/blocks/header.md +55 -0
- package/templates/skills/orc-diy/references/blocks/mock-example.md +22 -0
- package/templates/skills/orc-diy/references/blocks/pattern.md +18 -0
- package/templates/skills/orc-diy/references/blocks/planning.md +34 -0
- package/templates/skills/orc-diy/references/blocks/review.md +18 -0
- package/templates/skills/orc-diy/references/blocks/scoring.md +16 -0
- package/templates/skills/orc-diy/references/blocks/security.md +25 -0
- package/templates/skills/orc-diy/references/blocks/ship.md +25 -0
- package/templates/skills/orc-diy/references/blocks/summary.md +18 -0
- package/templates/skills/orc-diy/references/blocks/testgen.md +17 -0
- package/templates/skills/orc-diy/references/blocks/trace.md +28 -0
- package/templates/skills/orc-diy/references/blocks/verify.md +25 -0
- package/templates/skills/orc-diy/references/blocks/wiki.md +26 -0
- package/templates/skills/orc-diy/references/compile.md +59 -0
- package/templates/skills/orc-diy/references/flow-schema.md +100 -0
- package/templates/skills/orc-diy/references/locked-blocks.md +37 -0
- package/templates/skills/orc-doc/README.md +229 -0
- package/templates/skills/orc-doc/SKILL.md +444 -0
- package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -0
- package/templates/skills/orc-doc/references/chunking.md +527 -0
- package/templates/skills/orc-doc/references/gates.md +311 -0
- package/templates/skills/orc-doc/references/generation-rules.md +122 -0
- package/templates/skills/orc-doc/references/house-rules.md +170 -0
- package/templates/skills/orc-doc/references/import-targets.md +40 -0
- package/templates/skills/orc-doc/references/plain-language.md +66 -0
- package/templates/skills/orc-doc/references/portable-markdown.md +74 -0
- package/templates/skills/orc-doc/references/resume-protocol.md +228 -0
- package/templates/skills/orc-doc/references/templates/collaboration.md +118 -0
- package/templates/skills/orc-doc/references/templates/prd.md +133 -0
- package/templates/skills/orc-doc/references/templates/report.md +102 -0
- package/templates/skills/orc-doc/references/templates/tsd.md +122 -0
- package/templates/skills/orc-doc/references/templates/workflow.md +112 -0
- package/templates/skills/orc-explain/SKILL.md +57 -0
- package/templates/skills/orc-export/SKILL.md +154 -0
- package/templates/skills/orc-fast/SKILL.md +188 -0
- package/templates/skills/orc-grill/SKILL.md +207 -0
- package/templates/skills/orc-grill/references/grill-doc.md +105 -0
- package/templates/skills/orc-handoff/SKILL.md +204 -0
- package/templates/skills/orc-handoff/references/handoff-log.md +67 -0
- package/templates/skills/orc-handoff/references/surfaces.md +88 -0
- package/templates/skills/orc-judge/SKILL.md +82 -0
- package/templates/skills/orc-learn/SKILL.md +156 -0
- package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -0
- package/templates/skills/orc-learn/references/deepen.md +70 -0
- package/templates/skills/orc-learn/references/refresh.md +65 -0
- package/templates/skills/orc-learn/references/template-knowledge.md +83 -0
- package/templates/skills/orc-learn/references/template-learning.md +67 -0
- package/templates/skills/orc-mini/SKILL.md +226 -0
- package/templates/skills/orc-mini/examples/mini-run-mock.md +50 -0
- package/templates/skills/orc-pact/SKILL.md +218 -0
- package/templates/skills/orc-pact/references/gate.md +70 -0
- package/templates/skills/orc-pact/references/ledger.md +99 -0
- package/templates/skills/orc-pattern/SKILL.md +124 -0
- package/templates/skills/orc-pattern/references/INDEX.md +73 -0
- package/templates/skills/orc-pattern/references/be-django.md +80 -0
- package/templates/skills/orc-pattern/references/be-express.md +82 -0
- package/templates/skills/orc-pattern/references/be-fastapi.md +107 -0
- package/templates/skills/orc-pattern/references/be-go.md +96 -0
- package/templates/skills/orc-pattern/references/be-nestjs.md +86 -0
- package/templates/skills/orc-pattern/references/be-postgres.md +98 -0
- package/templates/skills/orc-pattern/references/fe-a11y.md +36 -0
- package/templates/skills/orc-pattern/references/fe-angular.md +87 -0
- package/templates/skills/orc-pattern/references/fe-nextjs.md +65 -0
- package/templates/skills/orc-pattern/references/fe-perf.md +39 -0
- package/templates/skills/orc-pattern/references/fe-react.md +83 -0
- package/templates/skills/orc-pattern/references/fe-vue.md +75 -0
- package/templates/skills/orc-pattern/schemas/pattern-doc.md +62 -0
- package/templates/skills/orc-poly/SKILL.md +216 -0
- package/templates/skills/orc-poly/examples/poly-run-mock.md +51 -0
- package/templates/skills/orc-poly/references/gather.md +70 -0
- package/templates/skills/orc-poly/references/poly-spec.md +84 -0
- package/templates/skills/orc-pr-driver/README.md +349 -0
- package/templates/skills/orc-pr-driver/SKILL.md +167 -0
- package/templates/skills/orc-pr-driver/references/conflict-playbook.md +78 -0
- package/templates/skills/orc-pr-driver/references/green-gate.md +105 -0
- package/templates/skills/orc-pr-driver/references/orc-run-split.md +99 -0
- package/templates/skills/orc-pr-setup/README.md +436 -0
- package/templates/skills/orc-pr-setup/SKILL.md +184 -0
- package/templates/skills/orc-pr-setup/references/certainty-gate.md +66 -0
- package/templates/skills/orc-pr-setup/references/layer-taxonomy.md +67 -0
- package/templates/skills/orc-quick/README.md +423 -0
- package/templates/skills/orc-quick/SKILL.md +306 -0
- package/templates/skills/orc-quick/references/context-doc.md +114 -0
- package/templates/skills/orc-quick/references/dispatch-gate.md +163 -0
- package/templates/skills/orc-quick/references/gh-mode.md +127 -0
- package/templates/skills/orc-retro/SKILL.md +222 -0
- package/templates/skills/orc-retro/examples/retro-mock.md +171 -0
- package/templates/skills/orc-route/SKILL.md +165 -0
- package/templates/skills/orc-verify/SKILL.md +86 -0
- package/templates/skills/orc-verify/examples/verify-mock.md +33 -0
- package/templates/skills/orc-wiki/README.md +325 -0
- package/templates/skills/orc-wiki/SKILL.md +322 -0
- package/templates/skills/orc-wiki/examples/wiki-run-mock.md +37 -0
- package/templates/skills/orc-wiki/references/claude-md-injection.md +61 -0
- package/templates/skills/orc-wiki/references/crosslink-compile.md +39 -0
- package/templates/skills/orc-wiki/references/crosslink-kinds.md +57 -0
- package/templates/skills/orc-wiki/references/crosslink.md +284 -0
- package/templates/skills/orc-wiki/references/extra.md +79 -0
- package/templates/skills/orc-wiki/references/integrity-check.md +86 -0
- package/templates/skills/orc-wiki/references/orientation.md +51 -0
- package/templates/skills/orc-wiki/references/partial-refresh.md +203 -0
- package/templates/skills/orc-wiki/references/pattern-prewarm.md +19 -0
- package/templates/skills/orc-wiki/references/staleness.md +288 -0
- package/templates/skills/orc-wiki/schemas/crosslink-tag.md +166 -0
- package/templates/skills/orc-wiki/schemas/wiki-doc.md +120 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ORC trace hook — the deterministic BACKBONE of ORC behavior-trace logging.
|
|
6
|
+
*
|
|
7
|
+
* ORC is not a runtime; the orchestrator (a Claude session following the orc
|
|
8
|
+
* skill) writes the RICH markers. This hook writes the compaction-proof
|
|
9
|
+
* SKELETON: a `SPAWN` line when an agent is dispatched (PreToolUse on the
|
|
10
|
+
* Task/Agent tool) and a
|
|
11
|
+
* `RETURN` line when a subagent finishes (SubagentStop). Even if the model
|
|
12
|
+
* forgets to narrate after a compaction, the flow shape survives here.
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT — this hook is intentionally BLIND to the dispatched model. Claude
|
|
15
|
+
* Code does not expose a subagent's model id to hooks (it lives only in the
|
|
16
|
+
* subagent's own system prompt). The claimed-vs-actual model check is done by
|
|
17
|
+
* the orchestrator from each agent's `actual_model` return field, NOT here.
|
|
18
|
+
*
|
|
19
|
+
* Logging is PERMANENT (always on) — no config toggle. This hook is the
|
|
20
|
+
* DETERMINISTIC guarantee that a trace exists: on the first ORC-agent dispatch
|
|
21
|
+
* it BOOTSTRAPS the log folder + run pointer itself, so a `.txt` is created for
|
|
22
|
+
* every run even if the orchestrator never writes a single rich marker. That
|
|
23
|
+
* removes the old failure where nothing was ever created because the folder /
|
|
24
|
+
* pointer depended entirely on the model remembering to make them.
|
|
25
|
+
*
|
|
26
|
+
* Gating (so non-ORC Tasks are never logged, enforced in code):
|
|
27
|
+
* - a SPAWN is written (and the folder+pointer bootstrapped if missing) only
|
|
28
|
+
* when the dispatched agent name starts with `orc` — a real ORC run.
|
|
29
|
+
* - a RETURN is written only when a run pointer already exists, the run is
|
|
30
|
+
* not STALE, and the file has fewer RETURNs than SPAWNs (a RETURN can never
|
|
31
|
+
* exist without a matching observed dispatch — this is what stops stray
|
|
32
|
+
* SubagentStops from unrelated sessions bleeding into an old trace).
|
|
33
|
+
* - a SubagentStop that carries a non-ORC `agent_type` is dropped, mirroring
|
|
34
|
+
* the SPAWN gate (an unrelated subagent must never claim an ORC RETURN).
|
|
35
|
+
*
|
|
36
|
+
* Attributable RETURN (v0.31.0): the bare `RETURN` skeleton is unattributable
|
|
37
|
+
* once ≥2 agents are in flight. Each SPAWN now also pushes a pending record into
|
|
38
|
+
* a sidecar next to the trace (`<trace>.pending.json` — `[{agent, desc, ts}]`).
|
|
39
|
+
* On SubagentStop the hook resolves the finishing agent from `data.agent_type`
|
|
40
|
+
* (Claude Code's SubagentStop payload) — or, on older Claude Code that omits it,
|
|
41
|
+
* pops the oldest pending record FIFO and marks the attribution approximate
|
|
42
|
+
* (`~`). It emits `RETURN <agent> :: <desc> dur=<m>m<s>s` and, when
|
|
43
|
+
* `last_assistant_message` carries the agent's `actual_model`, appends
|
|
44
|
+
* ` model=<id>` — so the claimed-vs-actual check is deterministic even if the
|
|
45
|
+
* orchestrator forgets its VERIFY line. The sidecar is best-effort: a missing or
|
|
46
|
+
* corrupt sidecar degrades to a bare RETURN (never throws, always exit 0).
|
|
47
|
+
*
|
|
48
|
+
* Attribution hardening (v0.32.0) — three bugs a real 8-task run proved:
|
|
49
|
+
* 1. DOUBLE RETURN. A stop that carried no `agent_type` FIFO-popped another
|
|
50
|
+
* agent's pending record; the REAL `agent_type` stop then found no record
|
|
51
|
+
* and wrote a second, desc-less RETURN for the same agent. Now: an
|
|
52
|
+
* `agent_type` stop with NO matching record while OTHER records are still
|
|
53
|
+
* in flight is a DUPLICATE (its slot was already consumed) and is dropped.
|
|
54
|
+
* An empty sidecar is NOT a duplicate signal — it still degrades to a bare
|
|
55
|
+
* RETURN, and the `returns >= spawns` guard covers the empty-list repeat.
|
|
56
|
+
* 2. MISSING RETURN. The blind FIFO pop above starved the agent whose record
|
|
57
|
+
* was stolen. Now an `agent_type`-less stop only CONSUMES a record when
|
|
58
|
+
* exactly ONE is in flight; with ≥2 it writes `RETURN ~agent :: unattributed`
|
|
59
|
+
* WITHOUT consuming, so the real `agent_type` stop can still claim its own.
|
|
60
|
+
* 3. RETRO SELF-POLLUTION. `/orc-retro` dispatches `orc-retro-*`, which matched
|
|
61
|
+
* the `/^orc/` gate — the trace miner was generating trace data. `orc-retro`
|
|
62
|
+
* is now on an explicit ignore-list: never bootstraps, never SPAWN/RETURN.
|
|
63
|
+
*
|
|
64
|
+
* A FOREIGN dispatch produces NOTHING here, and that is by design (v0.50.0).
|
|
65
|
+
* `orc extra dispatch` runs a non-Claude worker through Bash, so there is no
|
|
66
|
+
* `Agent`/`Task` call for this hook to observe: no SPAWN, no RETURN, no
|
|
67
|
+
* PHASE-EDGE, and therefore no contribution to NARRATION COVERAGE either. That
|
|
68
|
+
* is the same gap `/orc-quick`'s ad-hoc recon has (P7 — Extra ships zero new
|
|
69
|
+
* agents, so a foreign worker has no agent file to name).
|
|
70
|
+
*
|
|
71
|
+
* The record instead comes entirely from orchestrator-written lines: `DISPATCH
|
|
72
|
+
* … via=extra:<profile>`, `SCORE … via=extra:<profile>` and the `EXTRA` verb,
|
|
73
|
+
* whose text `orc extra dispatch --json` composes so no lane writes a second
|
|
74
|
+
* wording. NOTHING IS ADDED TO THIS FILE FOR THEM — a hook that tried to infer
|
|
75
|
+
* a foreign dispatch from a Bash command line would be guessing, and a guessed
|
|
76
|
+
* SPAWN is worse than an absent one because `/orc-retro` would count it.
|
|
77
|
+
*
|
|
78
|
+
* Deterministic phase inference (v0.32.0): ORC agent NAMES encode their role, so
|
|
79
|
+
* the hook can segment a run into phases with zero model cooperation. When a
|
|
80
|
+
* SPAWN's role family differs from the previous SPAWN's, the hook writes one
|
|
81
|
+
* extra line first — `PHASE-EDGE <role-family> :: first=<agent>` — so even a run
|
|
82
|
+
* where every narration dispatch was forgotten still reads as
|
|
83
|
+
* planning → execution → review → verify. `/orc-retro` reads these to compute
|
|
84
|
+
* NARRATION COVERAGE (phase edges with a trace-writer SPAWN between them).
|
|
85
|
+
*
|
|
86
|
+
* Caveat a retro must read this metric with (v0.34.2): CONTINUING an existing
|
|
87
|
+
* agent emits no PreToolUse/SubagentStop pair, so the hook cannot see it. A lane
|
|
88
|
+
* driven by continuing one agent under-counts real dispatch volume — the
|
|
89
|
+
* skeleton is a floor on what happened, never a census.
|
|
90
|
+
*
|
|
91
|
+
* Rich run filenames (v0.32.0): the canonical trace name is
|
|
92
|
+
* `run-<lane>-<slug>-<DDMMYY>-<HHMMSS>.txt`, written by the orchestrating lane at
|
|
93
|
+
* run start. The hook still bootstraps its own generic `run-<DDMMYY>-<HHMMSS>.txt`
|
|
94
|
+
* when the pointer is missing; the first `orc-trace-writer-haiku-4-5` dispatch
|
|
95
|
+
* RENAMES that bootstrap file (+ sidecars) and rewrites `.current`. The hook is
|
|
96
|
+
* name-agnostic (rotation/STALE logic is pointer-based) and holds no open
|
|
97
|
+
* handles, so a rename between two hook events is safe.
|
|
98
|
+
*
|
|
99
|
+
* Pointer clobber fix (v0.34.2) — the single largest defect in the trace corpus
|
|
100
|
+
* (9 lane-less stray files across 15 graded runs).
|
|
101
|
+
* `traceStats` returns null both for "pointer written two seconds ago, the lane
|
|
102
|
+
* has not created the file yet" and for "dangling pointer, run long over", and
|
|
103
|
+
* the hook rotated on both — so the lane's own run-start step reliably caused a
|
|
104
|
+
* SPLIT run: a generic bootstrap file holding the hook skeleton, plus a rich
|
|
105
|
+
* file holding every narrated line. Now the POINTER's own mtime decides: fresh
|
|
106
|
+
* (< STALE_MS) → honor the registered name and create the file under it; only a
|
|
107
|
+
* genuinely idle pointer rotates. The lanes also `touch` the trace file in the
|
|
108
|
+
* same step as `.current`, so both halves are fixed independently.
|
|
109
|
+
*
|
|
110
|
+
* Unbounded RETURN fix (v0.34.2): an `unattributed` RETURN claims no pending
|
|
111
|
+
* record, so it is excluded from the `returns` balance and the
|
|
112
|
+
* `returns >= spawns` guard could never stop it — every stop past the first
|
|
113
|
+
* wrote another line forever. The count is now bounded by the number of records
|
|
114
|
+
* actually in flight.
|
|
115
|
+
*
|
|
116
|
+
* Run rotation (v0.23.0): `.current` is a POINTER, not a lifetime lease. A run
|
|
117
|
+
* whose trace file has been idle longer than STALE_MS is considered ENDED — the
|
|
118
|
+
* next ORC dispatch rotates to a fresh `.txt` instead of appending days of
|
|
119
|
+
* unrelated sessions into one merged file.
|
|
120
|
+
*
|
|
121
|
+
* Wiring (installed by `orc init` into .claude/settings.json):
|
|
122
|
+
* hooks.PreToolUse[] { matcher:"Task|Agent", hooks:[{command:"node <..>/orc-trace.js"}] }
|
|
123
|
+
* hooks.SubagentStop[] { hooks:[{command:"node <..>/orc-trace.js"}] }
|
|
124
|
+
* (matcher covers both names — newer Claude Code dispatches subagents via the
|
|
125
|
+
* `Agent` tool, older via `Task`; matching only `Task` silently kills SPAWN.)
|
|
126
|
+
*
|
|
127
|
+
* Contract: read hook JSON from stdin. ALWAYS exit 0 (never block a tool call —
|
|
128
|
+
* tracing must never affect a run). Fail-silent on any error.
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
const fs = require("fs");
|
|
132
|
+
const path = require("path");
|
|
133
|
+
|
|
134
|
+
// .claude/hooks/orc-trace.js → CLAUDE_DIR = .. → PROJECT_ROOT = ../..
|
|
135
|
+
const CLAUDE_DIR = path.join(__dirname, "..");
|
|
136
|
+
const PROJECT_ROOT = path.join(CLAUDE_DIR, "..");
|
|
137
|
+
|
|
138
|
+
// Minimal, tolerant YAML line-scan (repo is zero-dep — no YAML parser).
|
|
139
|
+
// Reads a top-level `key: value` scalar; ignores comments and quotes.
|
|
140
|
+
function readConfigScalar(key) {
|
|
141
|
+
const file = path.join(CLAUDE_DIR, "orc.config.yaml");
|
|
142
|
+
let text;
|
|
143
|
+
try {
|
|
144
|
+
text = fs.readFileSync(file, "utf8");
|
|
145
|
+
} catch (_) {
|
|
146
|
+
return null; // no override file → key absent (caller applies default)
|
|
147
|
+
}
|
|
148
|
+
// Anchor to column 0 — a top-level key only, matching how the CLI reads
|
|
149
|
+
// top-level scalars. Prevents an indented `log_dir:` nested under another map
|
|
150
|
+
// from being read as the global override.
|
|
151
|
+
const re = new RegExp("^" + key + "\\s*:\\s*(.+?)\\s*(?:#.*)?$", "m");
|
|
152
|
+
const m = text.match(re);
|
|
153
|
+
if (!m) return null;
|
|
154
|
+
return m[1].replace(/^['"]|['"]$/g, "").trim();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function logDir() {
|
|
158
|
+
const override = readConfigScalar("log_dir");
|
|
159
|
+
const rel = override || ".claude/orc/logs";
|
|
160
|
+
return path.isAbsolute(rel) ? rel : path.join(PROJECT_ROOT, rel);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// DDMMYY HH:MM:SS.mmm — matches the decision-log timestamp style.
|
|
164
|
+
function stamp(d) {
|
|
165
|
+
const p = (n, w) => String(n).padStart(w || 2, "0");
|
|
166
|
+
const dd = p(d.getDate());
|
|
167
|
+
const mm = p(d.getMonth() + 1);
|
|
168
|
+
const yy = p(d.getFullYear() % 100);
|
|
169
|
+
const t =
|
|
170
|
+
p(d.getHours()) + ":" + p(d.getMinutes()) + ":" + p(d.getSeconds()) +
|
|
171
|
+
"." + p(d.getMilliseconds(), 3);
|
|
172
|
+
return `${dd}${mm}${yy} ${t}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function appendLine(dir, file, actor, verb, tail) {
|
|
176
|
+
// Ensure the folder exists — the hook is the deterministic writer, so it
|
|
177
|
+
// must never depend on the orchestrator having created log_dir first.
|
|
178
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
179
|
+
// One complete line per append keeps concurrent SubagentStop writes (a wave
|
|
180
|
+
// of N parallel agents) from interleaving mid-line.
|
|
181
|
+
const line =
|
|
182
|
+
`[${stamp(new Date())}] ${String(actor).padEnd(8)} ${verb}` +
|
|
183
|
+
(tail ? ` :: ${tail}` : "") + "\n";
|
|
184
|
+
fs.appendFileSync(path.join(dir, file), line);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Generic run slug used only when the hook bootstraps a trace before the
|
|
188
|
+
// orchestrator wrote its own pointer (e.g. the model skipped run-start).
|
|
189
|
+
function bootstrapSlug(d) {
|
|
190
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
191
|
+
const dd = p(d.getDate()), mm = p(d.getMonth() + 1), yy = p(d.getFullYear() % 100);
|
|
192
|
+
const t = p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds());
|
|
193
|
+
return `run-${dd}${mm}${yy}-${t}.txt`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Lanes whose agents must NEVER be traced. `/orc-retro` MINES the traces — its
|
|
197
|
+
// hard rule 4 says it writes no trace of its own, so an `orc-retro-*` dispatch
|
|
198
|
+
// must not bootstrap a run or emit SPAWN/RETURN (that would pollute the very
|
|
199
|
+
// data it reads). Matched on the agent name, before every other gate.
|
|
200
|
+
const IGNORED_AGENTS = /^orc-retro\b/i;
|
|
201
|
+
|
|
202
|
+
// Role families for deterministic phase inference. ORC agent names encode the
|
|
203
|
+
// role, so a change of family between consecutive SPAWNs IS a phase edge.
|
|
204
|
+
// A name that maps to null never opens an edge (and never closes the previous
|
|
205
|
+
// one) — including the trace writer, whose whole job is narration.
|
|
206
|
+
function roleFamily(agent) {
|
|
207
|
+
const a = String(agent).toLowerCase();
|
|
208
|
+
if (/trace-writer/.test(a)) return null;
|
|
209
|
+
// context-combiner FIRST: it is its own phase (merging confirmed analyses),
|
|
210
|
+
// not analysis — without this the combine lane has no edge at all and is
|
|
211
|
+
// structurally invisible to /orc-retro.
|
|
212
|
+
if (/context-combiner/.test(a)) return "combine";
|
|
213
|
+
if (/analyst|analyze|scout/.test(a)) return "analysis";
|
|
214
|
+
if (/planner/.test(a)) return "planning";
|
|
215
|
+
if (/executor/.test(a)) return "execution";
|
|
216
|
+
if (/reviewer/.test(a)) return "review";
|
|
217
|
+
if (/verifier/.test(a)) return "verify";
|
|
218
|
+
if (/test-author/.test(a)) return "testgen";
|
|
219
|
+
if (/advisor|judge/.test(a)) return "ultra-gate";
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// The role family of the LAST classified SPAWN in a trace. Derived from the file
|
|
224
|
+
// itself so phase inference needs no extra state file (and survives a rename).
|
|
225
|
+
function lastSpawnRole(dir, file) {
|
|
226
|
+
let text;
|
|
227
|
+
try {
|
|
228
|
+
text = fs.readFileSync(path.join(dir, file), "utf8");
|
|
229
|
+
} catch (_) {
|
|
230
|
+
return null; // new/unreadable trace → the next SPAWN opens the first edge
|
|
231
|
+
}
|
|
232
|
+
let last = null;
|
|
233
|
+
for (const m of text.matchAll(/\] hook\s+SPAWN (\S+)/g)) {
|
|
234
|
+
const fam = roleFamily(m[1]);
|
|
235
|
+
if (fam) last = fam;
|
|
236
|
+
}
|
|
237
|
+
return last;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Read the active run pointer, or null. Never throws.
|
|
241
|
+
function readPointer(dir) {
|
|
242
|
+
try {
|
|
243
|
+
const cur = fs.readFileSync(path.join(dir, ".current"), "utf8").trim();
|
|
244
|
+
return cur || null;
|
|
245
|
+
} catch (_) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Age of the POINTER itself (not the file it names), or null when absent.
|
|
251
|
+
// This is what tells a FRESH lane-registered pointer ("run start wrote
|
|
252
|
+
// `.current` seconds ago; the trace file is about to exist") apart from a
|
|
253
|
+
// DANGLING one left behind by a finished run — `traceStats` returns null for
|
|
254
|
+
// both, which is exactly how a run used to get split across two files.
|
|
255
|
+
function pointerAgeMs(dir) {
|
|
256
|
+
try {
|
|
257
|
+
return Date.now() - fs.statSync(path.join(dir, ".current")).mtimeMs;
|
|
258
|
+
} catch (_) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Sidecar of pending SPAWN records, next to the trace file. Best-effort — every
|
|
264
|
+
// accessor swallows errors so a missing/corrupt sidecar never affects the run.
|
|
265
|
+
function sidecarPath(dir, file) {
|
|
266
|
+
return path.join(dir, file + ".pending.json");
|
|
267
|
+
}
|
|
268
|
+
function readPending(dir, file) {
|
|
269
|
+
try {
|
|
270
|
+
const arr = JSON.parse(fs.readFileSync(sidecarPath(dir, file), "utf8"));
|
|
271
|
+
return Array.isArray(arr) ? arr : [];
|
|
272
|
+
} catch (_) {
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function writePending(dir, file, arr) {
|
|
277
|
+
try {
|
|
278
|
+
fs.writeFileSync(sidecarPath(dir, file), JSON.stringify(arr));
|
|
279
|
+
} catch (_) {}
|
|
280
|
+
}
|
|
281
|
+
function dropPending(dir, file) {
|
|
282
|
+
try {
|
|
283
|
+
fs.unlinkSync(sidecarPath(dir, file));
|
|
284
|
+
} catch (_) {}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// A trace file idle longer than this is a FINISHED run — never append to it.
|
|
288
|
+
const STALE_MS = 6 * 60 * 60 * 1000;
|
|
289
|
+
|
|
290
|
+
// Stats for the pointed-at trace file: idle age + hook SPAWN/RETURN balance.
|
|
291
|
+
// Returns null when the pointer is dangling (file missing/unreadable).
|
|
292
|
+
function traceStats(dir, file) {
|
|
293
|
+
try {
|
|
294
|
+
const full = path.join(dir, file);
|
|
295
|
+
const st = fs.statSync(full);
|
|
296
|
+
const text = fs.readFileSync(full, "utf8");
|
|
297
|
+
// Count only the hook's own skeleton lines (actor column = "hook") — the
|
|
298
|
+
// orchestrator's rich verbs (DISPATCH/VERIFY/…) never collide with these.
|
|
299
|
+
const spawns = (text.match(/\] hook\s+SPAWN /g) || []).length;
|
|
300
|
+
// `RETURN ~agent :: unattributed` claims no pending record (the ≥2-in-flight
|
|
301
|
+
// restraint above), so it must not count toward the balance either — if it
|
|
302
|
+
// did, it would starve the very RETURN it deliberately declined to steal.
|
|
303
|
+
const all = (text.match(/\] hook\s+RETURN/g) || []).length;
|
|
304
|
+
const loose = (text.match(/\] hook\s+RETURN ~agent :: unattributed/g) || []).length;
|
|
305
|
+
return { idleMs: Date.now() - st.mtimeMs, spawns, returns: all - loose, loose };
|
|
306
|
+
} catch (_) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let raw = "";
|
|
312
|
+
process.stdin.on("data", (c) => (raw += c));
|
|
313
|
+
process.stdin.on("end", () => {
|
|
314
|
+
try {
|
|
315
|
+
// Logging is PERMANENT (always on) — no config gate.
|
|
316
|
+
const dir = logDir();
|
|
317
|
+
|
|
318
|
+
let data = {};
|
|
319
|
+
try {
|
|
320
|
+
data = JSON.parse(raw || "{}");
|
|
321
|
+
} catch (_) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const event = data.hook_event_name || "";
|
|
326
|
+
const tool = data.tool_name || "";
|
|
327
|
+
|
|
328
|
+
if (event === "PreToolUse" && (tool === "Task" || tool === "Agent")) {
|
|
329
|
+
// Agent dispatch — record the REQUESTED agent name (the claim). The
|
|
330
|
+
// orchestrator's DISPATCH/VERIFY lines carry the authoritative detail.
|
|
331
|
+
const input = data.tool_input || {};
|
|
332
|
+
const agent = input.subagent_type || input.subagentType || "agent";
|
|
333
|
+
// Only ORC-agent dispatches start/extend a trace — non-ORC Tasks (Explore,
|
|
334
|
+
// general-purpose, superpowers, …) are never logged.
|
|
335
|
+
if (!/^orc/i.test(String(agent))) return;
|
|
336
|
+
// …and the trace miner is exempt from its own instrument.
|
|
337
|
+
if (IGNORED_AGENTS.test(String(agent))) return;
|
|
338
|
+
let current = readPointer(dir);
|
|
339
|
+
// Rotate away from a finished run: a dangling pointer or a trace file
|
|
340
|
+
// idle past STALE_MS means the old run ended — start a fresh `.txt`
|
|
341
|
+
// instead of merging a new day's run into it.
|
|
342
|
+
if (current) {
|
|
343
|
+
const stats = traceStats(dir, current);
|
|
344
|
+
if (!stats) {
|
|
345
|
+
// Pointer names a file that does not exist. TWO different states —
|
|
346
|
+
// and rotating on both is what produced the split trace pairs:
|
|
347
|
+
// fresh pointer → the lane just registered its rich filename and
|
|
348
|
+
// has not written into it yet. HONOR it: append
|
|
349
|
+
// under that name, leave `.current` alone.
|
|
350
|
+
// stale/dangling → the run really is over. Rotate.
|
|
351
|
+
const age = pointerAgeMs(dir);
|
|
352
|
+
if (age === null || age > STALE_MS) {
|
|
353
|
+
dropPending(dir, current);
|
|
354
|
+
current = null;
|
|
355
|
+
}
|
|
356
|
+
} else if (stats.idleMs > STALE_MS) {
|
|
357
|
+
// The old run is over — clean up its pending sidecar so a new run
|
|
358
|
+
// never inherits stale in-flight records.
|
|
359
|
+
dropPending(dir, current);
|
|
360
|
+
current = null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (!current) {
|
|
364
|
+
// Bootstrap: no live run pointer (never written, dangling, or stale).
|
|
365
|
+
// Create the folder + pointer so a trace exists regardless.
|
|
366
|
+
current = bootstrapSlug(new Date());
|
|
367
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
368
|
+
fs.writeFileSync(path.join(dir, ".current"), current + "\n");
|
|
369
|
+
}
|
|
370
|
+
const desc = (input.description || "").toString().slice(0, 80);
|
|
371
|
+
// Deterministic phase inference: a change of role family (or the first
|
|
372
|
+
// classified dispatch of the run) opens a phase edge. Written BEFORE the
|
|
373
|
+
// SPAWN so the edge reads as the header of the phase it opens.
|
|
374
|
+
const fam = roleFamily(agent);
|
|
375
|
+
if (fam && fam !== lastSpawnRole(dir, current))
|
|
376
|
+
appendLine(dir, current, "hook", `PHASE-EDGE ${fam}`, `first=${agent}`);
|
|
377
|
+
appendLine(dir, current, "hook", `SPAWN ${agent}`, desc);
|
|
378
|
+
// Push a pending record so the matching RETURN can be attributed (agent +
|
|
379
|
+
// desc + start time). Best-effort — a write failure degrades to a bare
|
|
380
|
+
// RETURN, never affects the run.
|
|
381
|
+
const pend = readPending(dir, current);
|
|
382
|
+
pend.push({ agent: String(agent), desc, ts: Date.now() });
|
|
383
|
+
writePending(dir, current, pend);
|
|
384
|
+
} else if (event === "SubagentStop" || event === "Stop") {
|
|
385
|
+
// A RETURN only makes sense inside an active run — don't manufacture a
|
|
386
|
+
// trace from a stray subagent stop that had no matching ORC dispatch.
|
|
387
|
+
const current = readPointer(dir);
|
|
388
|
+
if (!current) return;
|
|
389
|
+
const stats = traceStats(dir, current);
|
|
390
|
+
// Drop the RETURN when the run is over (stale/dangling) or when every
|
|
391
|
+
// observed SPAWN already has its RETURN — unrelated sessions' subagents
|
|
392
|
+
// must never bleed into an ORC trace.
|
|
393
|
+
if (!stats || stats.idleMs > STALE_MS) return;
|
|
394
|
+
if (stats.returns >= stats.spawns) return;
|
|
395
|
+
|
|
396
|
+
// Resolve WHICH agent finished. Claude Code's SubagentStop carries
|
|
397
|
+
// agent_type today; older builds omit it.
|
|
398
|
+
const agentType = (data.agent_type || data.agentType || "").toString();
|
|
399
|
+
// Non-ORC agent_type → drop, mirroring the SPAWN gate.
|
|
400
|
+
if (agentType && !/^orc/i.test(agentType)) return;
|
|
401
|
+
// The trace miner never returns into a trace either (hard rule 4).
|
|
402
|
+
if (agentType && IGNORED_AGENTS.test(agentType)) return;
|
|
403
|
+
|
|
404
|
+
const pend = readPending(dir, current);
|
|
405
|
+
let rec = null;
|
|
406
|
+
let name;
|
|
407
|
+
let approx = false;
|
|
408
|
+
let unattributed = false;
|
|
409
|
+
if (agentType) {
|
|
410
|
+
// Match the OLDEST pending record for this agent type (FIFO within name).
|
|
411
|
+
const idx = pend.findIndex((p) => p && p.agent === agentType);
|
|
412
|
+
if (idx >= 0) rec = pend.splice(idx, 1)[0];
|
|
413
|
+
// DUPLICATE STOP: no record for this agent, but others are still in
|
|
414
|
+
// flight → this agent's slot was already consumed (the classic
|
|
415
|
+
// approximate-pop-then-real-stop double fire). Drop it rather than
|
|
416
|
+
// write a second, desc-less RETURN for the same agent. An EMPTY sidecar
|
|
417
|
+
// is a lost/corrupt sidecar, not a duplicate — that case still degrades
|
|
418
|
+
// to a bare RETURN (and a genuine repeat is caught by returns>=spawns).
|
|
419
|
+
else if (pend.length) return;
|
|
420
|
+
name = agentType;
|
|
421
|
+
} else if (pend.length === 1) {
|
|
422
|
+
// Older Claude Code: no agent_type, and exactly ONE agent in flight —
|
|
423
|
+
// the FIFO pop is unambiguous. Mark it approximate (`~`) all the same.
|
|
424
|
+
rec = pend.shift();
|
|
425
|
+
name = rec.agent;
|
|
426
|
+
approx = true;
|
|
427
|
+
} else if (pend.length > 1) {
|
|
428
|
+
// ≥2 in flight and no agent_type: a blind FIFO pop would hand this stop
|
|
429
|
+
// another agent's record and STARVE that agent's real RETURN. Record
|
|
430
|
+
// that something finished, but consume NOTHING.
|
|
431
|
+
//
|
|
432
|
+
// BOUND them (v0.34.2). Because an `unattributed` line claims no record
|
|
433
|
+
// it is also excluded from `returns`, so the `returns >= spawns` guard
|
|
434
|
+
// can never stop it — on a wave of N the hook wrote a line for EVERY
|
|
435
|
+
// stop, forever. At most one unattributed line per in-flight record:
|
|
436
|
+
// a stray stop past that writes nothing.
|
|
437
|
+
if ((stats.loose || 0) >= pend.length) return;
|
|
438
|
+
name = "agent";
|
|
439
|
+
approx = true;
|
|
440
|
+
unattributed = true;
|
|
441
|
+
} else {
|
|
442
|
+
// No pending records at all (missing/corrupt sidecar) — bare RETURN.
|
|
443
|
+
name = "agent";
|
|
444
|
+
approx = true;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const parts = [];
|
|
448
|
+
if (unattributed) parts.push("unattributed");
|
|
449
|
+
if (rec && rec.desc) parts.push(String(rec.desc));
|
|
450
|
+
if (rec && typeof rec.ts === "number") {
|
|
451
|
+
const s = Math.max(0, Math.round((Date.now() - rec.ts) / 1000));
|
|
452
|
+
parts.push(`dur=${Math.floor(s / 60)}m${s % 60}s`);
|
|
453
|
+
}
|
|
454
|
+
// Opportunistic model capture from the finishing agent's last message —
|
|
455
|
+
// makes the downgrade check deterministic even without the VERIFY line.
|
|
456
|
+
const msg = (data.last_assistant_message || "").toString();
|
|
457
|
+
const mm =
|
|
458
|
+
msg.match(/actual_model["'\s:=]*["']?(claude-[a-z0-9-]+)/i) ||
|
|
459
|
+
msg.match(/\b(claude-[a-z0-9-]+)\b/);
|
|
460
|
+
if (mm) parts.push(`model=${mm[1]}`);
|
|
461
|
+
|
|
462
|
+
const label = approx ? `RETURN ~${name}` : `RETURN ${name}`;
|
|
463
|
+
appendLine(dir, current, "hook", label, parts.join(" "));
|
|
464
|
+
writePending(dir, current, pend);
|
|
465
|
+
}
|
|
466
|
+
} catch (_) {
|
|
467
|
+
// Tracing must never affect a run.
|
|
468
|
+
} finally {
|
|
469
|
+
process.exit(0);
|
|
470
|
+
}
|
|
471
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ORC update-check helper — shared by the ORC hooks (orc-effort-guard.js,
|
|
4
|
+
* orc-statusline.js). Surfaces a "newer version available" nudge INSIDE Claude
|
|
5
|
+
* Code (when you invoke /orc, and on the statusline) without any model tokens —
|
|
6
|
+
* hooks are deterministic scripts Claude Code runs, not model turns.
|
|
7
|
+
*
|
|
8
|
+
* How it knows versions:
|
|
9
|
+
* - installed version: `.claude/hooks/orc-version.json` (stamped by `orc init`/
|
|
10
|
+
* `update`/`upgrade` at install time).
|
|
11
|
+
* - latest version: the source's main package.json, fetched over HTTPS and
|
|
12
|
+
* cached 24h in ~/.orc-update-check.json (the SAME cache the CLI uses).
|
|
13
|
+
*
|
|
14
|
+
* Fail-silent everywhere: no network, bad JSON, or missing files → no nudge,
|
|
15
|
+
* never throws. Opt out with ORC_NO_UPDATE_CHECK=1 (also off under CI).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require("fs");
|
|
19
|
+
const os = require("os");
|
|
20
|
+
const path = require("path");
|
|
21
|
+
|
|
22
|
+
const UPDATE_URL =
|
|
23
|
+
process.env.ORC_VERSION_URL ||
|
|
24
|
+
"https://raw.githubusercontent.com/azure-id/orc/main/package.json";
|
|
25
|
+
const CACHE_FILE = path.join(os.homedir(), ".orc-update-check.json");
|
|
26
|
+
const TTL_MS = 24 * 60 * 60 * 1000;
|
|
27
|
+
|
|
28
|
+
const disabled = () =>
|
|
29
|
+
process.env.ORC_NO_UPDATE_CHECK === "1" || process.env.CI === "true";
|
|
30
|
+
|
|
31
|
+
function installedVersion(hooksDir) {
|
|
32
|
+
try {
|
|
33
|
+
return (
|
|
34
|
+
JSON.parse(fs.readFileSync(path.join(hooksDir, "orc-version.json"), "utf8"))
|
|
35
|
+
.version || null
|
|
36
|
+
);
|
|
37
|
+
} catch (_) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseSemver(v) {
|
|
43
|
+
const m = String(v || "").trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
44
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
45
|
+
}
|
|
46
|
+
function semverGt(a, b) {
|
|
47
|
+
const x = parseSemver(a);
|
|
48
|
+
const y = parseSemver(b);
|
|
49
|
+
if (!x || !y) return false;
|
|
50
|
+
for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] > y[i];
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readCache() {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(fs.readFileSync(CACHE_FILE, "utf8"));
|
|
57
|
+
} catch (_) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function writeCache(o) {
|
|
62
|
+
try {
|
|
63
|
+
fs.writeFileSync(CACHE_FILE, JSON.stringify(o));
|
|
64
|
+
} catch (_) {}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const nudgeText = (latest, cur) =>
|
|
68
|
+
`⬆ orc ${latest} available (you have ${cur || "?"}) — run \`orc upgrade\``;
|
|
69
|
+
|
|
70
|
+
// Instant, cache-only (no network). For the statusline hot path. → string|null.
|
|
71
|
+
function readCachedNudge(cur) {
|
|
72
|
+
if (disabled()) return null;
|
|
73
|
+
const c = readCache();
|
|
74
|
+
return c && c.latest && semverGt(c.latest, cur) ? nudgeText(c.latest, cur) : null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Cache-first, refreshes over HTTPS only when the cache is >24h old. Bounded
|
|
78
|
+
// (1.2s) and fail-silent. For the PreToolUse guard (fires on /orc invoke, so a
|
|
79
|
+
// once-a-day sub-second refresh is fine). Calls cb(string|null).
|
|
80
|
+
function refreshAndNudge(cur, cb) {
|
|
81
|
+
if (disabled()) return cb(null);
|
|
82
|
+
const c = readCache();
|
|
83
|
+
if (c && Date.now() - (c.checkedAt || 0) < TTL_MS) {
|
|
84
|
+
return cb(c.latest && semverGt(c.latest, cur) ? nudgeText(c.latest, cur) : null);
|
|
85
|
+
}
|
|
86
|
+
let done = false;
|
|
87
|
+
const finish = (latest) => {
|
|
88
|
+
if (done) return;
|
|
89
|
+
done = true;
|
|
90
|
+
const l = latest || (c ? c.latest : null);
|
|
91
|
+
writeCache({ checkedAt: Date.now(), latest: l });
|
|
92
|
+
cb(l && semverGt(l, cur) ? nudgeText(l, cur) : null);
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
const https = require("https");
|
|
96
|
+
const req = https.get(
|
|
97
|
+
UPDATE_URL,
|
|
98
|
+
{ headers: { "User-Agent": "orc-hook" } },
|
|
99
|
+
(res) => {
|
|
100
|
+
if (res.statusCode !== 200) {
|
|
101
|
+
res.resume();
|
|
102
|
+
return finish(null);
|
|
103
|
+
}
|
|
104
|
+
let s = "";
|
|
105
|
+
res.on("data", (ch) => (s += ch));
|
|
106
|
+
res.on("end", () => {
|
|
107
|
+
try {
|
|
108
|
+
finish(JSON.parse(s).version);
|
|
109
|
+
} catch (_) {
|
|
110
|
+
finish(null);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
req.on("error", () => finish(null));
|
|
116
|
+
req.setTimeout(1200, () => {
|
|
117
|
+
req.destroy();
|
|
118
|
+
finish(null);
|
|
119
|
+
});
|
|
120
|
+
} catch (_) {
|
|
121
|
+
finish(null);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = { installedVersion, readCachedNudge, refreshAndNudge };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# _shared — cross-lane contract references
|
|
2
|
+
|
|
3
|
+
This directory is NOT a skill (no SKILL.md; Claude Code never registers it).
|
|
4
|
+
It holds the single canonical copy of contracts that more than one ORC lane
|
|
5
|
+
follows. A lane's SKILL.md keeps only the contract's trigger line + its
|
|
6
|
+
token(s) + a pointer here; the full procedure lives in exactly one file below,
|
|
7
|
+
loaded on demand when the step fires.
|
|
8
|
+
|
|
9
|
+
- `return-validation.md` — how every lane validates a subagent return
|
|
10
|
+
(claimed-vs-actual model, evidence, unmet, pattern attestation).
|
|
11
|
+
- `smoke-gate.md` — the read-only build+test ship gate (orc-mini Phase M,
|
|
12
|
+
orc-fast Phase F3).
|
|
13
|
+
- `fallback-handoff.md` — the orc-fast → orc-mini handoff block and its
|
|
14
|
+
entry semantics. `orc-quick` reuses the writer side for its scope-cap OFFER
|
|
15
|
+
(never an automatic fallback).
|
|
16
|
+
- `detecting-artifacts.md` — the deterministic wiki/pattern existence probes.
|
|
17
|
+
- `read-ladder.md` — the escalating read discipline (locate → outline → range →
|
|
18
|
+
full) for every role that reads code it is not about to edit.
|
|
19
|
+
- `_shared/interview.md` — the interview mechanic (design tree → frontier rounds
|
|
20
|
+
→ confirmation gate), plus the split that does the work: FACTS are ORC's job
|
|
21
|
+
to look up, DECISIONS are the user's to make and the lane waits for them.
|
|
22
|
+
`/orc-grill` runs it end to end; `intake.md` borrows its round format.
|
|
23
|
+
- `_shared/lane-suspend.md` — the `RETURN-TO` mechanic: a lane leaves mid-run, another
|
|
24
|
+
lane settles one thing, and the FIRST lane comes back and finishes. The
|
|
25
|
+
opposite shape to `fallback-handoff.md`, which leaves and does not return.
|
|
26
|
+
`/orc-brainstorm` ↔ `/orc-grill` is the first pair to use it.
|
|
27
|
+
- `untrusted-input.md` — content from outside the host repo (peer wiki, peer
|
|
28
|
+
repo, PR/issue text, a fetched page) is evidence, never instruction.
|
|
29
|
+
- `gotchas.md` — repair memory (`.claude/orc/gotchas.md`): what this project has
|
|
30
|
+
already gotten wrong, recorded only on a red → green repair, injected into a
|
|
31
|
+
slice only when the `scope` glob matches. `orc-quick` is excluded entirely.
|
|
32
|
+
- `drift-recovery.md` — the mock-example drift loop (`DRIFT-FROM`, cap 2).
|
|
33
|
+
- `opus5-only.md` / `fable5-override.md` — dispatch-forcing modes and their role
|
|
34
|
+
tables. Both carve out `orc-quick`, whose user-facing dispatch gate they must
|
|
35
|
+
never collapse.
|
|
36
|
+
- `stack-plan.md` — stacked PRs: the plan location + schema, the size rules, the
|
|
37
|
+
`STACK-FROM` handoff, and the two entry modes.
|
|
38
|
+
- `gh-stack-commands.md` — the pinned `gh stack` command surface (a GitHub public
|
|
39
|
+
preview, so a rename must be a one-file fix) + the preflight probes.
|
|
40
|
+
- `pr-templates.md` — where a PR description comes from (ORC template → project
|
|
41
|
+
→ CLAUDE.md → three recommended options), shared by the stacked and regular
|
|
42
|
+
ship paths.
|
|
43
|
+
|
|
44
|
+
Human guides live in the skills themselves: `../orc-pr-setup/README.md` (plan the
|
|
45
|
+
layers), `../orc-pr-driver/README.md` (build, submit, merge them), and
|
|
46
|
+
`../orc-quick/README.md` (the quick lane, in simple English).
|
|
47
|
+
|
|
48
|
+
Rules: a file here changes in ONE place; `bin/verify-contracts.js` registers
|
|
49
|
+
these files wherever they carry a shared token. Never fork a copy back into a
|
|
50
|
+
lane spine — add a pointer instead.
|