dsh-compound-engineering 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +160 -2
- package/README.zh.md +161 -0
- package/cordis.patch.yml +6 -0
- package/lib/frontmatter.js +167 -0
- package/lib/index.js +46 -0
- package/lib/provider.js +201 -0
- package/package.json +62 -4
- package/skills/CODING_STANDARDS.md +68 -0
- package/skills/ce-babysit-pr/SKILL.md +59 -0
- package/skills/ce-babysit-pr/references/branch-currency.md +22 -0
- package/skills/ce-babysit-pr/references/envelope.md +44 -0
- package/skills/ce-babysit-pr/references/pipeline.md +15 -0
- package/skills/ce-babysit-pr/references/report.md +20 -0
- package/skills/ce-babysit-pr/references/settle.md +37 -0
- package/skills/ce-babysit-pr/references/setup.md +33 -0
- package/skills/ce-babysit-pr/references/stack-commands.md +39 -0
- package/skills/ce-babysit-pr/references/stack.md +43 -0
- package/skills/ce-babysit-pr/references/tick.md +102 -0
- package/skills/ce-babysit-pr/references/watch-loop.md +222 -0
- package/skills/ce-babysit-pr/scripts/pr-snapshot +3656 -0
- package/skills/ce-bakeoff/SKILL.md +48 -0
- package/skills/ce-bakeoff/references/candidates.md +37 -0
- package/skills/ce-bakeoff/references/judging.md +19 -0
- package/skills/ce-bakeoff/references/output.md +11 -0
- package/skills/ce-bakeoff/references/verification.md +15 -0
- package/skills/ce-brainstorm/SKILL.md +69 -0
- package/skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
- package/skills/ce-brainstorm/references/approaches.md +57 -0
- package/skills/ce-brainstorm/references/bakeoff.md +9 -0
- package/skills/ce-brainstorm/references/blindspot-pass.md +70 -0
- package/skills/ce-brainstorm/references/brainstorm-sections.md +458 -0
- package/skills/ce-brainstorm/references/dialogue.md +89 -0
- package/skills/ce-brainstorm/references/handoff.md +187 -0
- package/skills/ce-brainstorm/references/html-rendering.md +638 -0
- package/skills/ce-brainstorm/references/interaction-rules.md +33 -0
- package/skills/ce-brainstorm/references/markdown-rendering.md +242 -0
- package/skills/ce-brainstorm/references/model-tiers.md +13 -0
- package/skills/ce-brainstorm/references/output-mode.md +26 -0
- package/skills/ce-brainstorm/references/phase-0.md +104 -0
- package/skills/ce-brainstorm/references/plan-write.md +32 -0
- package/skills/ce-brainstorm/references/product-pressure-test.md +42 -0
- package/skills/ce-brainstorm/references/reasoning-elevation.md +124 -0
- package/skills/ce-brainstorm/references/settled-decisions.md +45 -0
- package/skills/ce-brainstorm/references/synthesis-summary.md +149 -0
- package/skills/ce-brainstorm/references/universal-brainstorming.md +72 -0
- package/skills/ce-brainstorm/references/verdict-routing.md +26 -0
- package/skills/ce-brainstorm/references/visual-probes.md +164 -0
- package/skills/ce-brainstorm/scripts/elevation-dispatch.sh +288 -0
- package/skills/ce-brainstorm/scripts/light-webserver.js +1275 -0
- package/skills/ce-brainstorm/scripts/packs-resolve.py +737 -0
- package/skills/ce-brainstorm/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-code-review/SKILL.md +40 -0
- package/skills/ce-code-review/references/action-class-rubric.md +67 -0
- package/skills/ce-code-review/references/cross-model-recovery.md +38 -0
- package/skills/ce-code-review/references/cross-model-review.md +191 -0
- package/skills/ce-code-review/references/depth-paths.md +32 -0
- package/skills/ce-code-review/references/diff-scope.md +59 -0
- package/skills/ce-code-review/references/dispatch-reviewers.md +135 -0
- package/skills/ce-code-review/references/findings-schema.json +125 -0
- package/skills/ce-code-review/references/finish-input.md +118 -0
- package/skills/ce-code-review/references/finish-review.md +202 -0
- package/skills/ce-code-review/references/intent-and-plan.md +73 -0
- package/skills/ce-code-review/references/modes-and-output.md +156 -0
- package/skills/ce-code-review/references/persona-catalog.md +66 -0
- package/skills/ce-code-review/references/personas/adversarial-reviewer.md +111 -0
- package/skills/ce-code-review/references/personas/agent-native-reviewer.md +173 -0
- package/skills/ce-code-review/references/personas/api-contract-reviewer.md +44 -0
- package/skills/ce-code-review/references/personas/correctness-reviewer.md +48 -0
- package/skills/ce-code-review/references/personas/data-migration-reviewer.md +111 -0
- package/skills/ce-code-review/references/personas/deployment-verification-agent.md +157 -0
- package/skills/ce-code-review/references/personas/julik-frontend-races-reviewer.md +45 -0
- package/skills/ce-code-review/references/personas/learnings-researcher.md +260 -0
- package/skills/ce-code-review/references/personas/maintainability-reviewer.md +85 -0
- package/skills/ce-code-review/references/personas/performance-reviewer.md +45 -0
- package/skills/ce-code-review/references/personas/previous-comments-reviewer.md +59 -0
- package/skills/ce-code-review/references/personas/project-standards-reviewer.md +77 -0
- package/skills/ce-code-review/references/personas/reliability-reviewer.md +49 -0
- package/skills/ce-code-review/references/personas/security-reviewer.md +50 -0
- package/skills/ce-code-review/references/personas/swift-ios-reviewer.md +99 -0
- package/skills/ce-code-review/references/personas/testing-reviewer.md +51 -0
- package/skills/ce-code-review/references/review-output-template.md +172 -0
- package/skills/ce-code-review/references/scope.md +176 -0
- package/skills/ce-code-review/references/select-and-route.md +93 -0
- package/skills/ce-code-review/references/subagent-template.md +206 -0
- package/skills/ce-code-review/references/validator-batch-template.md +67 -0
- package/skills/ce-code-review/scripts/cross-model-adversarial-review.sh +1275 -0
- package/skills/ce-code-review/scripts/findings-mechanics.py +274 -0
- package/skills/ce-code-review/scripts/packs-resolve.py +737 -0
- package/skills/ce-code-review/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-code-review/scripts/review-scope.py +419 -0
- package/skills/ce-code-review/scripts/run-log.py +280 -0
- package/skills/ce-commit/SKILL.md +60 -0
- package/skills/ce-commit-push-pr/SKILL.md +69 -0
- package/skills/ce-commit-push-pr/references/apply-and-handoff.md +79 -0
- package/skills/ce-commit-push-pr/references/branch-creation.md +47 -0
- package/skills/ce-commit-push-pr/references/commit-and-push.md +26 -0
- package/skills/ce-commit-push-pr/references/compose.md +29 -0
- package/skills/ce-commit-push-pr/references/context.md +42 -0
- package/skills/ce-commit-push-pr/references/gh-stack-cli.md +83 -0
- package/skills/ce-commit-push-pr/references/pr-description-writing.md +208 -0
- package/skills/ce-commit-push-pr/references/stack-submit.md +81 -0
- package/skills/ce-compound/SKILL.md +79 -0
- package/skills/ce-compound/assets/resolution-template.md +96 -0
- package/skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
- package/skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
- package/skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
- package/skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
- package/skills/ce-compound/references/agents/performance-oracle.md +108 -0
- package/skills/ce-compound/references/agents/security-sentinel.md +91 -0
- package/skills/ce-compound/references/agents/session-historian.md +82 -0
- package/skills/ce-compound/references/assembly.md +127 -0
- package/skills/ce-compound/references/concepts-vocabulary.md +98 -0
- package/skills/ce-compound/references/enhancement.md +42 -0
- package/skills/ce-compound/references/grounding-validation.md +89 -0
- package/skills/ce-compound/references/lightweight.md +56 -0
- package/skills/ce-compound/references/modes.md +13 -0
- package/skills/ce-compound/references/refresh-and-discoverability.md +96 -0
- package/skills/ce-compound/references/report.md +115 -0
- package/skills/ce-compound/references/research.md +144 -0
- package/skills/ce-compound/references/schema.yaml +236 -0
- package/skills/ce-compound/references/session-history.md +73 -0
- package/skills/ce-compound/references/yaml-schema.md +130 -0
- package/skills/ce-compound/scripts/packs-resolve.py +737 -0
- package/skills/ce-compound/scripts/session-history/__pycache__/dsh_session.cpython-314.pyc +0 -0
- package/skills/ce-compound/scripts/session-history/discover-sessions.sh +290 -0
- package/skills/ce-compound/scripts/session-history/discover_dsh.py +123 -0
- package/skills/ce-compound/scripts/session-history/dsh_session.py +225 -0
- package/skills/ce-compound/scripts/session-history/extract-errors.py +178 -0
- package/skills/ce-compound/scripts/session-history/extract-metadata.py +301 -0
- package/skills/ce-compound/scripts/session-history/extract-skeleton.py +346 -0
- package/skills/ce-compound/scripts/validate-doc-claims.py +497 -0
- package/skills/ce-compound/scripts/validate-frontmatter.py +137 -0
- package/skills/ce-compound-refresh/SKILL.md +88 -0
- package/skills/ce-compound-refresh/assets/resolution-template.md +96 -0
- package/skills/ce-compound-refresh/references/classify.md +42 -0
- package/skills/ce-compound-refresh/references/commit.md +7 -0
- package/skills/ce-compound-refresh/references/concepts-vocabulary.md +116 -0
- package/skills/ce-compound-refresh/references/discoverability.md +15 -0
- package/skills/ce-compound-refresh/references/investigate.md +23 -0
- package/skills/ce-compound-refresh/references/modes.md +27 -0
- package/skills/ce-compound-refresh/references/per-action-flows.md +142 -0
- package/skills/ce-compound-refresh/references/report.md +23 -0
- package/skills/ce-compound-refresh/references/schema.yaml +236 -0
- package/skills/ce-compound-refresh/references/scope.md +18 -0
- package/skills/ce-compound-refresh/references/worth-audit.md +35 -0
- package/skills/ce-compound-refresh/references/yaml-schema.md +130 -0
- package/skills/ce-compound-refresh/scripts/validate-doc-claims.py +497 -0
- package/skills/ce-compound-refresh/scripts/validate-frontmatter.py +137 -0
- package/skills/ce-debug/SKILL.md +122 -0
- package/skills/ce-debug/references/anti-patterns.md +91 -0
- package/skills/ce-debug/references/defense-in-depth.md +39 -0
- package/skills/ce-debug/references/fix.md +21 -0
- package/skills/ce-debug/references/investigate.md +114 -0
- package/skills/ce-debug/references/investigation-techniques.md +384 -0
- package/skills/ce-debug/references/pipeline-mode.md +78 -0
- package/skills/ce-debug/references/post-fix-handoff.md +60 -0
- package/skills/ce-debug/references/return-to-caller.md +57 -0
- package/skills/ce-doc-review/SKILL.md +75 -0
- package/skills/ce-doc-review/references/bulk-preview.md +146 -0
- package/skills/ce-doc-review/references/cross-model-review.md +207 -0
- package/skills/ce-doc-review/references/decision-primer.md +47 -0
- package/skills/ce-doc-review/references/dispatch.md +56 -0
- package/skills/ce-doc-review/references/document-intake.md +44 -0
- package/skills/ce-doc-review/references/findings-schema.json +85 -0
- package/skills/ce-doc-review/references/modes.md +20 -0
- package/skills/ce-doc-review/references/open-questions-defer.md +158 -0
- package/skills/ce-doc-review/references/persona-selection.md +41 -0
- package/skills/ce-doc-review/references/personas/adversarial-document-reviewer.md +109 -0
- package/skills/ce-doc-review/references/personas/coherence-reviewer.md +69 -0
- package/skills/ce-doc-review/references/personas/design-lens-reviewer.md +48 -0
- package/skills/ce-doc-review/references/personas/feasibility-reviewer.md +50 -0
- package/skills/ce-doc-review/references/personas/product-lens-reviewer.md +85 -0
- package/skills/ce-doc-review/references/personas/scope-guardian-reviewer.md +83 -0
- package/skills/ce-doc-review/references/personas/security-lens-reviewer.md +41 -0
- package/skills/ce-doc-review/references/personas/whole-doc-reviewer.md +25 -0
- package/skills/ce-doc-review/references/rendering-floor.md +175 -0
- package/skills/ce-doc-review/references/review-output-template.md +123 -0
- package/skills/ce-doc-review/references/subagent-template.md +188 -0
- package/skills/ce-doc-review/references/synthesis-and-presentation.md +350 -0
- package/skills/ce-doc-review/references/walkthrough.md +347 -0
- package/skills/ce-doc-review/scripts/cross-model-doc-review.sh +1270 -0
- package/skills/ce-doc-review/scripts/packs-resolve.py +737 -0
- package/skills/ce-doc-review/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-dogfood/SKILL.md +66 -0
- package/skills/ce-dogfood/agents/openai.yaml +2 -0
- package/skills/ce-dogfood/references/dogfood-report-template.md +97 -0
- package/skills/ce-dogfood/references/phases.md +167 -0
- package/skills/ce-dogfood/references/test-matrix-taxonomy.md +62 -0
- package/skills/ce-dogfood/scripts/packs-resolve.py +737 -0
- package/skills/ce-explain/SKILL.md +81 -0
- package/skills/ce-explain/references/agents/behavior-trace-scout.md +19 -0
- package/skills/ce-explain/references/agents/work-recap-scout.md +23 -0
- package/skills/ce-explain/references/check-in.md +18 -0
- package/skills/ce-explain/references/destinations.md +35 -0
- package/skills/ce-explain/references/explainer-html.md +29 -0
- package/skills/ce-explain/references/explainer-markdown.md +24 -0
- package/skills/ce-explain/references/intake.md +50 -0
- package/skills/ce-explain/references/orchestration.md +46 -0
- package/skills/ce-handoff/SKILL.md +54 -0
- package/skills/ce-handoff/references/create.md +88 -0
- package/skills/ce-handoff/references/resume.md +46 -0
- package/skills/ce-ideate/SKILL.md +75 -0
- package/skills/ce-ideate/references/agents/issue-intelligence-analyst.md +166 -0
- package/skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
- package/skills/ce-ideate/references/agents/slack-researcher.md +127 -0
- package/skills/ce-ideate/references/agents/web-researcher.md +121 -0
- package/skills/ce-ideate/references/decomposition.md +39 -0
- package/skills/ce-ideate/references/divergent-ideation.md +112 -0
- package/skills/ce-ideate/references/grounding.md +138 -0
- package/skills/ce-ideate/references/html-rendering.md +638 -0
- package/skills/ce-ideate/references/ideation-sections.md +191 -0
- package/skills/ce-ideate/references/issue-intelligence.md +44 -0
- package/skills/ce-ideate/references/markdown-rendering.md +242 -0
- package/skills/ce-ideate/references/output-mode.md +34 -0
- package/skills/ce-ideate/references/post-ideation-workflow.md +169 -0
- package/skills/ce-ideate/references/scope-gates.md +148 -0
- package/skills/ce-ideate/references/universal-ideation.md +119 -0
- package/skills/ce-ideate/references/user-research-artifacts.md +28 -0
- package/skills/ce-ideate/references/web-research-cache.md +56 -0
- package/skills/ce-noslop/SKILL.md +45 -0
- package/skills/ce-noslop/references/patterns.md +61 -0
- package/skills/ce-noslop/references/terminology.md +3 -0
- package/skills/ce-optimize/SKILL.md +64 -0
- package/skills/ce-optimize/references/agents/learnings-researcher.md +247 -0
- package/skills/ce-optimize/references/agents/repo-research-analyst.md +258 -0
- package/skills/ce-optimize/references/example-expensive-benchmark-spec.yaml +88 -0
- package/skills/ce-optimize/references/example-hard-spec.yaml +64 -0
- package/skills/ce-optimize/references/example-judge-spec.yaml +83 -0
- package/skills/ce-optimize/references/example-text-target-spec.yaml +80 -0
- package/skills/ce-optimize/references/experiment-log-schema.yaml +563 -0
- package/skills/ce-optimize/references/experiment-prompt-template.md +143 -0
- package/skills/ce-optimize/references/judge-prompt-template.md +117 -0
- package/skills/ce-optimize/references/loop.md +286 -0
- package/skills/ce-optimize/references/measurement.md +168 -0
- package/skills/ce-optimize/references/optimize-spec-schema.yaml +570 -0
- package/skills/ce-optimize/references/persistence.md +93 -0
- package/skills/ce-optimize/references/spec.md +107 -0
- package/skills/ce-optimize/references/text-targets.md +51 -0
- package/skills/ce-optimize/references/usage-guide.md +147 -0
- package/skills/ce-optimize/references/wrap-up.md +54 -0
- package/skills/ce-optimize/scripts/decide.mjs +676 -0
- package/skills/ce-optimize/scripts/experiment-worktree.sh +330 -0
- package/skills/ce-optimize/scripts/measure.sh +140 -0
- package/skills/ce-optimize/scripts/parallel-probe.sh +134 -0
- package/skills/ce-plan/SKILL.md +60 -0
- package/skills/ce-plan/references/agents/agent-native-planning-strategist.md +66 -0
- package/skills/ce-plan/references/agents/architecture-strategist.md +46 -0
- package/skills/ce-plan/references/agents/best-practices-researcher.md +118 -0
- package/skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
- package/skills/ce-plan/references/agents/framework-docs-researcher.md +97 -0
- package/skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
- package/skills/ce-plan/references/agents/learnings-researcher.md +268 -0
- package/skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
- package/skills/ce-plan/references/agents/performance-oracle.md +108 -0
- package/skills/ce-plan/references/agents/repo-research-analyst.md +262 -0
- package/skills/ce-plan/references/agents/security-sentinel.md +91 -0
- package/skills/ce-plan/references/agents/slack-researcher.md +131 -0
- package/skills/ce-plan/references/agents/spec-flow-analyzer.md +84 -0
- package/skills/ce-plan/references/agents/web-researcher.md +125 -0
- package/skills/ce-plan/references/approach-altitude.md +55 -0
- package/skills/ce-plan/references/bakeoff.md +9 -0
- package/skills/ce-plan/references/deepening-workflow.md +263 -0
- package/skills/ce-plan/references/final-review.md +134 -0
- package/skills/ce-plan/references/html-rendering.md +638 -0
- package/skills/ce-plan/references/intake.md +158 -0
- package/skills/ce-plan/references/markdown-rendering.md +242 -0
- package/skills/ce-plan/references/output-contracts.md +29 -0
- package/skills/ce-plan/references/output-mode.md +45 -0
- package/skills/ce-plan/references/plan-handoff.md +116 -0
- package/skills/ce-plan/references/plan-sections.md +489 -0
- package/skills/ce-plan/references/reasoning-elevation.md +124 -0
- package/skills/ce-plan/references/research.md +211 -0
- package/skills/ce-plan/references/resume.md +61 -0
- package/skills/ce-plan/references/settled-decisions.md +45 -0
- package/skills/ce-plan/references/structure.md +207 -0
- package/skills/ce-plan/references/synthesis-summary.md +260 -0
- package/skills/ce-plan/references/universal-planning.md +170 -0
- package/skills/ce-plan/scripts/elevation-dispatch.sh +288 -0
- package/skills/ce-plan/scripts/packs-resolve.py +737 -0
- package/skills/ce-plan/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-polish/SKILL.md +22 -0
- package/skills/ce-polish/agents/openai.yaml +2 -0
- package/skills/ce-polish/references/dev-server-astro.md +58 -0
- package/skills/ce-polish/references/dev-server-detection.md +40 -0
- package/skills/ce-polish/references/dev-server-next.md +61 -0
- package/skills/ce-polish/references/dev-server-nuxt.md +58 -0
- package/skills/ce-polish/references/dev-server-procfile.md +59 -0
- package/skills/ce-polish/references/dev-server-rails.md +50 -0
- package/skills/ce-polish/references/dev-server-remix.md +58 -0
- package/skills/ce-polish/references/dev-server-sveltekit.md +58 -0
- package/skills/ce-polish/references/dev-server-vite.md +48 -0
- package/skills/ce-polish/references/install-riffrec.md +35 -0
- package/skills/ce-polish/references/launch-json-schema.md +177 -0
- package/skills/ce-polish/references/live-loop.md +98 -0
- package/skills/ce-polish/references/live-remote.md +35 -0
- package/skills/ce-polish/references/live-start.md +93 -0
- package/skills/ce-polish/references/live-stream-contract.md +253 -0
- package/skills/ce-polish/references/run.md +67 -0
- package/skills/ce-polish/scripts/detect-project-type.sh +277 -0
- package/skills/ce-polish/scripts/detect-riffrec.sh +225 -0
- package/skills/ce-polish/scripts/live-endpoint.js +2841 -0
- package/skills/ce-polish/scripts/read-launch-json.sh +117 -0
- package/skills/ce-polish/scripts/resolve-package-manager.sh +95 -0
- package/skills/ce-polish/scripts/resolve-port.sh +307 -0
- package/skills/ce-pov/SKILL.md +64 -0
- package/skills/ce-pov/references/agents/external-evidence-researcher.md +26 -0
- package/skills/ce-pov/references/agents/pov-peer.md +43 -0
- package/skills/ce-pov/references/agents/precedent-activity-scout.md +21 -0
- package/skills/ce-pov/references/agents/project-grounding-scout.md +32 -0
- package/skills/ce-pov/references/boundaries.md +36 -0
- package/skills/ce-pov/references/cross-model-panel.md +596 -0
- package/skills/ce-pov/references/followup.md +9 -0
- package/skills/ce-pov/references/grounding.md +47 -0
- package/skills/ce-pov/references/intake.md +61 -0
- package/skills/ce-pov/references/invocation.md +47 -0
- package/skills/ce-pov/references/method.md +68 -0
- package/skills/ce-pov/references/pov-schema.json +56 -0
- package/skills/ce-pov/references/report.md +7 -0
- package/skills/ce-pov/scripts/cross-model-pov.sh +1110 -0
- package/skills/ce-pov/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-product-pulse/SKILL.md +81 -0
- package/skills/ce-product-pulse/agents/openai.yaml +2 -0
- package/skills/ce-product-pulse/references/config.md +20 -0
- package/skills/ce-product-pulse/references/interview.md +260 -0
- package/skills/ce-product-pulse/references/report-template.md +89 -0
- package/skills/ce-product-pulse/references/run.md +46 -0
- package/skills/ce-product-pulse/references/setup.md +43 -0
- package/skills/ce-promote/SKILL.md +90 -0
- package/skills/ce-promote/agents/openai.yaml +2 -0
- package/skills/ce-promote/references/spiral-cli.md +149 -0
- package/skills/ce-proof/SKILL.md +65 -0
- package/skills/ce-proof/references/api.md +176 -0
- package/skills/ce-proof/references/workflows.md +124 -0
- package/skills/ce-prototype/SKILL.md +59 -0
- package/skills/ce-prototype/assets/annotate.css +206 -0
- package/skills/ce-prototype/assets/annotate.js +837 -0
- package/skills/ce-prototype/references/annotation-loop.md +32 -0
- package/skills/ce-prototype/references/build.md +39 -0
- package/skills/ce-prototype/references/craft-floor.md +43 -0
- package/skills/ce-prototype/references/preview.md +118 -0
- package/skills/ce-prototype/references/scoping.md +38 -0
- package/skills/ce-prototype/references/write-back.md +37 -0
- package/skills/ce-prototype/scripts/light-webserver.js +1275 -0
- package/skills/ce-resolve-pr-feedback/SKILL.md +60 -0
- package/skills/ce-resolve-pr-feedback/references/agents/pr-comment-resolver.md +59 -0
- package/skills/ce-resolve-pr-feedback/references/evaluation-rubric.md +141 -0
- package/skills/ce-resolve-pr-feedback/references/full-mode.md +336 -0
- package/skills/ce-resolve-pr-feedback/references/pipeline-mode.md +23 -0
- package/skills/ce-resolve-pr-feedback/references/resume.md +60 -0
- package/skills/ce-resolve-pr-feedback/references/return-to-caller.md +111 -0
- package/skills/ce-resolve-pr-feedback/references/targeted-mode.md +48 -0
- package/skills/ce-resolve-pr-feedback/scripts/get-pr-comments +176 -0
- package/skills/ce-resolve-pr-feedback/scripts/get-thread-for-comment +84 -0
- package/skills/ce-resolve-pr-feedback/scripts/pending-feedback.py +287 -0
- package/skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread +57 -0
- package/skills/ce-resolve-pr-feedback/scripts/resolve-pr-thread +23 -0
- package/skills/ce-retune/SKILL.md +42 -0
- package/skills/ce-retune/agents/openai.yaml +2 -0
- package/skills/ce-retune/references/baseline-mining.md +122 -0
- package/skills/ce-retune/references/corpus-audit.md +128 -0
- package/skills/ce-retune/references/cut-passes.md +129 -0
- package/skills/ce-retune/references/halt-taxonomy.md +123 -0
- package/skills/ce-retune/references/noise-floor.md +131 -0
- package/skills/ce-retune/references/workflow-shapes.md +73 -0
- package/skills/ce-riffrec-feedback-analysis/SKILL.md +33 -0
- package/skills/ce-riffrec-feedback-analysis/references/analyzer.md +18 -0
- package/skills/ce-riffrec-feedback-analysis/references/compound-engineering-feedback-format.md +116 -0
- package/skills/ce-riffrec-feedback-analysis/references/extensive-analysis.md +98 -0
- package/skills/ce-riffrec-feedback-analysis/references/install-riffrec.md +27 -0
- package/skills/ce-riffrec-feedback-analysis/references/quick-bug-report.md +38 -0
- package/skills/ce-riffrec-feedback-analysis/scripts/analyze_riffrec_zip.py +1306 -0
- package/skills/ce-setup/SKILL.md +103 -0
- package/skills/ce-setup/agents/openai.yaml +2 -0
- package/skills/ce-setup/assets/compounding-directive.md +11 -0
- package/skills/ce-setup/assets/noslop-directive.md +7 -0
- package/skills/ce-setup/assets/pack-rule-template.md +11 -0
- package/skills/ce-setup/references/acpx-cache-warm.md +14 -0
- package/skills/ce-setup/references/config-template.yaml +210 -0
- package/skills/ce-setup/references/legacy-codex-tool-map.md +15 -0
- package/skills/ce-setup/references/pack-scaffold.md +45 -0
- package/skills/ce-setup/references/repo-fixes.md +121 -0
- package/skills/ce-setup/scripts/check-health +929 -0
- package/skills/ce-setup/scripts/packs-resolve.py +737 -0
- package/skills/ce-simplify-code/SKILL.md +76 -0
- package/skills/ce-simplify-code/references/personas/code-quality-reviewer.md +17 -0
- package/skills/ce-simplify-code/references/personas/code-reuse-reviewer.md +7 -0
- package/skills/ce-simplify-code/references/personas/comment-reviewer.md +24 -0
- package/skills/ce-simplify-code/references/personas/efficiency-reviewer.md +11 -0
- package/skills/ce-simplify-code/references/personas/test-value-reviewer.md +23 -0
- package/skills/ce-simplify-code/references/reviewer-dispatch.md +11 -0
- package/skills/ce-simplify-code/references/standalone-report.md +25 -0
- package/skills/ce-strategy/SKILL.md +61 -0
- package/skills/ce-strategy/references/grounding.md +22 -0
- package/skills/ce-strategy/references/interview.md +179 -0
- package/skills/ce-strategy/references/strategy-template.md +94 -0
- package/skills/ce-strategy/references/update-run.md +33 -0
- package/skills/ce-sweep/SKILL.md +93 -0
- package/skills/ce-sweep/agents/openai.yaml +2 -0
- package/skills/ce-sweep/references/agents/media-analyzer.md +54 -0
- package/skills/ce-sweep/references/interview.md +208 -0
- package/skills/ce-sweep/references/model-tiers.md +13 -0
- package/skills/ce-sweep/references/plan-template.md +62 -0
- package/skills/ce-sweep/references/run.md +126 -0
- package/skills/ce-sweep/references/sources/email.md +57 -0
- package/skills/ce-sweep/references/sources/github-issues.md +59 -0
- package/skills/ce-sweep/references/sources/slack.md +61 -0
- package/skills/ce-sweep/references/state-schema.md +157 -0
- package/skills/ce-sweep/references/subagent-template.md +60 -0
- package/skills/ce-sweep/scripts/analyze_riffrec_zip.py +1306 -0
- package/skills/ce-sweep/scripts/sweep-state.py +793 -0
- package/skills/ce-test-browser/SKILL.md +50 -0
- package/skills/ce-test-browser/references/agent-browser-driver.md +47 -0
- package/skills/ce-test-browser/references/pipeline-orchestration.md +45 -0
- package/skills/ce-test-browser/references/route-and-report.md +129 -0
- package/skills/ce-test-browser/scripts/resolve-port.sh +41 -0
- package/skills/ce-test-xcode/SKILL.md +26 -0
- package/skills/ce-test-xcode/agents/openai.yaml +2 -0
- package/skills/ce-test-xcode/references/setup-and-build.md +32 -0
- package/skills/ce-test-xcode/references/test-and-report.md +64 -0
- package/skills/ce-work/SKILL.md +62 -0
- package/skills/ce-work/references/agents/figma-design-sync.md +27 -0
- package/skills/ce-work/references/agents/implementation-worker.md +17 -0
- package/skills/ce-work/references/cross-model-execution.md +191 -0
- package/skills/ce-work/references/execution-engines.md +64 -0
- package/skills/ce-work/references/execution-strategy.md +73 -0
- package/skills/ce-work/references/implementation-loop.md +107 -0
- package/skills/ce-work/references/implementation-result-schema.json +52 -0
- package/skills/ce-work/references/input-triage.md +50 -0
- package/skills/ce-work/references/non-code-execution.md +23 -0
- package/skills/ce-work/references/return-to-caller.md +33 -0
- package/skills/ce-work/references/review-findings-followup.md +82 -0
- package/skills/ce-work/references/shipping-workflow.md +89 -0
- package/skills/ce-work/references/tracker-defer.md +150 -0
- package/skills/ce-work/references/work-intake.md +51 -0
- package/skills/ce-work/references/workspace-setup.md +27 -0
- package/skills/ce-work/scripts/__pycache__/unit_workspace_jobs.cpython-314.pyc +0 -0
- package/skills/ce-work/scripts/__pycache__/unit_workspace_state.cpython-314.pyc +0 -0
- package/skills/ce-work/scripts/cross-model-work.sh +1385 -0
- package/skills/ce-work/scripts/peer-job-runner.py +2594 -0
- package/skills/ce-work/scripts/unit-workspace.py +215 -0
- package/skills/ce-work/scripts/unit_workspace_ignored.py +93 -0
- package/skills/ce-work/scripts/unit_workspace_integration.py +677 -0
- package/skills/ce-work/scripts/unit_workspace_jobs.py +1216 -0
- package/skills/ce-work/scripts/unit_workspace_lifecycle.py +981 -0
- package/skills/ce-work/scripts/unit_workspace_state.py +1379 -0
- package/skills/ce-work/scripts/unit_workspace_transaction.py +612 -0
- package/skills/ce-worktree/SKILL.md +54 -0
- package/skills/lfg/SKILL.md +59 -0
- package/skills/lfg/references/debug-return.md +25 -0
- package/skills/lfg/references/intake.md +30 -0
- package/skills/lfg/references/next-work-handoff.md +96 -0
- package/skills/lfg/references/plan-brief.md +36 -0
- package/skills/lfg/references/review-followup.md +78 -0
- package/skills/lfg/references/shipping.md +65 -0
- package/skills/lfg/references/stage-routing.md +49 -0
- package/skills/lfg/references/task-visibility.md +11 -0
- package/skills/lfg/references/tracker-defer.md +150 -0
- package/skills/lfg/references/work-return.md +27 -0
- package/skills/wtf/SKILL.md +33 -0
- package/skills/wtf/agents/openai.yaml +2 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
"""Fail-stop canonical integration for one terminalized external unit."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import secrets
|
|
9
|
+
import shutil
|
|
10
|
+
import subprocess
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from types import SimpleNamespace
|
|
13
|
+
|
|
14
|
+
from unit_workspace_state import *
|
|
15
|
+
from unit_workspace_integration import (
|
|
16
|
+
cmd_integration_acquire,
|
|
17
|
+
cmd_integration_release,
|
|
18
|
+
cmd_mark_applied,
|
|
19
|
+
cmd_mark_committed,
|
|
20
|
+
cmd_mark_verified,
|
|
21
|
+
cmd_preflight,
|
|
22
|
+
cmd_restore,
|
|
23
|
+
cmd_wave_advance,
|
|
24
|
+
matches_expected_apply,
|
|
25
|
+
remove_introduced_paths,
|
|
26
|
+
semantic_snapshot,
|
|
27
|
+
validate_lock,
|
|
28
|
+
)
|
|
29
|
+
from unit_workspace_lifecycle import (
|
|
30
|
+
cmd_cleanup,
|
|
31
|
+
pending_plan_wide_verification,
|
|
32
|
+
plan_wide_verification_attempts,
|
|
33
|
+
receipted_plan_wide_verification,
|
|
34
|
+
)
|
|
35
|
+
from unit_workspace_ignored import diff_ignored_state, inventory_ignored_state
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _args(**values):
|
|
39
|
+
return SimpleNamespace(**values)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _verification_command(args, operation: str = "integrate") -> list[str]:
|
|
43
|
+
command = list(args.verification_command)
|
|
44
|
+
if command and command[0] == "--":
|
|
45
|
+
command.pop(0)
|
|
46
|
+
if not command or any(not value or "\0" in value for value in command):
|
|
47
|
+
raise Operational("REFUSED", f"{operation} requires a non-empty verification command after --")
|
|
48
|
+
return command
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _remove_owned_new_paths(repo: str, paths: set[str], pre_head: str) -> None:
|
|
52
|
+
for rel in sorted(paths, key=lambda value: (value.count("/"), value), reverse=True):
|
|
53
|
+
if git(repo, "ls-tree", "-z", "--full-tree", pre_head, "--", rel):
|
|
54
|
+
continue
|
|
55
|
+
target = os.path.abspath(os.path.join(repo, rel))
|
|
56
|
+
if os.path.commonpath([repo, target]) != repo:
|
|
57
|
+
raise Operational("BLOCKED", "verification artifact path escaped canonical repository")
|
|
58
|
+
if os.path.islink(target) or os.path.isfile(target):
|
|
59
|
+
os.unlink(target)
|
|
60
|
+
elif os.path.isdir(target):
|
|
61
|
+
shutil.rmtree(target)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _restore_owned_verification(
|
|
65
|
+
run_id: str,
|
|
66
|
+
unit_id: str,
|
|
67
|
+
token: str,
|
|
68
|
+
before: dict,
|
|
69
|
+
before_paths: set[str],
|
|
70
|
+
after_paths: set[str],
|
|
71
|
+
) -> None:
|
|
72
|
+
with locked_manifest(run_id) as doc:
|
|
73
|
+
validate_repo(doc)
|
|
74
|
+
unit = doc["units"].get(unit_id)
|
|
75
|
+
if not unit or not unit.get("integration", {}).get("pre_fold"):
|
|
76
|
+
raise Operational("BLOCKED", "owned verification restoration lacks pre-fold evidence")
|
|
77
|
+
repo = doc["repository"]["toplevel"]
|
|
78
|
+
pre = dict(unit["integration"]["pre_fold"])
|
|
79
|
+
expected = unit["integration"]["expected_apply"]
|
|
80
|
+
if not (
|
|
81
|
+
before["head"] == pre["head"]
|
|
82
|
+
and before["index_tree"] == expected["index_tree"]
|
|
83
|
+
and before["worktree_index_empty"]
|
|
84
|
+
and before_paths == set(expected["changed_paths"])
|
|
85
|
+
):
|
|
86
|
+
raise Operational("BLOCKED", "owned verification did not start from the expected transport application")
|
|
87
|
+
if git_text(repo, "rev-parse", "HEAD") != pre["head"]:
|
|
88
|
+
raise Operational("BLOCKED", "verification changed canonical HEAD; refusing automatic restoration")
|
|
89
|
+
verification_paths = after_paths - before_paths
|
|
90
|
+
with locked_manifest(run_id, write=True) as doc:
|
|
91
|
+
doc["units"][unit_id]["state"] = "restoring"
|
|
92
|
+
event(doc, "restore-intent", unit_id, {"source": "controller-owned-verification"})
|
|
93
|
+
git(repo, "reset", "--hard", pre["head"])
|
|
94
|
+
with locked_manifest(run_id) as doc:
|
|
95
|
+
remove_introduced_paths(repo, doc["units"][unit_id])
|
|
96
|
+
_remove_owned_new_paths(repo, verification_paths, pre["head"])
|
|
97
|
+
actual = semantic_snapshot(repo)
|
|
98
|
+
exact = actual == pre
|
|
99
|
+
with locked_manifest(run_id, write=True) as doc:
|
|
100
|
+
unit = doc["units"][unit_id]
|
|
101
|
+
unit["integration"]["restore"] = {"at": now_iso(), "exact": exact, "snapshot": actual}
|
|
102
|
+
if exact:
|
|
103
|
+
unit["state"] = "preserved"
|
|
104
|
+
event(doc, "canonical-restored", unit_id, {"source": "controller-owned-verification"})
|
|
105
|
+
else:
|
|
106
|
+
blocker = {"at": now_iso(), "unit_id": unit_id, "reason": "exact pre-fold restoration could not be proven"}
|
|
107
|
+
doc["blockers"].append(blocker)
|
|
108
|
+
event(doc, "restore-blocked", unit_id, {"source": "controller-owned-verification"})
|
|
109
|
+
if not exact:
|
|
110
|
+
raise Operational("BLOCKED", "exact pre-fold restoration could not be proven")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _verification_log(run_id: str, unit_id: str) -> tuple[str, object]:
|
|
114
|
+
parent = os.path.join(run_dir(run_id), "units", unit_id, "result")
|
|
115
|
+
validate_private_dir(parent)
|
|
116
|
+
path = os.path.join(parent, f"host-verification-{secrets.token_hex(6)}.log")
|
|
117
|
+
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | O_NOFOLLOW, 0o600)
|
|
118
|
+
return path, os.fdopen(fd, "wb")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _run_verification_log(run_id: str) -> tuple[str, object]:
|
|
122
|
+
parent = os.path.join(run_dir(run_id), "jobs")
|
|
123
|
+
validate_private_dir(parent)
|
|
124
|
+
path = os.path.join(parent, f"run-verification-{secrets.token_hex(6)}.log")
|
|
125
|
+
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | O_NOFOLLOW, 0o600)
|
|
126
|
+
return path, os.fdopen(fd, "wb")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _validate_accepted_run_head(repo: str, units: dict, current_head: str) -> None:
|
|
130
|
+
"""Require HEAD to be the accepted commit that contains every completed unit."""
|
|
131
|
+
commits: set[str] = set()
|
|
132
|
+
for unit in units.values():
|
|
133
|
+
commit = unit_accepted_commit(unit)
|
|
134
|
+
if commit is None:
|
|
135
|
+
raise Operational("BLOCKED", "unit completion evidence changed before plan-wide verification")
|
|
136
|
+
base = unit.get("workspace", {}).get("base")
|
|
137
|
+
if not isinstance(base, str) or git_text(repo, "merge-base", base, commit, check=False) != base:
|
|
138
|
+
raise Operational(
|
|
139
|
+
"BLOCKED",
|
|
140
|
+
"controller-accepted unit commit does not descend from its recorded base",
|
|
141
|
+
{"unit_id": unit.get("unit_id"), "base": base, "accepted_commit": commit},
|
|
142
|
+
)
|
|
143
|
+
if commit in commits:
|
|
144
|
+
raise Operational("BLOCKED", "unit completion evidence contains duplicate accepted commits")
|
|
145
|
+
commits.add(commit)
|
|
146
|
+
|
|
147
|
+
if current_head not in commits:
|
|
148
|
+
raise Operational(
|
|
149
|
+
"BLOCKED",
|
|
150
|
+
"canonical HEAD no longer matches the final controller-accepted unit commit",
|
|
151
|
+
{"accepted_heads": sorted(commits), "actual_head": current_head},
|
|
152
|
+
)
|
|
153
|
+
if any(git_text(repo, "merge-base", commit, current_head, check=False) != commit for commit in commits):
|
|
154
|
+
raise Operational(
|
|
155
|
+
"BLOCKED",
|
|
156
|
+
"canonical HEAD does not contain every controller-accepted unit",
|
|
157
|
+
{"accepted_heads": sorted(commits), "actual_head": current_head},
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _record_run_verification_attempt(
|
|
162
|
+
args,
|
|
163
|
+
attempt_id: str,
|
|
164
|
+
lock_unit: str,
|
|
165
|
+
lock_token: str,
|
|
166
|
+
command: list[str],
|
|
167
|
+
before: dict,
|
|
168
|
+
verification_log: str,
|
|
169
|
+
) -> None:
|
|
170
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
171
|
+
validate_lock(doc, lock_unit, lock_token)
|
|
172
|
+
doc.setdefault("verification_attempts", [])
|
|
173
|
+
attempts = plan_wide_verification_attempts(doc)
|
|
174
|
+
if any(attempt.get("attempt_id") == attempt_id for attempt in attempts):
|
|
175
|
+
raise TrustFailure("plan-wide verification attempt identity is duplicated")
|
|
176
|
+
attempts.append({
|
|
177
|
+
"attempt_id": attempt_id,
|
|
178
|
+
"started_at": now_iso(),
|
|
179
|
+
"status": "pending",
|
|
180
|
+
"integration_lock_nonce": lock_token,
|
|
181
|
+
"lock_unit_id": lock_unit,
|
|
182
|
+
"argv": command,
|
|
183
|
+
"summary": args.verification_summary,
|
|
184
|
+
"canonical_snapshot": before,
|
|
185
|
+
"verification_log": verification_log,
|
|
186
|
+
})
|
|
187
|
+
event(doc, "run-verification-started", None, {"attempt_id": attempt_id})
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _record_run_verification_receipt(args, attempt_id: str, lock_token: str, receipt: dict) -> None:
|
|
191
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
192
|
+
attempts = plan_wide_verification_attempts(doc)
|
|
193
|
+
matches = [attempt for attempt in attempts if attempt.get("attempt_id") == attempt_id]
|
|
194
|
+
if len(matches) != 1:
|
|
195
|
+
raise TrustFailure("plan-wide verification attempt identity is missing or duplicated")
|
|
196
|
+
attempt = matches[0]
|
|
197
|
+
if attempt.get("status") != "pending" or attempt.get("integration_lock_nonce") != lock_token:
|
|
198
|
+
raise TrustFailure("plan-wide verification attempt state or lock identity changed")
|
|
199
|
+
validate_lock(doc, attempt["lock_unit_id"], lock_token)
|
|
200
|
+
doc.setdefault("verifications", []).append(receipt)
|
|
201
|
+
attempt.update({
|
|
202
|
+
"status": "receipt-recorded",
|
|
203
|
+
"completed_at": now_iso(),
|
|
204
|
+
"evidence_digest": receipt["evidence_digest"],
|
|
205
|
+
})
|
|
206
|
+
event(doc, "run-verification-passed" if receipt["verification_exit"] == 0 else "run-verification-failed", None, {
|
|
207
|
+
"attempt_id": attempt_id,
|
|
208
|
+
"evidence_digest": receipt["evidence_digest"],
|
|
209
|
+
"verification_exit": receipt["verification_exit"],
|
|
210
|
+
})
|
|
211
|
+
if receipt["verification_exit"] != 0:
|
|
212
|
+
doc["blockers"].append({
|
|
213
|
+
"at": now_iso(),
|
|
214
|
+
"unit_id": None,
|
|
215
|
+
"reason": "plan-wide verification failed",
|
|
216
|
+
"evidence_digest": receipt["evidence_digest"],
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _verify_run_locked(
|
|
221
|
+
args,
|
|
222
|
+
repo: str,
|
|
223
|
+
command: list[str],
|
|
224
|
+
units: dict,
|
|
225
|
+
attempt_id: str,
|
|
226
|
+
lock_unit: str,
|
|
227
|
+
lock_token: str,
|
|
228
|
+
) -> tuple[str, dict]:
|
|
229
|
+
before = semantic_snapshot(repo)
|
|
230
|
+
before_paths = status_paths(repo)
|
|
231
|
+
if not before["status_empty"] or before_paths:
|
|
232
|
+
raise Operational("BLOCKED", "verify-run requires a clean canonical checkout")
|
|
233
|
+
_validate_accepted_run_head(repo, units, before["head"])
|
|
234
|
+
accepted_units = accepted_unit_commit_snapshot(units)
|
|
235
|
+
if accepted_units is None:
|
|
236
|
+
raise Operational("BLOCKED", "unit completion evidence changed before plan-wide verification")
|
|
237
|
+
before_ignored = inventory_ignored_state(repo)
|
|
238
|
+
|
|
239
|
+
verification_log, stream = _run_verification_log(args.run_id)
|
|
240
|
+
with stream:
|
|
241
|
+
_record_run_verification_attempt(
|
|
242
|
+
args,
|
|
243
|
+
attempt_id,
|
|
244
|
+
lock_unit,
|
|
245
|
+
lock_token,
|
|
246
|
+
command,
|
|
247
|
+
before,
|
|
248
|
+
verification_log,
|
|
249
|
+
)
|
|
250
|
+
try:
|
|
251
|
+
proc = subprocess.run(
|
|
252
|
+
command,
|
|
253
|
+
cwd=repo,
|
|
254
|
+
stdin=subprocess.DEVNULL,
|
|
255
|
+
stdout=stream,
|
|
256
|
+
stderr=subprocess.STDOUT,
|
|
257
|
+
env=sanitized_git_environment({"PYTHONDONTWRITEBYTECODE": "1"}),
|
|
258
|
+
check=False,
|
|
259
|
+
)
|
|
260
|
+
verification_exit = proc.returncode
|
|
261
|
+
except OSError as exc:
|
|
262
|
+
stream.write(f"verification launch failed: {exc}\n".encode("utf-8", "replace"))
|
|
263
|
+
verification_exit = 127
|
|
264
|
+
test_fault("verify-run-before-receipt")
|
|
265
|
+
|
|
266
|
+
after = semantic_snapshot(repo)
|
|
267
|
+
after_paths = status_paths(repo)
|
|
268
|
+
ignored_state = diff_ignored_state(before_ignored, inventory_ignored_state(repo))
|
|
269
|
+
cleaned_paths: list[str] = []
|
|
270
|
+
if after != before:
|
|
271
|
+
if after["branch_ref"] != before["branch_ref"] or after["head"] != before["head"]:
|
|
272
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
273
|
+
lock = doc.get("integration_lock") or {}
|
|
274
|
+
blocker = {
|
|
275
|
+
"at": now_iso(),
|
|
276
|
+
"unit_id": None,
|
|
277
|
+
"reason": "plan-wide verification changed canonical branch or HEAD",
|
|
278
|
+
"retain_integration_lock": True,
|
|
279
|
+
"integration_lock_nonce": lock.get("nonce"),
|
|
280
|
+
}
|
|
281
|
+
doc["blockers"].append(blocker)
|
|
282
|
+
event(doc, "run-verification-restore-blocked", None, {"verification_exit": verification_exit})
|
|
283
|
+
raise Operational(
|
|
284
|
+
"BLOCKED",
|
|
285
|
+
"plan-wide verification changed canonical branch or HEAD; automatic restoration refused",
|
|
286
|
+
{
|
|
287
|
+
"verification_exit": verification_exit,
|
|
288
|
+
"verification_log": verification_log,
|
|
289
|
+
"cleaned_paths": cleaned_paths,
|
|
290
|
+
"ignored_state": ignored_state,
|
|
291
|
+
"retain_integration_lock": True,
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
deletion_paths = after_paths - before_paths
|
|
295
|
+
cleaned_paths = sorted(deletion_paths)
|
|
296
|
+
git(repo, "reset", "--hard", before["head"])
|
|
297
|
+
_remove_owned_new_paths(repo, deletion_paths, before["head"])
|
|
298
|
+
restored = semantic_snapshot(repo)
|
|
299
|
+
if restored != before:
|
|
300
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
301
|
+
lock = doc.get("integration_lock") or {}
|
|
302
|
+
blocker = {
|
|
303
|
+
"at": now_iso(),
|
|
304
|
+
"unit_id": None,
|
|
305
|
+
"reason": "plan-wide verification restoration could not be proven",
|
|
306
|
+
"retain_integration_lock": True,
|
|
307
|
+
"integration_lock_nonce": lock.get("nonce"),
|
|
308
|
+
}
|
|
309
|
+
doc["blockers"].append(blocker)
|
|
310
|
+
event(doc, "run-verification-restore-blocked", None, {"verification_exit": verification_exit})
|
|
311
|
+
raise Operational(
|
|
312
|
+
"BLOCKED",
|
|
313
|
+
"plan-wide verification restoration could not be proven",
|
|
314
|
+
{
|
|
315
|
+
"verification_exit": verification_exit,
|
|
316
|
+
"verification_log": verification_log,
|
|
317
|
+
"cleaned_paths": cleaned_paths,
|
|
318
|
+
"ignored_state": ignored_state,
|
|
319
|
+
"retain_integration_lock": True,
|
|
320
|
+
},
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
log_digest = hashlib.sha256(Path(verification_log).read_bytes()).hexdigest()
|
|
324
|
+
receipt = {
|
|
325
|
+
"attempt_id": attempt_id,
|
|
326
|
+
"at": now_iso(),
|
|
327
|
+
"argv": command,
|
|
328
|
+
"summary": args.verification_summary,
|
|
329
|
+
"verification_exit": verification_exit,
|
|
330
|
+
"log_sha256": log_digest,
|
|
331
|
+
"canonical_head": before["head"],
|
|
332
|
+
"accepted_units": accepted_units,
|
|
333
|
+
"canonical_state_changed": after != before,
|
|
334
|
+
"cleaned_paths": cleaned_paths,
|
|
335
|
+
"ignored_state": ignored_state,
|
|
336
|
+
"verification_log": verification_log if verification_exit != 0 else None,
|
|
337
|
+
"verification_log_retained": verification_exit != 0,
|
|
338
|
+
}
|
|
339
|
+
receipt["evidence_digest"] = digest_bytes(json.dumps(receipt, sort_keys=True, separators=(",", ":")).encode())
|
|
340
|
+
_record_run_verification_receipt(args, attempt_id, lock_token, receipt)
|
|
341
|
+
if verification_exit != 0:
|
|
342
|
+
raise Operational(
|
|
343
|
+
"BLOCKED",
|
|
344
|
+
"plan-wide authoritative verification failed",
|
|
345
|
+
{
|
|
346
|
+
"verification_exit": verification_exit,
|
|
347
|
+
"verification_log": verification_log,
|
|
348
|
+
"evidence_digest": receipt["evidence_digest"],
|
|
349
|
+
"cleaned_paths": cleaned_paths,
|
|
350
|
+
"ignored_state": ignored_state,
|
|
351
|
+
},
|
|
352
|
+
)
|
|
353
|
+
os.unlink(verification_log)
|
|
354
|
+
return "RUN_VERIFIED", {
|
|
355
|
+
"verification_exit": 0,
|
|
356
|
+
"evidence_digest": receipt["evidence_digest"],
|
|
357
|
+
"canonical_head": before["head"],
|
|
358
|
+
"cleaned_paths": cleaned_paths,
|
|
359
|
+
"ignored_state": ignored_state,
|
|
360
|
+
"verification_log_retained": False,
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def cmd_verify_run(args) -> tuple[str, dict]:
|
|
365
|
+
"""Run a plan-wide gate while holding the canonical integration lock."""
|
|
366
|
+
command = _verification_command(args, "verify-run")
|
|
367
|
+
with locked_manifest(args.run_id) as doc:
|
|
368
|
+
info = validate_repo(doc)
|
|
369
|
+
units = doc.get("units", {})
|
|
370
|
+
if not units or any(not unit_ready_for_run_verification(unit) for unit in units.values()):
|
|
371
|
+
raise Operational(
|
|
372
|
+
"REFUSED",
|
|
373
|
+
"verify-run requires every unit to be terminal with an accepted canonical commit",
|
|
374
|
+
)
|
|
375
|
+
if doc.get("integration_lock") is not None:
|
|
376
|
+
raise Operational("BLOCKED", "verify-run requires no active integration lock")
|
|
377
|
+
repo = info["toplevel"]
|
|
378
|
+
lock_unit = sorted(units)[-1]
|
|
379
|
+
acquired = cmd_integration_acquire(_args(
|
|
380
|
+
run_id=args.run_id,
|
|
381
|
+
unit_id=lock_unit,
|
|
382
|
+
resume=False,
|
|
383
|
+
plan_verification=True,
|
|
384
|
+
))[1]
|
|
385
|
+
token = acquired["lock_token"]
|
|
386
|
+
attempt_id = secrets.token_hex(16)
|
|
387
|
+
try:
|
|
388
|
+
with locked_manifest(args.run_id) as doc:
|
|
389
|
+
validate_repo(doc)
|
|
390
|
+
units = doc.get("units", {})
|
|
391
|
+
if not units or any(not unit_ready_for_run_verification(unit) for unit in units.values()):
|
|
392
|
+
raise Operational("BLOCKED", "external unit completion evidence changed before plan-wide verification")
|
|
393
|
+
accepted_units = dict(units)
|
|
394
|
+
result = _verify_run_locked(
|
|
395
|
+
args,
|
|
396
|
+
repo,
|
|
397
|
+
command,
|
|
398
|
+
accepted_units,
|
|
399
|
+
attempt_id,
|
|
400
|
+
lock_unit,
|
|
401
|
+
token,
|
|
402
|
+
)
|
|
403
|
+
except Operational as exc:
|
|
404
|
+
with locked_manifest(args.run_id) as doc:
|
|
405
|
+
lock = doc.get("integration_lock")
|
|
406
|
+
pending = pending_plan_wide_verification(doc, lock) if isinstance(lock, dict) else None
|
|
407
|
+
receipted = receipted_plan_wide_verification(doc, lock) if isinstance(lock, dict) else None
|
|
408
|
+
if not exc.detail.get("retain_integration_lock") and not (
|
|
409
|
+
pending and pending.get("attempt_id") == attempt_id
|
|
410
|
+
):
|
|
411
|
+
if receipted and receipted.get("attempt_id") == attempt_id:
|
|
412
|
+
test_fault("verify-run-after-receipt")
|
|
413
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=lock_unit, lock_token=token))
|
|
414
|
+
raise
|
|
415
|
+
test_fault("verify-run-after-receipt")
|
|
416
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=lock_unit, lock_token=token))
|
|
417
|
+
return result
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def _integration_recovery_failure(args, original: Operational, failure: Operational, phase: str) -> Operational:
|
|
421
|
+
if phase == "restore":
|
|
422
|
+
reason = "integration failed and exact restoration could not be proven"
|
|
423
|
+
event_name = "integration-restore-blocked"
|
|
424
|
+
else:
|
|
425
|
+
reason = "integration failed after exact restoration but lock release failed"
|
|
426
|
+
event_name = "integration-release-blocked"
|
|
427
|
+
detail = {
|
|
428
|
+
"reason": reason,
|
|
429
|
+
"unit_id": args.unit_id,
|
|
430
|
+
"original_failure": str(original),
|
|
431
|
+
"original_word": original.word,
|
|
432
|
+
f"{phase}_failure": str(failure),
|
|
433
|
+
f"{phase}_word": failure.word,
|
|
434
|
+
"retain_integration_lock": True,
|
|
435
|
+
"recovery_path": os.path.join(run_dir(args.run_id), "units", args.unit_id),
|
|
436
|
+
}
|
|
437
|
+
if "ignored_state" in original.detail:
|
|
438
|
+
detail["ignored_state"] = original.detail["ignored_state"]
|
|
439
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
440
|
+
doc["blockers"].append({"at": now_iso(), **detail})
|
|
441
|
+
event(doc, event_name, args.unit_id, {
|
|
442
|
+
"original_word": original.word,
|
|
443
|
+
f"{phase}_word": failure.word,
|
|
444
|
+
})
|
|
445
|
+
return Operational("BLOCKED", reason, detail)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def cmd_integrate(args) -> tuple[str, dict]:
|
|
449
|
+
command = _verification_command(args)
|
|
450
|
+
if not args.commit_message.strip() or len(args.commit_message.encode()) > 1024:
|
|
451
|
+
raise Operational("REFUSED", "commit message must be non-empty and at most 1024 bytes")
|
|
452
|
+
|
|
453
|
+
token = None
|
|
454
|
+
before = None
|
|
455
|
+
verification_log = None
|
|
456
|
+
committed = False
|
|
457
|
+
ignored_state = None
|
|
458
|
+
try:
|
|
459
|
+
acquired = cmd_integration_acquire(_args(run_id=args.run_id, unit_id=args.unit_id, resume=False))[1]
|
|
460
|
+
token = acquired["lock_token"]
|
|
461
|
+
cmd_preflight(_args(
|
|
462
|
+
run_id=args.run_id,
|
|
463
|
+
unit_id=args.unit_id,
|
|
464
|
+
lock_token=token,
|
|
465
|
+
allowed_head=args.allowed_head,
|
|
466
|
+
))
|
|
467
|
+
with locked_manifest(args.run_id) as doc:
|
|
468
|
+
repo = doc["repository"]["toplevel"]
|
|
469
|
+
transport = doc["units"][args.unit_id]["transport"]["commit"]
|
|
470
|
+
git(repo, "cherry-pick", "--no-commit", transport)
|
|
471
|
+
cmd_mark_applied(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
472
|
+
with locked_manifest(args.run_id) as doc:
|
|
473
|
+
unit = doc["units"][args.unit_id]
|
|
474
|
+
if not matches_expected_apply(repo, unit):
|
|
475
|
+
raise Operational("BLOCKED", "canonical apply changed before verification")
|
|
476
|
+
before = semantic_snapshot(repo)
|
|
477
|
+
before_paths = status_paths(repo)
|
|
478
|
+
before_ignored = inventory_ignored_state(repo)
|
|
479
|
+
|
|
480
|
+
verification_log, stream = _verification_log(args.run_id, args.unit_id)
|
|
481
|
+
with stream:
|
|
482
|
+
try:
|
|
483
|
+
proc = subprocess.run(
|
|
484
|
+
command,
|
|
485
|
+
cwd=repo,
|
|
486
|
+
stdin=subprocess.DEVNULL,
|
|
487
|
+
stdout=stream,
|
|
488
|
+
stderr=subprocess.STDOUT,
|
|
489
|
+
env=sanitized_git_environment({"PYTHONDONTWRITEBYTECODE": "1"}),
|
|
490
|
+
check=False,
|
|
491
|
+
)
|
|
492
|
+
verification_exit = proc.returncode
|
|
493
|
+
except OSError as exc:
|
|
494
|
+
stream.write(f"verification launch failed: {exc}\n".encode("utf-8", "replace"))
|
|
495
|
+
verification_exit = 127
|
|
496
|
+
after = semantic_snapshot(repo)
|
|
497
|
+
after_paths = status_paths(repo)
|
|
498
|
+
ignored_state = diff_ignored_state(before_ignored, inventory_ignored_state(repo))
|
|
499
|
+
verification_failed = verification_exit != 0 or after != before
|
|
500
|
+
if verification_failed:
|
|
501
|
+
_restore_owned_verification(args.run_id, args.unit_id, token, before, before_paths, after_paths)
|
|
502
|
+
cleaned_paths = sorted(after_paths - before_paths)
|
|
503
|
+
log_digest = hashlib.sha256(Path(verification_log).read_bytes()).hexdigest()
|
|
504
|
+
if verification_failed:
|
|
505
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
506
|
+
token = None
|
|
507
|
+
raise Operational(
|
|
508
|
+
"BLOCKED",
|
|
509
|
+
"authoritative verification failed or changed canonical state",
|
|
510
|
+
{
|
|
511
|
+
"unit_id": args.unit_id,
|
|
512
|
+
"verification_exit": verification_exit,
|
|
513
|
+
"verification_log": verification_log,
|
|
514
|
+
"canonical_state_changed": after != before,
|
|
515
|
+
"cleaned_paths": cleaned_paths,
|
|
516
|
+
"ignored_state": ignored_state,
|
|
517
|
+
},
|
|
518
|
+
)
|
|
519
|
+
evidence = digest_bytes(json.dumps({
|
|
520
|
+
"argv": command,
|
|
521
|
+
"exit": verification_exit,
|
|
522
|
+
"log_sha256": log_digest,
|
|
523
|
+
"before": before,
|
|
524
|
+
"after": after,
|
|
525
|
+
"cleaned_paths": cleaned_paths,
|
|
526
|
+
"ignored_state": ignored_state,
|
|
527
|
+
}, sort_keys=True, separators=(",", ":")).encode())
|
|
528
|
+
cmd_mark_verified(_args(
|
|
529
|
+
run_id=args.run_id,
|
|
530
|
+
unit_id=args.unit_id,
|
|
531
|
+
lock_token=token,
|
|
532
|
+
evidence_digest=evidence,
|
|
533
|
+
summary=args.verification_summary,
|
|
534
|
+
ignored_state=ignored_state,
|
|
535
|
+
))
|
|
536
|
+
test_fault("before-canonical-commit")
|
|
537
|
+
commit_index_tree(repo, args.commit_message)
|
|
538
|
+
committed_body = cmd_mark_committed(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))[1]
|
|
539
|
+
committed = True
|
|
540
|
+
canonical = committed_body["canonical_commit"]["commit"]
|
|
541
|
+
test_fault("after-canonical-commit-confirmed")
|
|
542
|
+
with locked_manifest(args.run_id) as doc:
|
|
543
|
+
wave_id = doc["units"][args.unit_id].get("wave", {}).get("id")
|
|
544
|
+
if wave_id:
|
|
545
|
+
cmd_wave_advance(_args(
|
|
546
|
+
run_id=args.run_id,
|
|
547
|
+
unit_id=args.unit_id,
|
|
548
|
+
lock_token=token,
|
|
549
|
+
canonical_commit=canonical,
|
|
550
|
+
))
|
|
551
|
+
cmd_cleanup(_args(
|
|
552
|
+
run_id=args.run_id,
|
|
553
|
+
unit_id=args.unit_id,
|
|
554
|
+
abandon=False,
|
|
555
|
+
expect_transport=None,
|
|
556
|
+
expect_job=None,
|
|
557
|
+
))
|
|
558
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
559
|
+
token = None
|
|
560
|
+
return "UNIT_COMMITTED", {
|
|
561
|
+
"unit_id": args.unit_id,
|
|
562
|
+
"canonical_commit": canonical,
|
|
563
|
+
"verification_digest": evidence,
|
|
564
|
+
"verification_log_retained": False,
|
|
565
|
+
"cleaned_paths": cleaned_paths,
|
|
566
|
+
"ignored_state": ignored_state,
|
|
567
|
+
}
|
|
568
|
+
except (Operational, TrustFailure) as original:
|
|
569
|
+
if ignored_state is not None:
|
|
570
|
+
original.detail.setdefault("ignored_state", ignored_state)
|
|
571
|
+
if token is not None and committed:
|
|
572
|
+
detail = {
|
|
573
|
+
"reason": "canonical commit accepted but post-commit finalization is incomplete",
|
|
574
|
+
"unit_id": args.unit_id,
|
|
575
|
+
"canonical_commit": canonical,
|
|
576
|
+
"original_failure": str(original),
|
|
577
|
+
"original_word": original.word,
|
|
578
|
+
"retain_integration_lock": True,
|
|
579
|
+
"recovery_path": os.path.join(run_dir(args.run_id), "units", args.unit_id),
|
|
580
|
+
"ignored_state": ignored_state,
|
|
581
|
+
}
|
|
582
|
+
with locked_manifest(args.run_id, write=True) as doc:
|
|
583
|
+
doc["blockers"].append({"at": now_iso(), **detail})
|
|
584
|
+
event(doc, "post-commit-finalization-blocked", args.unit_id, {
|
|
585
|
+
"canonical_commit": canonical,
|
|
586
|
+
"original_word": original.word,
|
|
587
|
+
})
|
|
588
|
+
raise Operational(
|
|
589
|
+
"BLOCKED",
|
|
590
|
+
"canonical commit accepted but post-commit finalization is incomplete",
|
|
591
|
+
detail,
|
|
592
|
+
) from original
|
|
593
|
+
if token is not None and original.detail.get("retain_integration_lock"):
|
|
594
|
+
raise
|
|
595
|
+
if token is not None:
|
|
596
|
+
with locked_manifest(args.run_id) as doc:
|
|
597
|
+
unit = doc["units"].get(args.unit_id)
|
|
598
|
+
pre_fold = unit.get("integration", {}).get("pre_fold") if unit else None
|
|
599
|
+
if not pre_fold:
|
|
600
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
601
|
+
token = None
|
|
602
|
+
raise
|
|
603
|
+
try:
|
|
604
|
+
cmd_restore(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
605
|
+
except (Operational, TrustFailure) as restore_failure:
|
|
606
|
+
raise _integration_recovery_failure(args, original, restore_failure, "restore") from restore_failure
|
|
607
|
+
try:
|
|
608
|
+
cmd_integration_release(_args(run_id=args.run_id, unit_id=args.unit_id, lock_token=token))
|
|
609
|
+
token = None
|
|
610
|
+
except (Operational, TrustFailure) as release_failure:
|
|
611
|
+
raise _integration_recovery_failure(args, original, release_failure, "release") from release_failure
|
|
612
|
+
raise
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ce-worktree
|
|
3
|
+
description: Set up isolated git worktrees — create a new branch for fresh work, or attach a worktree to an existing branch, PR, or commit. Use when starting isolated work or isolating an existing ref.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Worktree Isolation
|
|
7
|
+
|
|
8
|
+
Ensure the current work happens in an isolated workspace, without disturbing the user's main checkout. Most coding harnesses now create a worktree by default at session start, so the common case is that **isolation already exists**.
|
|
9
|
+
|
|
10
|
+
**Done when:** the caller is working in an isolated tree — existing or newly created — and its path and branch have been reported, or a blocker has been reported instead.
|
|
11
|
+
|
|
12
|
+
**Order of operations: detect existing isolation -> prefer a native worktree tool -> fall back to plain git.** Never create a worktree the harness cannot see.
|
|
13
|
+
|
|
14
|
+
**Two modes, set by the caller's need:**
|
|
15
|
+
|
|
16
|
+
- **New work (default).** No ref named — create a fresh branch from a base (trunk). This is what `ce-work` and `ce-code-review` use when the user picks the worktree option.
|
|
17
|
+
- **Isolate an existing ref.** The caller names a PR head, branch, or commit — attach the worktree to that ref instead of creating a new branch. **A branch can be checked out in only one worktree at a time.** If the named ref is already checked out anywhere (most commonly as the primary checkout's current branch), do **not** create a second worktree — report that it is already checked out at `<path>` and let the caller act (work there in place; or, only if a clean separate tree is essential, create a *detached* worktree at the same commit).
|
|
18
|
+
|
|
19
|
+
## Step 0: Detect existing isolation
|
|
20
|
+
|
|
21
|
+
Compare the **resolved absolute** git dir against the **resolved absolute** common git dir. Git mixes absolute and relative forms depending on the current directory (from a subdirectory of a normal checkout, `--git-dir` comes back absolute while `--git-common-dir` may be relative), so a raw string compare yields a false "already isolated":
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git rev-parse --absolute-git-dir # absolute git dir for this worktree
|
|
25
|
+
(cd "$(git rev-parse --git-common-dir)" && pwd -P) # absolute shared (common) git dir
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Equal** -> normal checkout; continue to Step 1.
|
|
29
|
+
|
|
30
|
+
**Different** -> a linked worktree *or* a submodule. Distinguish with `git rev-parse --show-superproject-working-tree`:
|
|
31
|
+
|
|
32
|
+
- **Non-empty** -> submodule; treat it as a normal checkout and continue to Step 1.
|
|
33
|
+
- **Empty** -> **already isolated**. Report the worktree path (`git rev-parse --show-toplevel`) and current branch, then **work in place** — a worktree-from-worktree lands in the wrong tree and is invisible to the harness that made the current one. In isolate-an-existing-ref mode, check that ref out here (unless it is already current) rather than nesting a worktree.
|
|
34
|
+
|
|
35
|
+
## Step 1: Prefer the harness's native worktree tool
|
|
36
|
+
|
|
37
|
+
If the harness provides a native worktree primitive — for example an `EnterWorktree` / `WorktreeCreate` tool, a `/worktree` command, or a `--worktree` flag — use it and stop. Native tools place, track, and clean up the worktree so the harness can manage it. A behind-the-back `git worktree add` creates phantom state the harness cannot see, navigate to, or clean up.
|
|
38
|
+
|
|
39
|
+
## Step 2: Git fallback
|
|
40
|
+
|
|
41
|
+
Only when there is no native tool **and** Step 0 found no existing isolation.
|
|
42
|
+
|
|
43
|
+
1. **Run from the repo root:** `cd "$(git rev-parse --show-toplevel)"`. The paths below are repo-root-relative, but the skill runs from the user's current directory — without this, `.worktrees/<branch>` and the `.gitignore` edit land in a subdirectory (e.g. `src/.worktrees/...`).
|
|
44
|
+
2. Choose a meaningful branch name from the work description (e.g. `feat/login`, `fix/email-validation`) — never an opaque auto-generated one. Base: origin's default branch, else `main`.
|
|
45
|
+
3. **Ensure `.worktrees/` is gitignored before creating anything:** `git check-ignore -q .worktrees/` — **with the trailing slash**, so an existing directory-only `.worktrees/` rule is honored even before the directory exists (without the slash the probe misses it and dirties a correctly-configured repo). Not ignored -> add a `.worktrees/` line to `.gitignore`.
|
|
46
|
+
4. Refresh the base with `git fetch origin <from-branch>`. This is **non-fatal** — no `origin` remote, a differently-named remote, or a local-only branch is not an abort; continue with the local ref.
|
|
47
|
+
5. Create the worktree, per mode:
|
|
48
|
+
- **New work:** `git worktree add -b <branch-name> .worktrees/<branch-name> origin/<from-branch>` (use the local `<from-branch>` ref if `origin/<from-branch>` does not exist).
|
|
49
|
+
- **Existing branch or tag:** `git worktree add .worktrees/<slug> <target-ref>`.
|
|
50
|
+
- **PR:** check it out on a **local branch** — `git fetch origin pull/<n>/head:pr-<n>` then `git worktree add .worktrees/pr-<n> pr-<n>`. Never a detached `FETCH_HEAD`: that orphans the fix loop's commits instead of updating the PR. (For push-tracking back to the PR, create it detached — `git worktree add --detach .worktrees/pr-<n>` — then `cd` in and run `gh pr checkout <n>`, which is fork-safe.)
|
|
51
|
+
- If git reports the ref is already checked out elsewhere, apply the one-branch-one-worktree rule above — do not force a second worktree.
|
|
52
|
+
6. `cd` into it, then report the path and branch.
|
|
53
|
+
|
|
54
|
+
If `git worktree add` fails with a sandbox or permission error, the requested isolation does not exist. Do **not** proceed in the current checkout — the user chose isolation specifically to avoid it. Report the failure and ask, offering options such as "work in the current checkout" vs "stop and resolve the permission issue", using the host's blocking question tool already in the current tool list (match by capability, not by a host-specific name). Presence in the current tool list is proof the tool exists; never call a user-facing question tool to discover whether it exists. If a matching tool is listed but unloaded, use the host's tool-discovery primitive to load that capability — do not search for another host's tool name. Only when no such tool is in the list or a real question call errors, present the numbered options in chat and wait for the reply. Never skip the confirmation, and do not retry alternative paths automatically.
|