@opengsd/gsd-core 1.15.0 → 1.17.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -2
- package/.opencode/plugins/gsd-core.js +336 -6
- package/.opencode/plugins/gsd-statusline/tui.tsx +55 -0
- package/GEMINI.md +1 -1
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +5 -3
- package/agents/gsd-code-reviewer.md +8 -6
- package/agents/gsd-debug-session-manager.compact.md +7 -1
- package/agents/gsd-debug-session-manager.md +7 -1
- package/agents/gsd-debugger.md +2 -2
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +4 -4
- package/agents/gsd-intel-updater.compact.md +1 -1
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +2 -2
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +7 -2
- package/agents/gsd-planner.md +3 -3
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +1 -1
- package/agents/gsd-research-synthesizer.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +21 -30
- package/agents/gsd-ui-auditor.md +42 -51
- package/agents/gsd-ui-researcher.compact.md +1 -1
- package/agents/gsd-ui-researcher.md +1 -1
- package/agents/gsd-verifier.md +31 -9
- package/bin/gsd-mcp-server.js +3 -1
- package/bin/install.js +487 -290
- package/commands/gsd/add-tests.md +6 -1
- package/commands/gsd/ai-integration-phase.md +6 -1
- package/commands/gsd/audit-fix.md +5 -0
- package/commands/gsd/audit-milestone.md +6 -1
- package/commands/gsd/autonomous.md +5 -0
- package/commands/gsd/capture.md +8 -4
- package/commands/gsd/code-review.md +7 -2
- package/commands/gsd/complete-milestone.md +4 -0
- package/commands/gsd/config.md +7 -3
- package/commands/gsd/debug.md +11 -7
- package/commands/gsd/discuss-phase.md +7 -3
- package/commands/gsd/docs-update.md +12 -7
- package/commands/gsd/eval-review.md +6 -1
- package/commands/gsd/execute-phase.md +12 -7
- package/commands/gsd/extract-learnings.md +5 -0
- package/commands/gsd/fast.md +4 -0
- package/commands/gsd/forensics.md +5 -1
- package/commands/gsd/graphify.md +10 -6
- package/commands/gsd/health.md +5 -0
- package/commands/gsd/help.md +7 -2
- package/commands/gsd/import.md +7 -3
- package/commands/gsd/inbox.md +5 -0
- package/commands/gsd/ingest-docs.md +5 -1
- package/commands/gsd/manager.md +6 -1
- package/commands/gsd/map-codebase.md +7 -3
- package/commands/gsd/mempalace-capture.md +5 -1
- package/commands/gsd/mempalace-recall.md +5 -1
- package/commands/gsd/milestone-summary.md +5 -1
- package/commands/gsd/mvp-phase.md +8 -3
- package/commands/gsd/new-milestone.md +6 -1
- package/commands/gsd/new-project.md +5 -0
- package/commands/gsd/next.md +6 -1
- package/commands/gsd/ns-context.md +4 -0
- package/commands/gsd/ns-ideate.md +4 -0
- package/commands/gsd/ns-manage.md +4 -0
- package/commands/gsd/ns-project.md +4 -0
- package/commands/gsd/ns-review.md +4 -0
- package/commands/gsd/ns-workflow.md +4 -0
- package/commands/gsd/onboard.md +6 -1
- package/commands/gsd/pause-work.md +5 -1
- package/commands/gsd/phase.md +8 -4
- package/commands/gsd/plan-phase.md +6 -1
- package/commands/gsd/plan-review-convergence.md +5 -1
- package/commands/gsd/pr-branch.md +4 -0
- package/commands/gsd/profile-user.md +5 -1
- package/commands/gsd/progress.md +6 -1
- package/commands/gsd/quick-batch.md +20 -8
- package/commands/gsd/quick.md +12 -7
- package/commands/gsd/review.md +5 -1
- package/commands/gsd/secure-phase.md +6 -1
- package/commands/gsd/ship.md +5 -0
- package/commands/gsd/sketch.md +7 -2
- package/commands/gsd/spec-phase.md +5 -1
- package/commands/gsd/spike.md +8 -3
- package/commands/gsd/surface.md +5 -1
- package/commands/gsd/thread.md +4 -0
- package/commands/gsd/ui-phase.md +6 -1
- package/commands/gsd/ui-review.md +6 -1
- package/commands/gsd/ultraplan-phase.md +5 -1
- package/commands/gsd/undo.md +5 -1
- package/commands/gsd/update.md +6 -2
- package/commands/gsd/validate-phase.md +6 -1
- package/commands/gsd/verify-work.md +6 -1
- package/commands/gsd/workspace.md +7 -3
- package/gsd-core/bin/gsd-tools.cjs +159 -58
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- package/gsd-core/bin/lib/adr-parser.cjs +37 -5
- package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
- package/gsd-core/bin/lib/audit.cjs +78 -44
- package/gsd-core/bin/lib/broken-windows.cjs +13 -13
- package/gsd-core/bin/lib/capability-activation.cjs +9 -4
- package/gsd-core/bin/lib/capability-registry.cjs +249 -117
- package/gsd-core/bin/lib/capability-validator.cjs +18 -1
- package/gsd-core/bin/lib/capability-writer.cjs +2 -1
- package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
- package/gsd-core/bin/lib/check-command-router.cjs +164 -1712
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
- package/gsd-core/bin/lib/cli-exit.cjs +12 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +11 -8
- package/gsd-core/bin/lib/command-aliases.cjs +7 -0
- package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
- package/gsd-core/bin/lib/commands.cjs +201 -178
- package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
- package/gsd-core/bin/lib/config.cjs +43 -12
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/coverage.cjs +4 -8
- package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
- package/gsd-core/bin/lib/drift.cjs +177 -42
- package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
- package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
- package/gsd-core/bin/lib/frontmatter.cjs +413 -234
- package/gsd-core/bin/lib/gap-checker.cjs +72 -29
- package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
- package/gsd-core/bin/lib/gate-args.cjs +53 -0
- package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
- package/gsd-core/bin/lib/gate-config.cjs +46 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +142 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
- package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
- package/gsd-core/bin/lib/gate-exit.cjs +27 -0
- package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
- package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
- package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
- package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
- package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
- package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
- package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
- package/gsd-core/bin/lib/gate-ui-safety.cjs +81 -0
- package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
- package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
- package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
- package/gsd-core/bin/lib/graphify.cjs +3 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
- package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
- package/gsd-core/bin/lib/init.cjs +194 -108
- package/gsd-core/bin/lib/install-engine.cjs +30 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/install-shadow-report.cjs +12 -0
- package/gsd-core/bin/lib/installer-migrations/011-opencode-mcp-no-prompts.cjs +99 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +54 -1
- package/gsd-core/bin/lib/io.cjs +122 -3
- package/gsd-core/bin/lib/jsonc-edit.cjs +418 -0
- package/gsd-core/bin/lib/loop-host-contract.cjs +2 -1
- package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
- package/gsd-core/bin/lib/mcp-server.cjs +5 -1
- package/gsd-core/bin/lib/milestone.cjs +19 -1
- package/gsd-core/bin/lib/model-resolver.cjs +18 -18
- package/gsd-core/bin/lib/observability/event.cjs +1 -1
- package/gsd-core/bin/lib/observability/logger.cjs +46 -1
- package/gsd-core/bin/lib/opencode-mcp-entry.cjs +39 -0
- package/gsd-core/bin/lib/opencode-version.cjs +486 -0
- package/gsd-core/bin/lib/pattern.cjs +10 -0
- package/gsd-core/bin/lib/phase-command-router.cjs +11 -4
- package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
- package/gsd-core/bin/lib/phase-id.cjs +1 -1
- package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
- package/gsd-core/bin/lib/phase-status.cjs +360 -0
- package/gsd-core/bin/lib/phase.cjs +301 -80
- package/gsd-core/bin/lib/plan-document.cjs +93 -19
- package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
- package/gsd-core/bin/lib/planning-document.cjs +273 -40
- package/gsd-core/bin/lib/planning-inspect.cjs +42 -8
- package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +76 -53
- package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
- package/gsd-core/bin/lib/profile-output.cjs +6 -3
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
- package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +13 -9
- package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
- package/gsd-core/bin/lib/report-parser.cjs +269 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +13 -15
- package/gsd-core/bin/lib/roadmap-parser.cjs +82 -15
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +127 -65
- package/gsd-core/bin/lib/roadmap.cjs +169 -72
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +186 -161
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -1
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
- package/gsd-core/bin/lib/runtime-homes.cjs +13 -10
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +365 -594
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +60 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +111 -56
- package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
- package/gsd-core/bin/lib/state-contract.cjs +15 -18
- package/gsd-core/bin/lib/state-document.cjs +100 -22
- package/gsd-core/bin/lib/state-transition.cjs +67 -9
- package/gsd-core/bin/lib/state.cjs +668 -171
- package/gsd-core/bin/lib/surface.cjs +2 -1
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -152
- package/gsd-core/bin/lib/uat-predicate.cjs +313 -35
- package/gsd-core/bin/lib/uat.cjs +424 -7
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +94 -58
- package/gsd-core/bin/lib/update-context.cjs +18 -1
- package/gsd-core/bin/lib/vendor/README.md +31 -9
- package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
- package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
- package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +1265 -324
- package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
- package/gsd-core/bin/lib/verify.cjs +286 -567
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
- package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
- package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
- package/gsd-core/bin/lib/workstream.cjs +11 -2
- package/gsd-core/bin/shared/config-defaults.manifest.json +5 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -0
- package/gsd-core/references/autonomous-smart-discuss.md +2 -1
- package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
- package/gsd-core/references/execute-mvp-tdd.md +5 -10
- package/gsd-core/references/execute-phase-between-wave-reset.md +3 -0
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +7 -1
- package/gsd-core/references/offer-next.md +1 -1
- package/gsd-core/references/planning-config.md +1 -1
- package/gsd-core/references/spidr-splitting.md +1 -1
- package/gsd-core/references/tdd.md +10 -4
- package/gsd-core/references/verifier-phase-gates.md +5 -2
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -3
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/UAT.md +17 -1
- package/gsd-core/templates/config.json +2 -11
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
- package/gsd-core/workflows/add-backlog.md +1 -1
- package/gsd-core/workflows/add-phase.md +8 -7
- package/gsd-core/workflows/add-tests.md +3 -2
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +3 -2
- package/gsd-core/workflows/audit-fix.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +4 -3
- package/gsd-core/workflows/audit-uat.md +1 -1
- package/gsd-core/workflows/autonomous.md +28 -18
- package/gsd-core/workflows/check-todos.md +6 -5
- package/gsd-core/workflows/cleanup.md +1 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
- package/gsd-core/workflows/code-review-fix.md +5 -4
- package/gsd-core/workflows/code-review.md +100 -91
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
- package/gsd-core/workflows/complete-milestone.md +12 -7
- package/gsd-core/workflows/debug.md +30 -5
- package/gsd-core/workflows/diagnose-issues.md +3 -2
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +4 -3
- package/gsd-core/workflows/do.md +1 -1
- package/gsd-core/workflows/docs-update.md +4 -3
- package/gsd-core/workflows/edit-phase.md +4 -3
- package/gsd-core/workflows/eval-review.md +5 -3
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +4 -2
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
- package/gsd-core/workflows/execute-phase.md +81 -171
- package/gsd-core/workflows/execute-plan.md +13 -19
- package/gsd-core/workflows/explore.md +2 -2
- package/gsd-core/workflows/extract-learnings.md +3 -2
- package/gsd-core/workflows/fast.md +1 -1
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +3 -2
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +4 -3
- package/gsd-core/workflows/list-seeds.md +1 -1
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +5 -3
- package/gsd-core/workflows/map-codebase.md +4 -3
- package/gsd-core/workflows/milestone-summary.md +3 -2
- package/gsd-core/workflows/mvp-phase.md +14 -14
- package/gsd-core/workflows/new-milestone.md +10 -10
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +1 -1
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +1 -1
- package/gsd-core/workflows/pause-work.md +2 -2
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +1 -1
- package/gsd-core/workflows/plan-phase.md +27 -18
- package/gsd-core/workflows/plan-review-convergence.md +1 -1
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +1 -1
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress.md +19 -49
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -2
- package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
- package/gsd-core/workflows/quick-batch.md +15 -10
- package/gsd-core/workflows/quick.md +42 -31
- package/gsd-core/workflows/remove-phase.md +3 -2
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +17 -12
- package/gsd-core/workflows/review.md +3 -2
- package/gsd-core/workflows/scan.md +3 -2
- package/gsd-core/workflows/secure-phase.md +11 -12
- package/gsd-core/workflows/settings-advanced.md +1 -1
- package/gsd-core/workflows/settings-integrations.md +1 -1
- package/gsd-core/workflows/settings.md +1 -1
- package/gsd-core/workflows/ship.md +12 -12
- package/gsd-core/workflows/sketch-wrap-up.md +1 -1
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/spike-wrap-up.md +1 -1
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +1 -1
- package/gsd-core/workflows/sync-skills.md +1 -1
- package/gsd-core/workflows/thread.md +2 -2
- package/gsd-core/workflows/transition.md +13 -23
- package/gsd-core/workflows/ui-phase.md +5 -4
- package/gsd-core/workflows/ui-review.md +4 -3
- package/gsd-core/workflows/ultraplan-phase.md +3 -2
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/validate-phase.md +10 -12
- package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
- package/gsd-core/workflows/verify-work.md +68 -59
- package/hooks/dist/gsd-agent-isolation-guard.js +8 -0
- package/hooks/dist/gsd-check-update-worker.js +8 -0
- package/hooks/dist/gsd-check-update.js +34 -20
- package/hooks/dist/gsd-context-monitor.js +45 -13
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +263 -16
- package/hooks/dist/gsd-statusline.js +336 -29
- package/hooks/dist/gsd-update-banner.js +8 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
- package/hooks/dist/gsd-workflow-guard.js +5 -4
- package/hooks/dist/gsd-worktree-path-guard.js +6 -2
- package/hooks/dist/lib/cli-exit.js +12 -0
- package/hooks/dist/lib/git-probe.js +17 -1
- package/hooks/dist/lib/isolation-sentinel.js +2 -2
- package/hooks/gsd-agent-isolation-guard.js +8 -0
- package/hooks/gsd-check-update-worker.js +8 -0
- package/hooks/gsd-check-update.js +34 -20
- package/hooks/gsd-context-monitor.js +45 -13
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +263 -16
- package/hooks/gsd-statusline.js +336 -29
- package/hooks/gsd-update-banner.js +8 -0
- package/hooks/gsd-windsurf-pre-write.js +11 -2
- package/hooks/gsd-workflow-guard.js +5 -4
- package/hooks/gsd-worktree-path-guard.js +6 -2
- package/hooks/hooks.json +5 -5
- package/hooks/lib/cli-exit.js +12 -0
- package/hooks/lib/git-probe.js +17 -1
- package/hooks/lib/isolation-sentinel.js +2 -2
- package/package.json +21 -4
- package/scripts/changeset/parse.cjs +52 -4
- package/scripts/ci-timeout-report.cjs +770 -4
- package/scripts/command-contract-helpers.cjs +12 -8
- package/scripts/docs-guard-registry.cjs +6 -0
- package/scripts/gen-capability-registry.cjs +7 -1
- package/scripts/gen-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +14 -2
- package/scripts/gen-platform-conformance-tier.cjs +187 -1
- package/scripts/gen-plugin-skills.cjs +87 -1
- package/scripts/gen-research-agents.cjs +24 -31
- package/scripts/gen-scripts-cli-exit.cjs +30 -3
- package/scripts/gen-test-timings.cjs +32 -7
- package/scripts/lib/cli-exit.cjs +12 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +24 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +44 -5
- package/scripts/lib/registration-ledger-preload.cjs +155 -0
- package/scripts/lib/vendor-bundle.cjs +59 -0
- package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-completion-predicate-drift.cjs +18 -19
- package/scripts/lint-descriptions.cjs +7 -3
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +10 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
- package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
- package/scripts/lint-phase-enumeration-drift.cjs +12 -8
- package/scripts/lint-phase-id-drift.cjs +29 -0
- package/scripts/lint-planning-document-positive-control.cjs +329 -0
- package/scripts/lint-response-language-coverage.cjs +3 -0
- package/scripts/lint-skill-deps.cjs +7 -3
- package/scripts/lint-test-file-count.allowlist.json +11 -1
- package/scripts/lint-test-file-count.cjs +34 -1
- package/scripts/lint-vendored-deps.cjs +41 -5
- package/scripts/lint-workflow-shellcheck-baseline.json +10 -10
- package/scripts/mutation-matrix.cjs +53 -6
- package/scripts/release-tarball-smoke.cjs +14 -7
- package/scripts/require-issue-link-policy.cjs +6 -2
- package/scripts/sync-runtime-launcher.cjs +184 -2
- package/scripts/verify-npm-publish.cjs +76 -20
- package/skills/gsd-add-tests/SKILL.md +6 -1
- package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
- package/skills/gsd-audit-fix/SKILL.md +5 -0
- package/skills/gsd-audit-milestone/SKILL.md +6 -1
- package/skills/gsd-autonomous/SKILL.md +5 -0
- package/skills/gsd-capture/SKILL.md +8 -4
- package/skills/gsd-code-review/SKILL.md +7 -2
- package/skills/gsd-complete-milestone/SKILL.md +4 -0
- package/skills/gsd-config/SKILL.md +8 -4
- package/skills/gsd-debug/SKILL.md +11 -7
- package/skills/gsd-discuss-phase/SKILL.md +7 -3
- package/skills/gsd-docs-update/SKILL.md +12 -7
- package/skills/gsd-eval-review/SKILL.md +6 -1
- package/skills/gsd-execute-phase/SKILL.md +12 -7
- package/skills/gsd-extract-learnings/SKILL.md +5 -0
- package/skills/gsd-fast/SKILL.md +4 -0
- package/skills/gsd-forensics/SKILL.md +5 -1
- package/skills/gsd-graphify/SKILL.md +10 -6
- package/skills/gsd-health/SKILL.md +5 -0
- package/skills/gsd-help/SKILL.md +7 -2
- package/skills/gsd-import/SKILL.md +7 -3
- package/skills/gsd-inbox/SKILL.md +5 -0
- package/skills/gsd-ingest-docs/SKILL.md +5 -1
- package/skills/gsd-manager/SKILL.md +6 -1
- package/skills/gsd-map-codebase/SKILL.md +7 -3
- package/skills/gsd-mempalace-capture/SKILL.md +5 -1
- package/skills/gsd-mempalace-recall/SKILL.md +5 -1
- package/skills/gsd-milestone-summary/SKILL.md +5 -1
- package/skills/gsd-mvp-phase/SKILL.md +8 -3
- package/skills/gsd-new-milestone/SKILL.md +6 -1
- package/skills/gsd-new-project/SKILL.md +5 -0
- package/skills/gsd-next/SKILL.md +6 -1
- package/skills/gsd-ns-context/SKILL.md +4 -0
- package/skills/gsd-ns-ideate/SKILL.md +4 -0
- package/skills/gsd-ns-manage/SKILL.md +4 -0
- package/skills/gsd-ns-project/SKILL.md +4 -0
- package/skills/gsd-ns-review/SKILL.md +4 -0
- package/skills/gsd-ns-workflow/SKILL.md +4 -0
- package/skills/gsd-onboard/SKILL.md +6 -1
- package/skills/gsd-pause-work/SKILL.md +5 -1
- package/skills/gsd-phase/SKILL.md +8 -4
- package/skills/gsd-plan-phase/SKILL.md +6 -1
- package/skills/gsd-plan-review-convergence/SKILL.md +5 -1
- package/skills/gsd-pr-branch/SKILL.md +4 -0
- package/skills/gsd-profile-user/SKILL.md +5 -1
- package/skills/gsd-progress/SKILL.md +6 -1
- package/skills/gsd-quick/SKILL.md +16 -10
- package/skills/gsd-quick-batch/SKILL.md +20 -8
- package/skills/gsd-review/SKILL.md +5 -1
- package/skills/gsd-review-backlog/SKILL.md +3 -2
- package/skills/gsd-secure-phase/SKILL.md +6 -1
- package/skills/gsd-ship/SKILL.md +5 -0
- package/skills/gsd-sketch/SKILL.md +7 -2
- package/skills/gsd-spec-phase/SKILL.md +5 -1
- package/skills/gsd-spike/SKILL.md +8 -3
- package/skills/gsd-surface/SKILL.md +5 -1
- package/skills/gsd-thread/SKILL.md +4 -0
- package/skills/gsd-ui-phase/SKILL.md +6 -1
- package/skills/gsd-ui-review/SKILL.md +6 -1
- package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
- package/skills/gsd-undo/SKILL.md +5 -1
- package/skills/gsd-update/SKILL.md +6 -2
- package/skills/gsd-validate-phase/SKILL.md +6 -1
- package/skills/gsd-verify-work/SKILL.md +6 -1
- package/skills/gsd-workspace/SKILL.md +7 -3
- package/skills/gsd-workstreams/SKILL.md +6 -6
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/execute-phase/steps/stale-reverification.md +0 -24
|
@@ -33,11 +33,12 @@ const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
|
33
33
|
const commandRoster = require("./command-roster.cjs");
|
|
34
34
|
const { readGsdCommandNames, transformContentToHyphen } = commandRoster;
|
|
35
35
|
const runtimeNamePolicy = require("./runtime-name-policy.cjs");
|
|
36
|
-
const { getDirName } = runtimeNamePolicy;
|
|
36
|
+
const { getDirName, hostBehaviorsFor } = runtimeNamePolicy;
|
|
37
37
|
const capabilityRegistry = require("./capability-registry.cjs");
|
|
38
38
|
const hostIntegration = require("./host-integration.cjs");
|
|
39
39
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
40
40
|
const frontmatterModule = require("./frontmatter.cjs");
|
|
41
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
41
42
|
const pattern_cjs_1 = require("./pattern.cjs");
|
|
42
43
|
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
43
44
|
// #2870: install-scope.cts is a leaf-tier sibling (imports only
|
|
@@ -93,24 +94,6 @@ function gsdVersion() {
|
|
|
93
94
|
cachedVersion = resolveVersionFrom(__dirname);
|
|
94
95
|
return cachedVersion;
|
|
95
96
|
}
|
|
96
|
-
/**
|
|
97
|
-
* Host-specific install behaviors declared on the runtime descriptor
|
|
98
|
-
* (capabilities/<runtime>/capability.json -> runtime.hostBehaviors). Mirrors
|
|
99
|
-
* bin/install.js's / install-engine.cts's `_hostBehaviors` (ADR-1239 / #2086
|
|
100
|
-
* / #2092). Returns {} for runtimes that declare none, so every behavior
|
|
101
|
-
* branch degrades to the generic path by default. Unlike the bin/install.js
|
|
102
|
-
* and install-engine.cts variants, this module already imports
|
|
103
|
-
* `capabilityRegistry` statically (see NON_CLAUDE_RUNTIMES below), so this
|
|
104
|
-
* reads it directly rather than re-require()-ing inside a try/catch.
|
|
105
|
-
*/
|
|
106
|
-
function _hostBehaviors(runtime) {
|
|
107
|
-
return ((capabilityRegistry &&
|
|
108
|
-
capabilityRegistry.runtimes &&
|
|
109
|
-
capabilityRegistry.runtimes[runtime] &&
|
|
110
|
-
capabilityRegistry.runtimes[runtime].runtime &&
|
|
111
|
-
capabilityRegistry.runtimes[runtime].runtime.hostBehaviors) ||
|
|
112
|
-
{});
|
|
113
|
-
}
|
|
114
97
|
/**
|
|
115
98
|
* Public accessor for the `hostBehaviors.agentFileExtension` descriptor field
|
|
116
99
|
* (ADR-1239 / #2099 / #2103). Returns the runtime's declared agent-file
|
|
@@ -122,7 +105,7 @@ function _hostBehaviors(runtime) {
|
|
|
122
105
|
* duplicating a hardcoded `runtime === 'copilot'` check (#2103 fold).
|
|
123
106
|
*/
|
|
124
107
|
function agentFileExtensionFor(runtime) {
|
|
125
|
-
const ext =
|
|
108
|
+
const ext = hostBehaviorsFor(runtime).agentFileExtension;
|
|
126
109
|
return typeof ext === 'string' ? ext : undefined;
|
|
127
110
|
}
|
|
128
111
|
const colorNameToHex = {
|
|
@@ -312,6 +295,61 @@ function buildKiloAgentPermissionBlock(claudeTools) {
|
|
|
312
295
|
}
|
|
313
296
|
return lines;
|
|
314
297
|
}
|
|
298
|
+
// OpenCode agent tool restrictions (#5338, ADR-5331 D4). Claude's `tools:` allowlist and
|
|
299
|
+
// `disallowedTools:` denylist become OpenCode `permission:` entries. The V1 `permission` form is the one
|
|
300
|
+
// written because OpenCode 2.x translates it automatically ("legacy agent frontmatter … is translated"),
|
|
301
|
+
// so one form serves both generations — verified: a `permission: {edit: deny, bash: deny}` agent drops the
|
|
302
|
+
// edit/write/shell tools from the model's tool list on 1.18.29 and 2.0.27. Only denials are emitted: an
|
|
303
|
+
// allowed tool keeps the user's own configured default instead of being forced to `allow`, and MCP tool
|
|
304
|
+
// entries are not restricted.
|
|
305
|
+
const claudeToOpencodePermission = {
|
|
306
|
+
Read: 'read',
|
|
307
|
+
Write: 'edit',
|
|
308
|
+
Edit: 'edit',
|
|
309
|
+
MultiEdit: 'edit',
|
|
310
|
+
NotebookEdit: 'edit',
|
|
311
|
+
Bash: 'bash',
|
|
312
|
+
Grep: 'grep',
|
|
313
|
+
Glob: 'glob',
|
|
314
|
+
WebFetch: 'webfetch',
|
|
315
|
+
WebSearch: 'websearch',
|
|
316
|
+
Task: 'task',
|
|
317
|
+
Agent: 'task',
|
|
318
|
+
Skill: 'skill',
|
|
319
|
+
SlashCommand: 'skill',
|
|
320
|
+
TodoWrite: 'todowrite',
|
|
321
|
+
};
|
|
322
|
+
const opencodeAgentPermissionOrder = ['read', 'edit', 'bash', 'grep', 'glob', 'webfetch', 'websearch', 'task', 'skill', 'todowrite'];
|
|
323
|
+
/**
|
|
324
|
+
* `permission:` frontmatter lines for an OpenCode agent, or `[]` when the agent declares no tool
|
|
325
|
+
* restriction (an agent with neither `tools` nor `disallowedTools` inherits everything, as in Claude).
|
|
326
|
+
*/
|
|
327
|
+
function buildOpencodeAgentPermissionBlock(allowedTools, disallowedTools) {
|
|
328
|
+
const allowed = new Set();
|
|
329
|
+
for (const tool of allowedTools) {
|
|
330
|
+
const mapped = claudeToOpencodePermission[tool];
|
|
331
|
+
if (mapped)
|
|
332
|
+
allowed.add(mapped);
|
|
333
|
+
}
|
|
334
|
+
const denied = new Set();
|
|
335
|
+
if (allowedTools.length > 0) {
|
|
336
|
+
for (const permission of opencodeAgentPermissionOrder) {
|
|
337
|
+
if (!allowed.has(permission))
|
|
338
|
+
denied.add(permission);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
for (const tool of disallowedTools) {
|
|
342
|
+
const mapped = claudeToOpencodePermission[tool];
|
|
343
|
+
if (mapped)
|
|
344
|
+
denied.add(mapped);
|
|
345
|
+
}
|
|
346
|
+
const lines = [];
|
|
347
|
+
for (const permission of opencodeAgentPermissionOrder) {
|
|
348
|
+
if (denied.has(permission))
|
|
349
|
+
lines.push(` ${permission}: deny`);
|
|
350
|
+
}
|
|
351
|
+
return lines.length > 0 ? ['permission:', ...lines] : [];
|
|
352
|
+
}
|
|
315
353
|
function replaceRelativePathReference(content, fromPath, toPath) {
|
|
316
354
|
const escapedPath = (0, pattern_cjs_1.escapeRegex)(fromPath);
|
|
317
355
|
return content.replace(new RegExp(`(^|[^A-Za-z0-9_./-])${escapedPath}`, 'g'), (_, prefix) => `${prefix}${toPath}`);
|
|
@@ -485,7 +523,7 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
|
|
|
485
523
|
// Hermes' SKILL.md spec lists `version` as a required frontmatter field.
|
|
486
524
|
// Track GSD's package version so Hermes' skill_view() reports a stable
|
|
487
525
|
// identifier per install.
|
|
488
|
-
if (runtime
|
|
526
|
+
if (hostBehaviorsFor(runtime).skillFrontmatterVersion) {
|
|
489
527
|
const version = gsdVersion();
|
|
490
528
|
if (version)
|
|
491
529
|
fm += `version: ${yamlQuote(version)}\n`;
|
|
@@ -495,7 +533,7 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
|
|
|
495
533
|
// runtimes that declare the flag so Claude/Hermes skill frontmatter is
|
|
496
534
|
// unchanged (they ignore the field, but we keep their output byte-stable).
|
|
497
535
|
// skillName is the `gsd-<stem>` dir name. (ADR-1239 / #2092)
|
|
498
|
-
if (
|
|
536
|
+
if (hostBehaviorsFor(runtime).skillPriorityFrontmatter) {
|
|
499
537
|
const stem = typeof skillName === 'string' && skillName.startsWith('gsd-')
|
|
500
538
|
? skillName.slice(4)
|
|
501
539
|
: skillName;
|
|
@@ -730,10 +768,13 @@ function appendAgentTools(content, grants) {
|
|
|
730
768
|
return content;
|
|
731
769
|
const eol = content.includes('\r\n') ? '\r\n' : '\n';
|
|
732
770
|
const lines = content.split(eol);
|
|
733
|
-
|
|
771
|
+
// The block is the one the one fence owner finds; `frontmatterEnd` is its closing fence's
|
|
772
|
+
// line index in `lines`.
|
|
773
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
774
|
+
if (!fence?.closed)
|
|
734
775
|
return content;
|
|
735
|
-
const frontmatterEnd =
|
|
736
|
-
if (frontmatterEnd
|
|
776
|
+
const frontmatterEnd = content.slice(0, fence.closingStart).split(eol).length - 1;
|
|
777
|
+
if (frontmatterEnd < 1)
|
|
737
778
|
return content;
|
|
738
779
|
const toolsIndex = lines.findIndex((line, index) => index < frontmatterEnd && /^tools:[ \t]*(.*)$/.test(line));
|
|
739
780
|
if (toolsIndex === -1)
|
|
@@ -1080,17 +1121,19 @@ function yamlIdentifier(value) {
|
|
|
1080
1121
|
}
|
|
1081
1122
|
return yamlQuote(text);
|
|
1082
1123
|
}
|
|
1124
|
+
/**
|
|
1125
|
+
* The frontmatter YAML (trimmed) and everything after the closing fence line's text, for the
|
|
1126
|
+
* block the one fence owner (`locateFrontmatterFence`) finds — so a `---` inside a value (a
|
|
1127
|
+
* description that mentions `a---b`) cannot end the block early.
|
|
1128
|
+
*/
|
|
1083
1129
|
function extractFrontmatterAndBody(content) {
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
}
|
|
1087
|
-
const endIndex = content.indexOf('---', 3);
|
|
1088
|
-
if (endIndex === -1) {
|
|
1130
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
1131
|
+
if (!fence?.closed) {
|
|
1089
1132
|
return { frontmatter: null, body: content };
|
|
1090
1133
|
}
|
|
1091
1134
|
return {
|
|
1092
|
-
frontmatter: content.
|
|
1093
|
-
body: content.
|
|
1135
|
+
frontmatter: content.slice(fence.openEnd, fence.bodyEnd).trim(),
|
|
1136
|
+
body: content.slice(fence.closingFenceEnd),
|
|
1094
1137
|
};
|
|
1095
1138
|
}
|
|
1096
1139
|
function extractFrontmatterField(frontmatter, fieldName) {
|
|
@@ -1539,7 +1582,7 @@ function convertClaudeCommandToTraeSkill(content, skillName) {
|
|
|
1539
1582
|
// is not formally documented (thin SPA docs) — descriptor-driven, single
|
|
1540
1583
|
// fixed GSD-side value (runtime.hostBehaviors.soloStageMetadata), inferred/
|
|
1541
1584
|
// best-effort.
|
|
1542
|
-
const soloStage =
|
|
1585
|
+
const soloStage = hostBehaviorsFor('trae').soloStageMetadata;
|
|
1543
1586
|
if (soloStage)
|
|
1544
1587
|
fm += `stage: ${soloStage}\n`;
|
|
1545
1588
|
fm += '---';
|
|
@@ -1955,23 +1998,21 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
1955
1998
|
convertedContent = convertedContent.replace(/subagent_type="general-purpose"/g, 'subagent_type="general"');
|
|
1956
1999
|
// Runtime-neutral agent name replacement (#766)
|
|
1957
2000
|
convertedContent = neutralizeAgentReferences(convertedContent, 'AGENTS.md');
|
|
1958
|
-
//
|
|
1959
|
-
|
|
2001
|
+
// The frontmatter block, as the one fence owner finds it (none → nothing to convert).
|
|
2002
|
+
const { frontmatter, body } = extractFrontmatterAndBody(convertedContent);
|
|
2003
|
+
if (frontmatter === null) {
|
|
1960
2004
|
return convertedContent;
|
|
1961
2005
|
}
|
|
1962
|
-
// Find the end of frontmatter
|
|
1963
|
-
const endIndex = convertedContent.indexOf('---', 3);
|
|
1964
|
-
if (endIndex === -1) {
|
|
1965
|
-
return convertedContent;
|
|
1966
|
-
}
|
|
1967
|
-
const frontmatter = convertedContent.substring(3, endIndex).trim();
|
|
1968
|
-
const body = convertedContent.substring(endIndex + 3);
|
|
1969
2006
|
// Parse frontmatter line by line (simple YAML parsing)
|
|
1970
2007
|
const lines = frontmatter.split('\n');
|
|
1971
2008
|
const newLines = [];
|
|
1972
2009
|
let inAllowedTools = false;
|
|
1973
2010
|
let inSkippedArray = false;
|
|
2011
|
+
let inAgentTools = false;
|
|
2012
|
+
let inDisallowedTools = false;
|
|
1974
2013
|
const allowedTools = [];
|
|
2014
|
+
const agentTools = [];
|
|
2015
|
+
const agentDisallowed = [];
|
|
1975
2016
|
for (const line of lines) {
|
|
1976
2017
|
const trimmed = line.trim();
|
|
1977
2018
|
// For agents: skip commented-out lines (e.g. hooks blocks)
|
|
@@ -1983,11 +2024,31 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
1983
2024
|
inAllowedTools = true;
|
|
1984
2025
|
continue;
|
|
1985
2026
|
}
|
|
2027
|
+
// Agents: collect the `tools:` allowlist and `disallowedTools:` denylist (block-list continuation
|
|
2028
|
+
// lines) so they can be rendered as `permission:` entries below.
|
|
2029
|
+
if (isAgent && (inAgentTools || inDisallowedTools)) {
|
|
2030
|
+
if (trimmed.startsWith('- ')) {
|
|
2031
|
+
const tool = decodeToolScalar(trimmed.substring(2));
|
|
2032
|
+
if (tool !== null)
|
|
2033
|
+
(inAgentTools ? agentTools : agentDisallowed).push(tool);
|
|
2034
|
+
continue;
|
|
2035
|
+
}
|
|
2036
|
+
if (trimmed && !trimmed.startsWith('-')) {
|
|
2037
|
+
inAgentTools = false;
|
|
2038
|
+
inDisallowedTools = false;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
1986
2041
|
// Detect inline tools: field (comma-separated string)
|
|
1987
2042
|
if (trimmed.startsWith('tools:')) {
|
|
1988
2043
|
if (isAgent) {
|
|
1989
|
-
|
|
1990
|
-
|
|
2044
|
+
const toolsValue = trimmed.substring(6).trim();
|
|
2045
|
+
// A comment-only value (`tools: # note`) is not inline content: read the block list instead.
|
|
2046
|
+
if (toolsValue && !toolsValue.startsWith('#')) {
|
|
2047
|
+
agentTools.push(...splitToolScalars(toolsValue).map(decodeToolScalar).filter((tool) => tool !== null));
|
|
2048
|
+
}
|
|
2049
|
+
else {
|
|
2050
|
+
inAgentTools = true;
|
|
2051
|
+
}
|
|
1991
2052
|
continue;
|
|
1992
2053
|
}
|
|
1993
2054
|
const toolsValue = trimmed.substring(6).trim();
|
|
@@ -1998,8 +2059,18 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
1998
2059
|
}
|
|
1999
2060
|
continue;
|
|
2000
2061
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2062
|
+
if (isAgent && trimmed.startsWith('disallowedTools:')) {
|
|
2063
|
+
const value = trimmed.substring(16).trim();
|
|
2064
|
+
if (value && !value.startsWith('#')) {
|
|
2065
|
+
agentDisallowed.push(...splitToolScalars(value).map(decodeToolScalar).filter((tool) => tool !== null));
|
|
2066
|
+
}
|
|
2067
|
+
else {
|
|
2068
|
+
inDisallowedTools = true;
|
|
2069
|
+
}
|
|
2070
|
+
continue;
|
|
2071
|
+
}
|
|
2072
|
+
// For agents: strip skills:, color:, memory:, maxTurns:, permissionMode:
|
|
2073
|
+
if (isAgent && /^(skills|color|memory|maxTurns|permissionMode):/.test(trimmed)) {
|
|
2003
2074
|
inSkippedArray = true;
|
|
2004
2075
|
continue;
|
|
2005
2076
|
}
|
|
@@ -2083,6 +2154,7 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
|
|
|
2083
2154
|
if (variant) {
|
|
2084
2155
|
newLines.push(frontmatterScalar('variant:', variant));
|
|
2085
2156
|
}
|
|
2157
|
+
newLines.push(...buildOpencodeAgentPermissionBlock(agentTools, agentDisallowed));
|
|
2086
2158
|
}
|
|
2087
2159
|
// For commands: add tools object if we had allowed-tools or tools
|
|
2088
2160
|
if (!isAgent && allowedTools.length > 0) {
|
|
@@ -2121,17 +2193,11 @@ function convertClaudeToKiloFrontmatter(content, { isAgent = false, modelOverrid
|
|
|
2121
2193
|
convertedContent = convertedContent.replace(/subagent_type="general-purpose"/g, 'subagent_type="general"');
|
|
2122
2194
|
// Runtime-neutral agent name replacement (#766)
|
|
2123
2195
|
convertedContent = neutralizeAgentReferences(convertedContent, 'AGENTS.md');
|
|
2124
|
-
//
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
}
|
|
2128
|
-
// Find the end of frontmatter
|
|
2129
|
-
const endIndex = convertedContent.indexOf('---', 3);
|
|
2130
|
-
if (endIndex === -1) {
|
|
2196
|
+
// The frontmatter block, as the one fence owner finds it (none → nothing to convert).
|
|
2197
|
+
const { frontmatter, body } = extractFrontmatterAndBody(convertedContent);
|
|
2198
|
+
if (frontmatter === null) {
|
|
2131
2199
|
return convertedContent;
|
|
2132
2200
|
}
|
|
2133
|
-
const frontmatter = convertedContent.substring(3, endIndex).trim();
|
|
2134
|
-
const body = convertedContent.substring(endIndex + 3);
|
|
2135
2201
|
// Parse frontmatter line by line (simple YAML parsing)
|
|
2136
2202
|
const lines = frontmatter.split('\n');
|
|
2137
2203
|
const newLines = [];
|
|
@@ -2526,7 +2592,7 @@ function convertClaudeAgentToTraeAgent(content) {
|
|
|
2526
2592
|
* forms to avoid double-rewriting the same substring.
|
|
2527
2593
|
*/
|
|
2528
2594
|
function convertClaudeAgentToQwenAgent(content) {
|
|
2529
|
-
const _b =
|
|
2595
|
+
const _b = hostBehaviorsFor('qwen').brandingRewrites || {};
|
|
2530
2596
|
let converted = content;
|
|
2531
2597
|
if (_b['CLAUDE.md'])
|
|
2532
2598
|
converted = converted.replace(/CLAUDE\.md/g, _b['CLAUDE.md']);
|
|
@@ -2591,18 +2657,14 @@ function convertClaudeAgentToZcodeAgent(content) {
|
|
|
2591
2657
|
// present. The unchanged scan below still preserves byte-identical content.
|
|
2592
2658
|
if (!content.includes('mcp__') && !content.includes('\\'))
|
|
2593
2659
|
return content;
|
|
2594
|
-
|
|
2595
|
-
|
|
2660
|
+
// The block is the one the one fence owner finds; unterminated (or absent) → leave verbatim.
|
|
2661
|
+
// The rewrite below re-joins lines on '\n', so a CRLF block is left verbatim too rather than
|
|
2662
|
+
// given mixed line endings.
|
|
2663
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
2664
|
+
if (!fence?.closed || fence.eol !== '\n')
|
|
2596
2665
|
return content;
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
if (lines[i] === '---') {
|
|
2600
|
-
fmEnd = i;
|
|
2601
|
-
break;
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
if (fmEnd === -1)
|
|
2605
|
-
return content; // unterminated frontmatter — leave verbatim
|
|
2666
|
+
const lines = content.split('\n');
|
|
2667
|
+
const fmEnd = content.slice(0, fence.closingStart).split('\n').length - 1;
|
|
2606
2668
|
const out = [];
|
|
2607
2669
|
let changed = false;
|
|
2608
2670
|
let i = 1;
|
|
@@ -2699,12 +2761,12 @@ function convertClaudeAgentToClineAgent(content) {
|
|
|
2699
2761
|
* rewrites applied automatically. A runtime with no `brandingRewrites`
|
|
2700
2762
|
* declared returns `content` unchanged (no rewrite table to apply).
|
|
2701
2763
|
*
|
|
2702
|
-
* Byte-identical to the inline loop's `else if (
|
|
2764
|
+
* Byte-identical to the inline loop's `else if (hostBehaviorsFor(runtime).brandingRewrites)`
|
|
2703
2765
|
* branch, including plain (non-word-boundary) `.replace(/\bClaude Code\b/g, ...)`
|
|
2704
2766
|
* semantics — J9.
|
|
2705
2767
|
*/
|
|
2706
2768
|
function applyAgentBrandingRewrites(content, runtime) {
|
|
2707
|
-
const _b =
|
|
2769
|
+
const _b = hostBehaviorsFor(runtime).brandingRewrites;
|
|
2708
2770
|
if (!_b)
|
|
2709
2771
|
return content;
|
|
2710
2772
|
let converted = content;
|
|
@@ -2890,7 +2952,7 @@ function projectRelativePrefixFromProjectRoot(projectRoot, resolvedTarget) {
|
|
|
2890
2952
|
* directory in a project-relative include: that directory was never created.
|
|
2891
2953
|
*/
|
|
2892
2954
|
function localIncludeDirName(runtime) {
|
|
2893
|
-
return
|
|
2955
|
+
return hostBehaviorsFor(runtime).localTargetIsProjectRoot === true ? undefined : getDirName(runtime);
|
|
2894
2956
|
}
|
|
2895
2957
|
/**
|
|
2896
2958
|
* #4377: the project-relative prefix for a local install, or `''` when the
|
|
@@ -3194,11 +3256,16 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3194
3256
|
// #1521: stamp runtime identity + use_worktrees=false for every non-Claude runtime
|
|
3195
3257
|
// before brand-specific path rewrites, so the replace operates on the pristine
|
|
3196
3258
|
// source line and is idempotent regardless of subsequent path substitutions.
|
|
3197
|
-
|
|
3259
|
+
// #5169: the descriptor declares which hosts skip the stamp
|
|
3260
|
+
// (`hostBehaviors.skipRuntimeDefaultsStamp`) and which rewrite profile applies
|
|
3261
|
+
// (`hostBehaviors.contentRewriteProfile`). The switch below is keyed by PROFILE
|
|
3262
|
+
// name, not runtime id, so two hosts that share a body share one case.
|
|
3263
|
+
const rewriteBehaviors = hostBehaviorsFor(runtime);
|
|
3264
|
+
if (!rewriteBehaviors.skipRuntimeDefaultsStamp) {
|
|
3198
3265
|
content = _stampNonClaudeRuntimeDefaults(content, runtime);
|
|
3199
3266
|
}
|
|
3200
|
-
switch (
|
|
3201
|
-
case '
|
|
3267
|
+
switch (rewriteBehaviors.contentRewriteProfile) {
|
|
3268
|
+
case 'slash-own-tilde':
|
|
3202
3269
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3203
3270
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3204
3271
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3206,7 +3273,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3206
3273
|
// #1515 stamp moved to _stampNonClaudeRuntimeDefaults (#1521 generalisation).
|
|
3207
3274
|
content = processAttribution(content, attribution);
|
|
3208
3275
|
break;
|
|
3209
|
-
case '
|
|
3276
|
+
case 'slash-bare-own-tilde':
|
|
3210
3277
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3211
3278
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3212
3279
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3218,7 +3285,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3218
3285
|
content = content.replace(/\$HOME\/\.cline\b/g, normalizedPathPrefix);
|
|
3219
3286
|
content = processAttribution(content, attribution);
|
|
3220
3287
|
break;
|
|
3221
|
-
case '
|
|
3288
|
+
case 'slash-lookahead-own-tilde':
|
|
3222
3289
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3223
3290
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3224
3291
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3228,7 +3295,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3228
3295
|
content = content.replace(/~\/\.cursor\//g, pathPrefix);
|
|
3229
3296
|
content = processAttribution(content, attribution);
|
|
3230
3297
|
break;
|
|
3231
|
-
case '
|
|
3298
|
+
case 'slash-lookahead-nested-own-devin': {
|
|
3232
3299
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3233
3300
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3234
3301
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3244,7 +3311,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3244
3311
|
content = processAttribution(content, attribution);
|
|
3245
3312
|
break;
|
|
3246
3313
|
}
|
|
3247
|
-
case '
|
|
3314
|
+
case 'slash-lookahead-own-derived': {
|
|
3248
3315
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3249
3316
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3250
3317
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3262,7 +3329,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3262
3329
|
content = processAttribution(content, attribution);
|
|
3263
3330
|
break;
|
|
3264
3331
|
}
|
|
3265
|
-
case '
|
|
3332
|
+
case 'slash-bare-own-derived':
|
|
3266
3333
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3267
3334
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3268
3335
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3275,7 +3342,7 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3275
3342
|
content = content.replace(new RegExp('~/' + (0, pattern_cjs_1.escapeRegex)(dirName) + '/', 'g'), pathPrefix);
|
|
3276
3343
|
content = processAttribution(content, attribution);
|
|
3277
3344
|
break;
|
|
3278
|
-
case '
|
|
3345
|
+
case 'slash-bare-own-tilde-bare':
|
|
3279
3346
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3280
3347
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3281
3348
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3288,13 +3355,14 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3288
3355
|
content = content.replace(/\$HOME\/\.codebuddy\b/g, normalizedPathPrefix);
|
|
3289
3356
|
content = processAttribution(content, attribution);
|
|
3290
3357
|
break;
|
|
3291
|
-
case '
|
|
3358
|
+
case 'attribution-only':
|
|
3292
3359
|
content = processAttribution(content, attribution);
|
|
3293
3360
|
break;
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3361
|
+
// claude and zcode share this profile. #4002: ZCode is a Claude-Code-shaped
|
|
3362
|
+
// host (dot-home `.zcode`, `@~`-ref expansion, `~/.zcode/...` documented
|
|
3363
|
+
// paths) whose commands install with `converter: null` — this pass is their
|
|
3364
|
+
// only chance to receive runtime-correct paths, including the tilde restore.
|
|
3365
|
+
case 'slash-tilde-restore':
|
|
3298
3366
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3299
3367
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3300
3368
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3308,12 +3376,15 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3308
3376
|
// brand VALUES (CLAUDE.md/Claude Code/.claude/ replacements) now read from
|
|
3309
3377
|
// runtime.hostBehaviors.brandingRewrites instead of hardcoded literals.
|
|
3310
3378
|
// EXACT regexes/order preserved — only the replacement values changed.
|
|
3311
|
-
|
|
3379
|
+
// qwen and hermes share this profile; their own dot-dir is derived from the
|
|
3380
|
+
// descriptor's `localConfigDir` (`getDirName`) rather than spelled per host.
|
|
3381
|
+
case 'branded-lookahead-own-derived': {
|
|
3312
3382
|
// Guarded (post-review #2092): brandingRewrites is undefined if the
|
|
3313
3383
|
// capability registry fails to load — degrade closed (skip the
|
|
3314
3384
|
// brand-literal replacements, still apply the non-branding path
|
|
3315
3385
|
// rewrites below) instead of throwing on `_b['CLAUDE.md']`.
|
|
3316
|
-
const _b =
|
|
3386
|
+
const _b = rewriteBehaviors.brandingRewrites;
|
|
3387
|
+
const _own = (0, pattern_cjs_1.escapeRegex)(dirName);
|
|
3317
3388
|
if (_b) {
|
|
3318
3389
|
content = content.replace(/CLAUDE\.md/g, _b['CLAUDE.md']);
|
|
3319
3390
|
// #2284(b): skips <runtime_compatibility> comparison-table content (protected region).
|
|
@@ -3321,46 +3392,21 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3321
3392
|
}
|
|
3322
3393
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3323
3394
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3324
|
-
content = content.replace(
|
|
3325
|
-
content = content.replace(
|
|
3395
|
+
content = content.replace(new RegExp('~/' + _own + '/', 'g'), pathPrefix);
|
|
3396
|
+
content = content.replace(new RegExp('\\$HOME/' + _own + '/', 'g'), pathPrefix);
|
|
3326
3397
|
content = content.replace(/~\/\.claude(?![\w-])/g, normalizedPathPrefix);
|
|
3327
3398
|
content = content.replace(/\$HOME\/\.claude(?![\w-])/g, normalizedPathPrefix);
|
|
3328
|
-
content = content.replace(
|
|
3329
|
-
content = content.replace(
|
|
3399
|
+
content = content.replace(new RegExp('~/' + _own + '(?![\\w-])', 'g'), normalizedPathPrefix);
|
|
3400
|
+
content = content.replace(new RegExp('\\$HOME/' + _own + '(?![\\w-])', 'g'), normalizedPathPrefix);
|
|
3330
3401
|
if (_b) {
|
|
3331
3402
|
content = content.replace(/\.claude\//g, _b['.claude/']);
|
|
3332
3403
|
}
|
|
3333
3404
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
3334
|
-
content = content.replace(
|
|
3405
|
+
content = content.replace(new RegExp('\\./' + _own + '/', 'g'), `./${dirName}/`);
|
|
3335
3406
|
content = processAttribution(content, attribution);
|
|
3336
3407
|
break;
|
|
3337
3408
|
}
|
|
3338
|
-
case '
|
|
3339
|
-
// Guarded (post-review #2092): see qwen case above — same degrade-closed
|
|
3340
|
-
// rationale.
|
|
3341
|
-
const _b = _hostBehaviors(runtime).brandingRewrites;
|
|
3342
|
-
if (_b) {
|
|
3343
|
-
content = content.replace(/CLAUDE\.md/g, _b['CLAUDE.md']);
|
|
3344
|
-
// #2284(b): skips <runtime_compatibility> comparison-table content (protected region).
|
|
3345
|
-
content = applyClaudeCodeBrandSwap(content, _b['Claude Code']);
|
|
3346
|
-
}
|
|
3347
|
-
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3348
|
-
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3349
|
-
content = content.replace(/~\/\.hermes\//g, pathPrefix);
|
|
3350
|
-
content = content.replace(/\$HOME\/\.hermes\//g, pathPrefix);
|
|
3351
|
-
content = content.replace(/~\/\.claude(?![\w-])/g, normalizedPathPrefix);
|
|
3352
|
-
content = content.replace(/\$HOME\/\.claude(?![\w-])/g, normalizedPathPrefix);
|
|
3353
|
-
content = content.replace(/~\/\.hermes(?![\w-])/g, normalizedPathPrefix);
|
|
3354
|
-
content = content.replace(/\$HOME\/\.hermes(?![\w-])/g, normalizedPathPrefix);
|
|
3355
|
-
if (_b) {
|
|
3356
|
-
content = content.replace(/\.claude\//g, _b['.claude/']);
|
|
3357
|
-
}
|
|
3358
|
-
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
3359
|
-
content = content.replace(/\.\/\.hermes\//g, `./${dirName}/`);
|
|
3360
|
-
content = processAttribution(content, attribution);
|
|
3361
|
-
break;
|
|
3362
|
-
}
|
|
3363
|
-
case 'kimi':
|
|
3409
|
+
case 'slash-bare':
|
|
3364
3410
|
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3365
3411
|
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3366
3412
|
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
@@ -3369,22 +3415,8 @@ function _applyRuntimeRewritesInner(content, runtime, pathPrefix, isGlobal = fal
|
|
|
3369
3415
|
content = content.replace(/\.\/\.claude\b/g, `./${dirName}`);
|
|
3370
3416
|
content = processAttribution(content, attribution);
|
|
3371
3417
|
break;
|
|
3372
|
-
case 'zcode':
|
|
3373
|
-
// #4002: ZCode is a Claude-Code-shaped host (dot-home `.zcode`, `@~`-ref
|
|
3374
|
-
// expansion, `~/.zcode/...` documented paths) whose commands install with
|
|
3375
|
-
// `converter: null` — this pass is their only chance to receive
|
|
3376
|
-
// runtime-correct paths. Same shape as `claude`, including the tilde
|
|
3377
|
-
// restore: the tilde form is what ZCode expands and what its docs use.
|
|
3378
|
-
// `${_GSD_RUNTIME_ROOT}/.claude/…` matches none of these regexes and
|
|
3379
|
-
// survives as the project-local fallback, exactly as on every sibling.
|
|
3380
|
-
content = content.replace(/~\/\.claude\//g, pathPrefix);
|
|
3381
|
-
content = content.replace(/\$HOME\/\.claude\//g, pathPrefix);
|
|
3382
|
-
content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
|
|
3383
|
-
content = restoreClaudeGlobalAtRefTilde(content, pathPrefix);
|
|
3384
|
-
content = processAttribution(content, attribution);
|
|
3385
|
-
break;
|
|
3386
3418
|
default:
|
|
3387
|
-
//
|
|
3419
|
+
// No profile declared — no rewrites (OpenCode/Kilo handled by their own install path).
|
|
3388
3420
|
break;
|
|
3389
3421
|
}
|
|
3390
3422
|
return content;
|
|
@@ -3450,7 +3482,7 @@ function applyRuntimeContentRewritesForCommandsInPlace(stagedDir, runtime, pathP
|
|
|
3450
3482
|
content = _applyRuntimeRewrites(content, runtime, pathPrefix, isGlobal, attribution);
|
|
3451
3483
|
// #2097 (ADR-1239): descriptor-driven — commandBodyConverter name comes
|
|
3452
3484
|
// from runtime.hostBehaviors instead of a hardcoded runtime-name branch.
|
|
3453
|
-
const _cmdConv =
|
|
3485
|
+
const _cmdConv = hostBehaviorsFor(runtime).commandBodyConverter;
|
|
3454
3486
|
if (_cmdConv && COMMAND_BODY_CONVERTERS[_cmdConv]) {
|
|
3455
3487
|
content = COMMAND_BODY_CONVERTERS[_cmdConv](content);
|
|
3456
3488
|
}
|
|
@@ -3539,7 +3571,7 @@ function rewriteStagedSkillBodies(stagedDir, opts) {
|
|
|
3539
3571
|
// no skills-kind entry at local scope, so this is already structurally
|
|
3540
3572
|
// scoped to global (row 23) — the explicit isGlobal check is defense-in-depth
|
|
3541
3573
|
// against that descriptor wiring ever changing.
|
|
3542
|
-
if (runtime
|
|
3574
|
+
if (hostBehaviorsFor(runtime).specRootSkillPass && isGlobal) {
|
|
3543
3575
|
applySpecRootReferenceToStagedSkills(stagedDir);
|
|
3544
3576
|
}
|
|
3545
3577
|
}
|
|
@@ -3591,7 +3623,7 @@ function rewriteStagedCommandBodies(stagedDir, opts) {
|
|
|
3591
3623
|
* @param cmdNames gsd command names from readGsdCommandNames()
|
|
3592
3624
|
*/
|
|
3593
3625
|
function normalizeAgentBodyForRuntime(content, runtime, cmdNames) {
|
|
3594
|
-
if (
|
|
3626
|
+
if (hostBehaviorsFor(runtime).hyphenNameAgentBody !== true)
|
|
3595
3627
|
return content;
|
|
3596
3628
|
return transformContentToHyphen(content, cmdNames);
|
|
3597
3629
|
}
|
|
@@ -3621,7 +3653,7 @@ function normalizeAgentBodyForRuntime(content, runtime, cmdNames) {
|
|
|
3621
3653
|
* @returns content with path-prefix rewrites applied (or unchanged for noPathRewrite runtimes, e.g. copilot)
|
|
3622
3654
|
*/
|
|
3623
3655
|
function applyAgentPathRewrites(content, runtime, pathPrefix) {
|
|
3624
|
-
if (
|
|
3656
|
+
if (hostBehaviorsFor(runtime).noPathRewrite === true)
|
|
3625
3657
|
return content;
|
|
3626
3658
|
// #4377: the agents pipeline is the third emit path that substitutes this
|
|
3627
3659
|
// prefix (skills/commands via _applyRuntimeRewrites, the gsd-core spec tree
|
|
@@ -3663,7 +3695,7 @@ function applyAgentPathRewritesInner(content, runtime, pathPrefix) {
|
|
|
3663
3695
|
// anchored to the exact prefix string it is handed — so `restore(pathPrefix)`
|
|
3664
3696
|
// fixes `@$HOME/.claude/x` and leaves a bare `@$HOME/.claude` broken. The
|
|
3665
3697
|
// normalized form is a PREFIX of both, so one call covers both.
|
|
3666
|
-
if (runtime
|
|
3698
|
+
if (hostBehaviorsFor(runtime).restoreAtRefTildeInAgents) {
|
|
3667
3699
|
content = restoreClaudeGlobalAtRefTilde(content, normalizedPathPrefix);
|
|
3668
3700
|
}
|
|
3669
3701
|
return content;
|
|
@@ -3687,8 +3719,8 @@ function deriveAgentName(fileName) {
|
|
|
3687
3719
|
* `applyAgentFrontmatterExtensions` below for the orchestration that calls it.
|
|
3688
3720
|
*
|
|
3689
3721
|
* The function:
|
|
3690
|
-
* -
|
|
3691
|
-
* otherwise LF).
|
|
3722
|
+
* - Reads the block the one fence owner (`locateFrontmatterFence`) finds, and
|
|
3723
|
+
* its EOL (CRLF if the opening `---` line ends with \r\n, otherwise LF).
|
|
3692
3724
|
* - Skips injection if an `effort:` key already exists in the frontmatter
|
|
3693
3725
|
* (idempotent).
|
|
3694
3726
|
* - Inserts `effort: <value>` immediately before the closing `---` delimiter,
|
|
@@ -3697,19 +3729,15 @@ function deriveAgentName(fileName) {
|
|
|
3697
3729
|
* - Returns the original content unchanged when no YAML frontmatter is found.
|
|
3698
3730
|
*/
|
|
3699
3731
|
function injectEffortFrontmatter(content, effortValue) {
|
|
3700
|
-
const
|
|
3701
|
-
|
|
3702
|
-
const match = fmRe.exec(content);
|
|
3703
|
-
if (!match)
|
|
3732
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
3733
|
+
if (!fence?.closed)
|
|
3704
3734
|
return content; // no YAML frontmatter — leave unchanged
|
|
3705
|
-
const fmBody =
|
|
3735
|
+
const fmBody = content.slice(fence.openEnd, fence.closingStart); // content between the two fences
|
|
3706
3736
|
if (/^effort:/m.test(fmBody))
|
|
3707
3737
|
return content;
|
|
3708
|
-
const
|
|
3709
|
-
const
|
|
3710
|
-
|
|
3711
|
-
const after = content.slice(closingStart);
|
|
3712
|
-
return `${before}effort: ${effortValue}${eol}${after}`;
|
|
3738
|
+
const before = content.slice(0, fence.closingStart);
|
|
3739
|
+
const after = content.slice(fence.closingStart);
|
|
3740
|
+
return `${before}effort: ${effortValue}${fence.eol}${after}`;
|
|
3713
3741
|
}
|
|
3714
3742
|
/**
|
|
3715
3743
|
* #767 — Inject `disallowedTools: <value>` into the YAML frontmatter of a
|
|
@@ -3719,19 +3747,15 @@ function injectEffortFrontmatter(content, effortValue) {
|
|
|
3719
3747
|
* frontmatter keys. Relocated verbatim from bin/install.js (#2875 Part 2).
|
|
3720
3748
|
*/
|
|
3721
3749
|
function injectDisallowedToolsFrontmatter(content, disallowedValue) {
|
|
3722
|
-
const
|
|
3723
|
-
|
|
3724
|
-
const match = fmRe.exec(content);
|
|
3725
|
-
if (!match)
|
|
3750
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
3751
|
+
if (!fence?.closed)
|
|
3726
3752
|
return content; // no YAML frontmatter — leave unchanged
|
|
3727
|
-
const fmBody =
|
|
3753
|
+
const fmBody = content.slice(fence.openEnd, fence.closingStart); // content between the two fences
|
|
3728
3754
|
if (/^disallowedTools:/m.test(fmBody))
|
|
3729
3755
|
return content;
|
|
3730
|
-
const
|
|
3731
|
-
const
|
|
3732
|
-
|
|
3733
|
-
const after = content.slice(closingStart);
|
|
3734
|
-
return `${before}disallowedTools: ${disallowedValue}${eol}${after}`;
|
|
3756
|
+
const before = content.slice(0, fence.closingStart);
|
|
3757
|
+
const after = content.slice(fence.closingStart);
|
|
3758
|
+
return `${before}disallowedTools: ${disallowedValue}${fence.eol}${after}`;
|
|
3735
3759
|
}
|
|
3736
3760
|
// #767 — Read-only verifier/auditor agents get a Claude-Code disallowedTools deny-list.
|
|
3737
3761
|
// Group A (pure read-only) deny Write,Edit,MultiEdit. Group B report-writers Write one
|
|
@@ -3757,7 +3781,7 @@ const READONLY_AGENT_DISALLOWED_TOOLS = {
|
|
|
3757
3781
|
* OpenCode/Qwen/Hermes reject unknown frontmatter keys.
|
|
3758
3782
|
*
|
|
3759
3783
|
* Byte-identical to the inline agent loop's
|
|
3760
|
-
* `if ((
|
|
3784
|
+
* `if ((hostBehaviorsFor(runtime).agentFrontmatterExtensions || []).includes('effort'))`
|
|
3761
3785
|
* block (bin/install.js): both the effort injection AND the disallowedTools
|
|
3762
3786
|
* injection are gated behind the SAME `'effort'` extension flag — there is no
|
|
3763
3787
|
* separate `'disallowedTools'` extension key, mirroring the loop exactly.
|
|
@@ -3772,7 +3796,7 @@ const READONLY_AGENT_DISALLOWED_TOOLS = {
|
|
|
3772
3796
|
* @param targetDir install root — resolves .planning/config.json + ~/.gsd/defaults.json
|
|
3773
3797
|
*/
|
|
3774
3798
|
function applyAgentFrontmatterExtensions(content, { runtime, agentName, targetDir }) {
|
|
3775
|
-
const extensions =
|
|
3799
|
+
const extensions = hostBehaviorsFor(runtime).agentFrontmatterExtensions || [];
|
|
3776
3800
|
if (!extensions.includes('effort'))
|
|
3777
3801
|
return content;
|
|
3778
3802
|
let result = content;
|
|
@@ -3882,6 +3906,7 @@ module.exports = {
|
|
|
3882
3906
|
convertClaudeToOpencodeFrontmatter,
|
|
3883
3907
|
convertClaudeToKiloFrontmatter,
|
|
3884
3908
|
_decodeToolScalar: decodeToolScalar,
|
|
3909
|
+
_buildOpencodeAgentPermissionBlock: buildOpencodeAgentPermissionBlock,
|
|
3885
3910
|
_splitToolScalars: splitToolScalars,
|
|
3886
3911
|
readGsdCommandNames,
|
|
3887
3912
|
transformContentToHyphen,
|