@opengsd/gsd-core 1.10.0 → 1.12.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 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-debug-session-manager.md +12 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-dom-verifier.md +169 -0
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +22 -14
- package/agents/gsd-framework-selector.md +1 -3
- package/agents/gsd-intel-updater.md +1 -1
- package/agents/gsd-mempalace-curator.md +5 -3
- package/agents/gsd-pattern-mapper.md +11 -0
- package/agents/gsd-phase-researcher.md +23 -2
- package/agents/gsd-plan-checker.md +50 -53
- package/agents/gsd-planner.md +50 -50
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.md +2 -2
- package/agents/gsd-roadmapper.md +15 -11
- package/agents/gsd-ui-checker.md +63 -4
- package/agents/gsd-ui-researcher.md +41 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +13 -4
- package/bin/install.js +1448 -1103
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/discuss-phase.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/import.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +9 -5
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +1035 -138
- package/gsd-core/bin/lib/active-workstream-store.cjs +146 -22
- package/gsd-core/bin/lib/adr-parser.cjs +13 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +392 -32
- package/gsd-core/bin/lib/api-coverage.cjs +33 -14
- package/gsd-core/bin/lib/artifacts.cjs +5 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +32 -15
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +1026 -268
- package/gsd-core/bin/lib/broken-windows.cjs +306 -28
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-lock.cjs +10 -4
- package/gsd-core/bin/lib/capability-registry.cjs +845 -130
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-state.cjs +18 -3
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +700 -40
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +216 -42
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/cli-exit.cjs +496 -10
- package/gsd-core/bin/lib/code-review-depth.cjs +288 -0
- package/gsd-core/bin/lib/codex-agent-toml.cjs +735 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-arg-projection.cjs +144 -14
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/command-routing-hub.cjs +31 -2
- package/gsd-core/bin/lib/commands.cjs +1172 -108
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1192 -0
- package/gsd-core/bin/lib/config-loader.cjs +187 -23
- package/gsd-core/bin/lib/config.cjs +102 -3
- package/gsd-core/bin/lib/configuration.cjs +129 -37
- package/gsd-core/bin/lib/core-utils.cjs +208 -33
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/edge-probe.cjs +9 -1
- package/gsd-core/bin/lib/estimate-cli.cjs +55 -11
- package/gsd-core/bin/lib/exit-code-registry.cjs +98 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +899 -229
- package/gsd-core/bin/lib/gap-checker.cjs +95 -10
- package/gsd-core/bin/lib/git-base-branch.cjs +276 -39
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +149 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +268 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +187 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +451 -0
- package/gsd-core/bin/lib/host-integration.cjs +39 -6
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +118 -21
- package/gsd-core/bin/lib/init.cjs +439 -168
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +811 -259
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +235 -0
- package/gsd-core/bin/lib/install-profiles.cjs +212 -61
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations/010-antigravity-retire-confighome-artifacts.cjs +169 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +148 -38
- package/gsd-core/bin/lib/intel.cjs +101 -26
- package/gsd-core/bin/lib/io.cjs +170 -15
- package/gsd-core/bin/lib/learnings.cjs +85 -14
- package/gsd-core/bin/lib/legacy-cleanup.cjs +8 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +183 -22
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +842 -73
- package/gsd-core/bin/lib/model-catalog.cjs +232 -16
- package/gsd-core/bin/lib/model-resolver.cjs +193 -68
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/onboard-projection.cjs +5 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +18 -9
- package/gsd-core/bin/lib/phase-id.cjs +514 -40
- package/gsd-core/bin/lib/phase-lifecycle.cjs +52 -19
- package/gsd-core/bin/lib/phase-locator.cjs +262 -34
- package/gsd-core/bin/lib/phase.cjs +1038 -214
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-document.cjs +263 -0
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +98 -3
- package/gsd-core/bin/lib/planning-command-router.cjs +61 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +1168 -0
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +894 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +112 -6
- package/gsd-core/bin/lib/probe-core.cjs +5 -2
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/profile-pipeline-command-router.cjs +50 -7
- package/gsd-core/bin/lib/profile-pipeline.cjs +6 -3
- package/gsd-core/bin/lib/real-home-guard.cjs +419 -0
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +766 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +22 -13
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +59 -11
- package/gsd-core/bin/lib/roadmap-parser.cjs +1006 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +442 -96
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +702 -52
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +459 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +402 -58
- package/gsd-core/bin/lib/runtime-identity.cjs +234 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +96 -8
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +342 -7
- package/gsd-core/bin/lib/smart-entry.cjs +133 -23
- package/gsd-core/bin/lib/spec-section.cjs +12 -7
- package/gsd-core/bin/lib/state-command-router.cjs +52 -19
- package/gsd-core/bin/lib/state-contract.cjs +359 -0
- package/gsd-core/bin/lib/state-document.cjs +338 -8
- package/gsd-core/bin/lib/state-md-schema.cjs +221 -0
- package/gsd-core/bin/lib/state-transition.cjs +846 -176
- package/gsd-core/bin/lib/state.cjs +2589 -369
- package/gsd-core/bin/lib/surface.cjs +33 -11
- package/gsd-core/bin/lib/task-command-router.cjs +111 -1
- package/gsd-core/bin/lib/task-content-resolution.cjs +368 -0
- package/gsd-core/bin/lib/teams-status.cjs +4 -1
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +67 -23
- package/gsd-core/bin/lib/uat.cjs +1761 -167
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +9 -1
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +51 -12
- package/gsd-core/bin/lib/unusable-input.cjs +37 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate-command-router.cjs +2 -2
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +75 -0
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +3014 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +272 -9
- package/gsd-core/bin/lib/verify-command-grounding.cjs +846 -0
- package/gsd-core/bin/lib/verify.cjs +453 -918
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream-name-policy.cjs +25 -4
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +66 -12
- package/gsd-core/bin/lib/worktree-safety.cjs +341 -18
- package/gsd-core/bin/shared/config-defaults.manifest.json +8 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +12 -1
- package/gsd-core/bin/shared/exit-codes.json +8 -0
- package/gsd-core/bin/shared/exit-codes.sh +20 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -1
- package/gsd-core/references/agent-contracts.md +44 -26
- package/gsd-core/references/api-coverage.md +24 -2
- package/gsd-core/references/autonomous-smart-discuss.md +3 -3
- package/gsd-core/references/checkpoints.md +39 -21
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/decimal-phase-calculation.md +5 -5
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/edge-probe.md +8 -0
- package/gsd-core/references/execute-mvp-tdd.md +4 -6
- package/gsd-core/references/execute-phase-between-wave-reset.md +15 -14
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +17 -11
- package/gsd-core/references/failing-direction.md +78 -0
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-integration.md +5 -5
- package/gsd-core/references/git-planning-commit.md +5 -4
- package/gsd-core/references/gsd-run-resolver.md +1 -1
- package/gsd-core/references/loop-hook-dispatch.md +61 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/nyquist-compliance.md +74 -0
- package/gsd-core/references/offer-next.md +3 -5
- package/gsd-core/references/phase-argument-parsing.md +3 -3
- package/gsd-core/references/planner-failing-direction.md +53 -0
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-human-verify-mode.md +15 -1
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planner-revision.md +1 -1
- package/gsd-core/references/planner-verify-command-grounding.md +17 -0
- package/gsd-core/references/planning-config.md +44 -13
- package/gsd-core/references/reviewer-instances.md +31 -0
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/runtime-aware-dispatch.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/tdd.md +1 -3
- package/gsd-core/references/ui-brand.md +65 -21
- package/gsd-core/references/ui-consideration-probe.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +5 -5
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-command-path-resolvability.md +42 -0
- package/gsd-core/references/verify-mvp-mode.md +2 -2
- package/gsd-core/references/workstream-flag.md +33 -17
- package/gsd-core/templates/README.md +1 -1
- package/gsd-core/templates/SECURITY.md +3 -3
- package/gsd-core/templates/UI-SPEC.md +25 -3
- package/gsd-core/templates/VALIDATION.md +3 -3
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +5 -4
- package/gsd-core/templates/state.md +11 -4
- package/gsd-core/templates/verification-report.md +9 -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 +3 -3
- package/gsd-core/workflows/add-tests.md +3 -8
- package/gsd-core/workflows/add-todo.md +1 -1
- package/gsd-core/workflows/ai-integration-phase.md +13 -20
- package/gsd-core/workflows/audit-fix.md +12 -3
- package/gsd-core/workflows/audit-milestone.md +9 -9
- package/gsd-core/workflows/audit-uat.md +17 -2
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +2 -2
- package/gsd-core/workflows/autonomous.md +11 -27
- package/gsd-core/workflows/check-todos.md +1 -1
- package/gsd-core/workflows/cleanup.md +64 -5
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +14 -4
- package/gsd-core/workflows/code-review-fix.md +38 -11
- package/gsd-core/workflows/code-review.md +159 -52
- package/gsd-core/workflows/complete-milestone.md +151 -23
- package/gsd-core/workflows/debug.md +12 -8
- package/gsd-core/workflows/diagnose-issues.md +47 -15
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -8
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase/modes/text.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +1 -3
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +3 -6
- package/gsd-core/workflows/docs-update.md +5 -4
- package/gsd-core/workflows/edit-phase.md +27 -2
- package/gsd-core/workflows/eval-review.md +7 -14
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +142 -15
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +1 -1
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +24 -4
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/protected-branch.md +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +39 -0
- package/gsd-core/workflows/execute-phase.md +72 -100
- package/gsd-core/workflows/execute-plan.md +52 -15
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/extract-learnings.md +1 -1
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/forensics.md +1 -1
- package/gsd-core/workflows/graduation.md +5 -5
- package/gsd-core/workflows/health.md +76 -10
- package/gsd-core/workflows/import.md +18 -15
- package/gsd-core/workflows/inbox.md +4 -5
- package/gsd-core/workflows/ingest-docs.md +49 -16
- package/gsd-core/workflows/insert-phase.md +5 -5
- package/gsd-core/workflows/list-seeds.md +5 -3
- package/gsd-core/workflows/list-workspaces.md +1 -1
- package/gsd-core/workflows/manager.md +12 -23
- package/gsd-core/workflows/map-codebase.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +1 -1
- package/gsd-core/workflows/mvp-phase.md +8 -5
- package/gsd-core/workflows/new-milestone.md +22 -29
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +1 -1
- package/gsd-core/workflows/new-project.md +26 -40
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +14 -2
- package/gsd-core/workflows/pause-work.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -4
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +3 -3
- package/gsd-core/workflows/plan-phase.md +162 -59
- package/gsd-core/workflows/plan-review-convergence.md +96 -11
- package/gsd-core/workflows/plant-seed.md +2 -2
- package/gsd-core/workflows/pr-branch.md +187 -51
- package/gsd-core/workflows/profile-user.md +16 -14
- package/gsd-core/workflows/progress.md +61 -18
- package/gsd-core/workflows/quick/steps/discussion-phase.md +1 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +5 -7
- package/gsd-core/workflows/quick/steps/quick-verification.md +28 -9
- package/gsd-core/workflows/quick/steps/research-phase.md +4 -6
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +3 -3
- package/gsd-core/workflows/quick.md +55 -44
- package/gsd-core/workflows/remove-phase.md +4 -4
- package/gsd-core/workflows/remove-workspace.md +2 -2
- package/gsd-core/workflows/resume-project.md +8 -12
- package/gsd-core/workflows/review.md +219 -20
- package/gsd-core/workflows/scan.md +1 -1
- package/gsd-core/workflows/secure-phase.md +3 -3
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings-advanced.md +7 -9
- package/gsd-core/workflows/settings-integrations.md +64 -31
- package/gsd-core/workflows/settings.md +69 -7
- package/gsd-core/workflows/ship.md +116 -50
- package/gsd-core/workflows/sketch-wrap-up.md +11 -17
- package/gsd-core/workflows/sketch.md +12 -18
- package/gsd-core/workflows/smart-entry.md +3 -5
- package/gsd-core/workflows/spec-phase.md +53 -13
- package/gsd-core/workflows/spike-wrap-up.md +7 -11
- package/gsd-core/workflows/spike.md +20 -31
- package/gsd-core/workflows/stats.md +2 -2
- package/gsd-core/workflows/sync-skills.md +64 -9
- package/gsd-core/workflows/thread.md +11 -7
- package/gsd-core/workflows/transition.md +49 -14
- package/gsd-core/workflows/ui-phase.md +15 -21
- package/gsd-core/workflows/ui-review.md +8 -12
- package/gsd-core/workflows/ultraplan-phase.md +5 -13
- package/gsd-core/workflows/undo.md +8 -16
- package/gsd-core/workflows/update.md +7 -11
- package/gsd-core/workflows/validate-phase.md +3 -3
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +25 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +1 -1
- package/gsd-core/workflows/verify-work.md +66 -25
- package/hooks/dist/gsd-agent-isolation-guard.js +158 -30
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-config-reload.js +18 -12
- package/hooks/dist/gsd-context-monitor.js +19 -10
- package/hooks/dist/gsd-cursor-post-tool.js +3 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +2 -3
- package/hooks/dist/gsd-cursor-session-start.js +2 -1
- package/hooks/dist/gsd-cursor-stop.js +2 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +83 -3
- package/hooks/dist/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/dist/gsd-ensure-canonical-path.js +2 -1
- package/hooks/dist/gsd-graphify-update.sh +22 -18
- package/hooks/dist/gsd-node-runner.sh +76 -0
- package/hooks/dist/gsd-phase-boundary.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +37 -27
- package/hooks/dist/gsd-read-guard.js +16 -7
- package/hooks/dist/gsd-read-injection-scanner.js +55 -32
- package/hooks/dist/gsd-session-state.sh +1 -0
- package/hooks/dist/gsd-statusline.js +231 -24
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-validate-commit.sh +80 -6
- package/hooks/dist/gsd-windsurf-pre-command.js +16 -11
- package/hooks/dist/gsd-windsurf-pre-write.js +22 -13
- package/hooks/dist/gsd-workflow-guard.js +162 -46
- package/hooks/dist/gsd-worktree-path-guard.js +36 -21
- package/hooks/dist/gsd-write-guard.js +35 -25
- package/hooks/dist/lib/cli-exit.js +560 -0
- package/hooks/dist/lib/exit-code-registry.js +98 -0
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/git-probe.js +84 -0
- package/hooks/dist/lib/hook-exit.js +81 -0
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/dist/managed-hooks-registry.cjs +3 -0
- package/hooks/gsd-agent-isolation-guard.js +158 -30
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-config-reload.js +18 -12
- package/hooks/gsd-context-monitor.js +19 -10
- package/hooks/gsd-cursor-post-tool.js +3 -1
- package/hooks/gsd-cursor-pre-tool.js +2 -3
- package/hooks/gsd-cursor-session-start.js +2 -1
- package/hooks/gsd-cursor-stop.js +2 -1
- package/hooks/gsd-cursor-subagent-start.js +83 -3
- package/hooks/gsd-cursor-subagent-stop.js +6 -3
- package/hooks/gsd-ensure-canonical-path.js +2 -1
- package/hooks/gsd-graphify-update.sh +22 -18
- package/hooks/gsd-node-runner.sh +76 -0
- package/hooks/gsd-phase-boundary.sh +1 -0
- package/hooks/gsd-prompt-guard.js +37 -27
- package/hooks/gsd-read-guard.js +16 -7
- package/hooks/gsd-read-injection-scanner.js +55 -32
- package/hooks/gsd-session-state.sh +1 -0
- package/hooks/gsd-statusline.js +231 -24
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-validate-commit.sh +80 -6
- package/hooks/gsd-windsurf-pre-command.js +16 -11
- package/hooks/gsd-windsurf-pre-write.js +22 -13
- package/hooks/gsd-workflow-guard.js +162 -46
- package/hooks/gsd-worktree-path-guard.js +36 -21
- package/hooks/gsd-write-guard.js +35 -25
- package/hooks/lib/cli-exit.js +560 -0
- package/hooks/lib/exit-code-registry.js +98 -0
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/git-probe.js +84 -0
- package/hooks/lib/hook-exit.js +81 -0
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/hooks/managed-hooks-registry.cjs +3 -0
- package/package.json +28 -11
- package/pi/gsd.cjs +19 -5
- package/scripts/base64-scan.sh +74 -12
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/build-hooks.js +5 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/check-glossary-refs.cjs +77 -15
- package/scripts/check-mutation-score-ratchet.cjs +156 -0
- package/scripts/ci-check-job-near-cap.cjs +49 -0
- package/scripts/ci-pr-mergeability.cjs +262 -0
- package/scripts/ci-test-scope.cjs +64 -14
- package/scripts/ci-timeout-report.cjs +230 -0
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/docs-guard-registry.cjs +396 -0
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +11 -21
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-exit-code-docs.cjs +318 -0
- package/scripts/gen-exit-code-registry.cjs +891 -0
- package/scripts/gen-features.cjs +836 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-hooks-cli-exit.cjs +239 -0
- package/scripts/gen-install-tree-fixtures.cjs +2 -2
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +138 -25
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-scripts-cli-exit.cjs +185 -0
- package/scripts/gen-state-md-docs.cjs +727 -0
- package/scripts/{test-failure-reasons.cjs → gsd-test-gate-reasons.cjs} +6 -0
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/ci-job-timing.cjs +72 -0
- package/scripts/lib/cli-exit.cjs +546 -44
- package/scripts/lib/drift-scan.cjs +308 -0
- package/scripts/lib/exit-code-registry.cjs +98 -0
- package/scripts/lib/ndjson-reporter.cjs +119 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-docs-guard-registration.cjs +495 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +38 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/{lint-fix-has-regression-test.cjs → lint-fix-has-regression-tests.cjs} +12 -6
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +461 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-mutation-test-derivation-drift.cjs +86 -0
- package/scripts/lint-phase-enumeration-drift.cjs +492 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +471 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +488 -0
- package/scripts/lint-seam-enforcement.cjs +182 -0
- package/scripts/lint-slug-derivation-drift.cjs +921 -0
- package/scripts/lint-source-test-name-collision.cjs +241 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +950 -0
- package/scripts/lint-test-file-count.allowlist.json +137 -8
- package/scripts/lint-test-file-count.cjs +25 -3
- package/scripts/lint-unreachable-guard-drift.cjs +830 -0
- package/scripts/lint-vendored-deps.cjs +297 -0
- package/scripts/mutation-matrix.cjs +599 -50
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +100 -14
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/secret-scan.sh +75 -13
- package/scripts/select-docs-guards.cjs +56 -0
- package/scripts/sync-runtime-launcher.cjs +24 -7
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-discuss-phase/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-import/SKILL.md +1 -1
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +9 -5
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/bin/lib/ui-safety-gate.cjs +0 -107
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/lint-emitted-drift-ack.cjs +0 -344
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -13,13 +13,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
15
|
const node_os_1 = __importDefault(require("node:os"));
|
|
16
|
+
// #2874 (ADR-58 cleanup phase): route the staging functions' fs calls
|
|
17
|
+
// through the installRuntimeArtifacts call tree's injectable seam — see
|
|
18
|
+
// install-fs-adapter.cts's module doc. Resolves to real `node:fs` unless the
|
|
19
|
+
// top-level installRuntimeArtifacts call injected a `deps.fs`. Only the
|
|
20
|
+
// staging functions reachable FROM that call tree are routed
|
|
21
|
+
// (stageSkillsForProfile / stageAgentsForProfile /
|
|
22
|
+
// stageAgentsForRuntimeWithConverter / stageSkillsForRuntimeAsSkills /
|
|
23
|
+
// stageCommandsForRuntimeFlat / buildNamespaceBundleMap) — the profile-marker
|
|
24
|
+
// and manifest-loading helpers below are not on that call tree and keep
|
|
25
|
+
// using real `fs` directly.
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
27
|
+
const installFsAdapter = require("./install-fs-adapter.cjs");
|
|
28
|
+
const { installFs, mkInstallTempDir } = installFsAdapter;
|
|
16
29
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
17
30
|
// #2322: reuse the existing pure path-containment seam (ADR-1239 Phase C-2)
|
|
18
31
|
// instead of hand-rolling a new traversal check for capability skill stems.
|
|
19
32
|
const external_descriptor_trust_cjs_1 = require("./external-descriptor-trust.cjs");
|
|
20
33
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
34
|
const conversionModule = require("./runtime-artifact-conversion.cjs");
|
|
22
|
-
const { applyAgentPathRewrites: _applyAgentPathRewrites, processAttribution: _processAttribution, normalizeAgentBodyForRuntime: _normalizeAgentBodyForRuntime, readGsdCommandNames: _readGsdCommandNames, } = conversionModule;
|
|
35
|
+
const { applyAgentPathRewrites: _applyAgentPathRewrites, processAttribution: _processAttribution, normalizeAgentBodyForRuntime: _normalizeAgentBodyForRuntime, readGsdCommandNames: _readGsdCommandNames, deriveAgentName: _deriveAgentName, applyAgentFrontmatterExtensions: _applyAgentFrontmatterExtensions, } = conversionModule;
|
|
23
36
|
// #2995 (epic #1671 Phase 6.4): agent bodies join the fragment model. Markers are
|
|
24
37
|
// stripped at emit BEFORE any path rewrite or converter runs, so a `.claude/` ->
|
|
25
38
|
// `.windsurf/` regex can never reach inside a marker attribute and corrupt it —
|
|
@@ -124,9 +137,79 @@ function parseCallsAgents(content) {
|
|
|
124
137
|
* Also derives calls_agents for each skill by scanning the body text for
|
|
125
138
|
* `gsd-*` agent name references. Agent stems are stored under the special
|
|
126
139
|
* key `_calls_agents_<stem>` so they don't conflict with skill stems.
|
|
140
|
+
*
|
|
141
|
+
* #3798: command bodies are thin delegators — the actual `subagent_type=`
|
|
142
|
+
* spawns live in the workflow files each command references
|
|
143
|
+
* (`@…/workflows/<name>.md`). The agent derivation therefore ALSO reads every
|
|
144
|
+
* workflow file the command references (plus the workflow's steps/ fragments
|
|
145
|
+
* when it is split per the progressive-disclosure pattern) and unions their
|
|
146
|
+
* `gsd-*` tokens into the same `_calls_agents_<stem>` set. Without this,
|
|
147
|
+
* tiered profiles omitted agents their own installed skills spawn
|
|
148
|
+
* (gsd-verifier at execute-phase's verify_phase_goal was the filed repro).
|
|
149
|
+
* Over-inclusion fails safe: a tiered profile installing one extra agent
|
|
150
|
+
* costs bytes, never a broken spawn.
|
|
127
151
|
*/
|
|
128
152
|
const DEFAULT_COMMANDS_DIR = node_path_1.default.resolve(__dirname, '..', '..', '..', 'commands', 'gsd');
|
|
129
|
-
|
|
153
|
+
const DEFAULT_WORKFLOWS_DIR = node_path_1.default.resolve(__dirname, '..', '..', 'workflows');
|
|
154
|
+
/**
|
|
155
|
+
* Collect the `gsd-*` agent tokens from every workflow file a command body
|
|
156
|
+
* references. References are the `workflows/<name>.md` path suffixes the
|
|
157
|
+
* delegating commands embed (`@…/gsd-core/workflows/<name>.md`). A
|
|
158
|
+
* split workflow (workflows/<name>/steps/*.md) contributes its fragments as
|
|
159
|
+
* well, because the parent dispatches into them and the spawns live there.
|
|
160
|
+
*/
|
|
161
|
+
function workflowAgentRefs(content, workflowsDir) {
|
|
162
|
+
const refs = content.match(/workflows\/([a-z0-9][a-z0-9-]*)\.md/g) || [];
|
|
163
|
+
const names = [...new Set(refs.map((r) => r.slice('workflows/'.length)))];
|
|
164
|
+
const tokens = new Set();
|
|
165
|
+
for (const name of names) {
|
|
166
|
+
const direct = node_path_1.default.join(workflowsDir, name);
|
|
167
|
+
let body = null;
|
|
168
|
+
try {
|
|
169
|
+
body = node_fs_1.default.readFileSync(direct, 'utf8');
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
body = null;
|
|
173
|
+
}
|
|
174
|
+
if (body === null)
|
|
175
|
+
continue;
|
|
176
|
+
for (const tok of parseCallsAgents(body))
|
|
177
|
+
tokens.add(tok);
|
|
178
|
+
// Split workflow: union EVERY fragment under the workflow's directory
|
|
179
|
+
// (steps/, modes/, templates/…) — the parent dispatches into these per
|
|
180
|
+
// the progressive-disclosure pattern, and spawns live in all of them
|
|
181
|
+
// (#3798 review: modes/ carried gsd-advisor-researcher's spawn while the
|
|
182
|
+
// parent only named it incidentally in prose).
|
|
183
|
+
const fragDir = node_path_1.default.join(workflowsDir, name.slice(0, -3));
|
|
184
|
+
const walk = (dir) => {
|
|
185
|
+
let frags;
|
|
186
|
+
try {
|
|
187
|
+
frags = node_fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
for (const frag of frags) {
|
|
193
|
+
const full = node_path_1.default.join(dir, frag.name);
|
|
194
|
+
if (frag.isDirectory()) {
|
|
195
|
+
walk(full);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (!frag.isFile() || !frag.name.endsWith('.md'))
|
|
199
|
+
continue;
|
|
200
|
+
try {
|
|
201
|
+
const fragBody = node_fs_1.default.readFileSync(full, 'utf8');
|
|
202
|
+
for (const tok of parseCallsAgents(fragBody))
|
|
203
|
+
tokens.add(tok);
|
|
204
|
+
}
|
|
205
|
+
catch { /* unreadable fragment — skip */ }
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
walk(fragDir);
|
|
209
|
+
}
|
|
210
|
+
return [...tokens];
|
|
211
|
+
}
|
|
212
|
+
function loadSkillsManifest(commandsDir = DEFAULT_COMMANDS_DIR, workflowsDir = DEFAULT_WORKFLOWS_DIR) {
|
|
130
213
|
const manifest = new Map();
|
|
131
214
|
if (!node_fs_1.default.existsSync(commandsDir))
|
|
132
215
|
return manifest;
|
|
@@ -140,9 +223,12 @@ function loadSkillsManifest(commandsDir = DEFAULT_COMMANDS_DIR) {
|
|
|
140
223
|
try {
|
|
141
224
|
const content = node_fs_1.default.readFileSync(node_path_1.default.join(commandsDir, entry.name), 'utf8');
|
|
142
225
|
manifest.set(stem, parseRequires(content));
|
|
143
|
-
// Derive agent references from body text
|
|
144
|
-
const agentRefs =
|
|
145
|
-
|
|
226
|
+
// Derive agent references from body text + the workflows it delegates to
|
|
227
|
+
const agentRefs = [
|
|
228
|
+
...parseCallsAgents(content),
|
|
229
|
+
...workflowAgentRefs(content, workflowsDir),
|
|
230
|
+
];
|
|
231
|
+
manifest.set(`_calls_agents_${stem}`, [...new Set(agentRefs)]);
|
|
146
232
|
}
|
|
147
233
|
catch {
|
|
148
234
|
manifest.set(stem, []);
|
|
@@ -264,10 +350,41 @@ function resolveProfile({ modes, manifest, _profilesOverride, registry } = {}) {
|
|
|
264
350
|
// site to track its own cleanup handle.
|
|
265
351
|
const STAGED_DIRS = new Set();
|
|
266
352
|
let exitHandlerRegistered = false;
|
|
353
|
+
// #2874 leak-fix: `cleanupStagedSkills` runs at process exit — AFTER
|
|
354
|
+
// `withInstallFs` has already restored `current` back to the real adapter
|
|
355
|
+
// (install-fs-adapter.cts's module doc, "SYNCHRONOUS-ONLY / RE-ENTRANCY
|
|
356
|
+
// ASSUMPTION" — extended there to reference this map). A dir staged during a
|
|
357
|
+
// fake-adapter call must be cleaned up with THAT SAME fake adapter, not with
|
|
358
|
+
// whatever is ambiently active later, or an exit handler would perform real
|
|
359
|
+
// filesystem IO on a path that only ever existed in the fake's in-memory
|
|
360
|
+
// store. Capturing the adapter OBJECT `installFs()` returns at registration
|
|
361
|
+
// time (not the ambient `current` variable, which changes) means cleanup
|
|
362
|
+
// always replays the exact adapter that created the path. Dirs added to
|
|
363
|
+
// STAGED_DIRS without going through `registerStagedDir` (the deprecated
|
|
364
|
+
// `stageSkillsForMode`, which creates its stage dir via raw `fs.mkdtempSync`
|
|
365
|
+
// and was never on the injectable seam) have no entry here and fall back to
|
|
366
|
+
// real `fs.rmSync` below — the same real fs it always used to create them.
|
|
367
|
+
const STAGED_DIR_ADAPTERS = new Map();
|
|
368
|
+
/**
|
|
369
|
+
* Register a dir just staged through the injectable seam (`installFs()`) for
|
|
370
|
+
* exit-time cleanup, capturing the adapter that staged it alongside the path.
|
|
371
|
+
* See `STAGED_DIR_ADAPTERS`'s comment for why the capture matters.
|
|
372
|
+
*/
|
|
373
|
+
function registerStagedDir(dir) {
|
|
374
|
+
STAGED_DIRS.add(dir);
|
|
375
|
+
STAGED_DIR_ADAPTERS.set(dir, installFs());
|
|
376
|
+
ensureExitCleanup();
|
|
377
|
+
}
|
|
267
378
|
function cleanupStagedSkills() {
|
|
268
379
|
for (const dir of STAGED_DIRS) {
|
|
380
|
+
const adapter = STAGED_DIR_ADAPTERS.get(dir);
|
|
269
381
|
try {
|
|
270
|
-
|
|
382
|
+
if (adapter) {
|
|
383
|
+
adapter.rmSync(dir, { recursive: true, force: true });
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
node_fs_1.default.rmSync(dir, { recursive: true, force: true });
|
|
387
|
+
}
|
|
271
388
|
}
|
|
272
389
|
catch {
|
|
273
390
|
// Best-effort: missing dir or permission error shouldn't crash a
|
|
@@ -275,6 +392,7 @@ function cleanupStagedSkills() {
|
|
|
275
392
|
}
|
|
276
393
|
}
|
|
277
394
|
STAGED_DIRS.clear();
|
|
395
|
+
STAGED_DIR_ADAPTERS.clear();
|
|
278
396
|
}
|
|
279
397
|
// Signals we register a cleanup handler for in addition to the natural
|
|
280
398
|
// 'exit' event. `process.on('exit')` does NOT fire on these — an installer
|
|
@@ -303,11 +421,11 @@ function ensureExitCleanup() {
|
|
|
303
421
|
function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
304
422
|
if (resolvedProfile.skills === '*')
|
|
305
423
|
return srcDir;
|
|
306
|
-
if (!
|
|
424
|
+
if (!installFs().existsSync(srcDir))
|
|
307
425
|
return srcDir;
|
|
308
|
-
const stageDir =
|
|
426
|
+
const stageDir = mkInstallTempDir('gsd-profile-skills-');
|
|
309
427
|
try {
|
|
310
|
-
const entries =
|
|
428
|
+
const entries = installFs().readdirSync(srcDir, { withFileTypes: true });
|
|
311
429
|
for (const entry of entries) {
|
|
312
430
|
if (!entry.isFile())
|
|
313
431
|
continue;
|
|
@@ -316,18 +434,17 @@ function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
|
316
434
|
const stem = entry.name.slice(0, -3);
|
|
317
435
|
if (!(resolvedProfile.skills).has(stem))
|
|
318
436
|
continue;
|
|
319
|
-
|
|
437
|
+
installFs().copyFileSync(node_path_1.default.join(srcDir, entry.name), node_path_1.default.join(stageDir, entry.name));
|
|
320
438
|
}
|
|
321
439
|
}
|
|
322
440
|
catch (err) {
|
|
323
441
|
try {
|
|
324
|
-
|
|
442
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
325
443
|
}
|
|
326
444
|
catch { /* best-effort */ }
|
|
327
445
|
throw err;
|
|
328
446
|
}
|
|
329
|
-
|
|
330
|
-
ensureExitCleanup();
|
|
447
|
+
registerStagedDir(stageDir);
|
|
331
448
|
return stageDir;
|
|
332
449
|
}
|
|
333
450
|
/**
|
|
@@ -353,12 +470,12 @@ function stageSkillsForProfile(srcDir, resolvedProfile) {
|
|
|
353
470
|
function stageAgentsForProfile(srcAgentsDir, resolvedProfile) {
|
|
354
471
|
if (resolvedProfile.skills === '*')
|
|
355
472
|
return srcAgentsDir;
|
|
356
|
-
if (!
|
|
473
|
+
if (!installFs().existsSync(srcAgentsDir))
|
|
357
474
|
return srcAgentsDir;
|
|
358
|
-
const stageDir =
|
|
475
|
+
const stageDir = mkInstallTempDir('gsd-profile-agents-');
|
|
359
476
|
try {
|
|
360
477
|
if (resolvedProfile.agents instanceof Set && resolvedProfile.agents.size > 0) {
|
|
361
|
-
const entries =
|
|
478
|
+
const entries = installFs().readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
362
479
|
for (const entry of entries) {
|
|
363
480
|
if (!entry.isFile())
|
|
364
481
|
continue;
|
|
@@ -368,20 +485,19 @@ function stageAgentsForProfile(srcAgentsDir, resolvedProfile) {
|
|
|
368
485
|
const stem = entry.name.slice(0, -3);
|
|
369
486
|
if (!resolvedProfile.agents.has(stem))
|
|
370
487
|
continue;
|
|
371
|
-
|
|
488
|
+
installFs().copyFileSync(node_path_1.default.join(srcAgentsDir, entry.name), node_path_1.default.join(stageDir, entry.name));
|
|
372
489
|
}
|
|
373
490
|
}
|
|
374
491
|
// If agents is empty Set, we produce an empty stageDir (no agents for this profile)
|
|
375
492
|
}
|
|
376
493
|
catch (err) {
|
|
377
494
|
try {
|
|
378
|
-
|
|
495
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
379
496
|
}
|
|
380
497
|
catch { /* best-effort */ }
|
|
381
498
|
throw err;
|
|
382
499
|
}
|
|
383
|
-
|
|
384
|
-
ensureExitCleanup();
|
|
500
|
+
registerStagedDir(stageDir);
|
|
385
501
|
return stageDir;
|
|
386
502
|
}
|
|
387
503
|
/**
|
|
@@ -395,10 +511,10 @@ function buildNamespaceBundleMap(srcCommandsDir) {
|
|
|
395
511
|
const routerStems = new Set();
|
|
396
512
|
const routerChildren = new Map();
|
|
397
513
|
const childToRouters = new Map();
|
|
398
|
-
if (!
|
|
514
|
+
if (!installFs().existsSync(srcCommandsDir)) {
|
|
399
515
|
return { routerStems, routerChildren, childToRouters };
|
|
400
516
|
}
|
|
401
|
-
for (const entry of
|
|
517
|
+
for (const entry of installFs().readdirSync(srcCommandsDir, { withFileTypes: true })) {
|
|
402
518
|
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
403
519
|
continue;
|
|
404
520
|
if (!entry.name.startsWith('ns-'))
|
|
@@ -406,7 +522,7 @@ function buildNamespaceBundleMap(srcCommandsDir) {
|
|
|
406
522
|
const stem = entry.name.slice(0, -3);
|
|
407
523
|
let children = [];
|
|
408
524
|
try {
|
|
409
|
-
children = parseRequires(
|
|
525
|
+
children = parseRequires(installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8'));
|
|
410
526
|
}
|
|
411
527
|
catch {
|
|
412
528
|
children = [];
|
|
@@ -637,7 +753,7 @@ function readInstalledCapabilitySkill(stem, registry) {
|
|
|
637
753
|
* When absent, NOTHING third-party is staged (fail closed).
|
|
638
754
|
*/
|
|
639
755
|
function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converter, prefix, nested = false, registry) {
|
|
640
|
-
if (!
|
|
756
|
+
if (!installFs().existsSync(srcCommandsDir))
|
|
641
757
|
return srcCommandsDir;
|
|
642
758
|
// Nesting applies to the `full` install AND to any surface whose skill set
|
|
643
759
|
// still contains every namespace router (a full/reset surface). It must NOT
|
|
@@ -660,9 +776,9 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
660
776
|
// this call, so the third-party fill-in pass below can enforce "first-party
|
|
661
777
|
// ALWAYS wins on collision" without re-deriving membership.
|
|
662
778
|
const firstPartyStems = new Set();
|
|
663
|
-
const stageDir =
|
|
779
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-skills-');
|
|
664
780
|
try {
|
|
665
|
-
const entries =
|
|
781
|
+
const entries = installFs().readdirSync(srcCommandsDir, { withFileTypes: true });
|
|
666
782
|
for (const entry of entries) {
|
|
667
783
|
if (!entry.isFile())
|
|
668
784
|
continue;
|
|
@@ -672,15 +788,15 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
672
788
|
if (resolvedProfile.skills !== '*' && !(resolvedProfile.skills).has(stem))
|
|
673
789
|
continue;
|
|
674
790
|
firstPartyStems.add(stem);
|
|
675
|
-
const content =
|
|
791
|
+
const content = installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8');
|
|
676
792
|
const skillName = `${prefix}${stem}`;
|
|
677
793
|
const converted = converter(content, skillName);
|
|
678
794
|
if (doNest && bundles.routerStems.has(stem)) {
|
|
679
795
|
// Router skill: rewrite its routing table to the nested Read pattern and
|
|
680
796
|
// emit it as the single top-level bundle entry.
|
|
681
797
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
682
|
-
|
|
683
|
-
|
|
798
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
799
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), transformRouterBodyToNested(converted));
|
|
684
800
|
continue;
|
|
685
801
|
}
|
|
686
802
|
if (doNest && bundles.childToRouters.has(stem)) {
|
|
@@ -689,16 +805,16 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
689
805
|
// top-level eager listing while staying readable by file path (#69).
|
|
690
806
|
for (const routerStem of bundles.childToRouters.get(stem)) {
|
|
691
807
|
const destDir = node_path_1.default.join(stageDir, `${prefix}${routerStem}`, 'skills', stem);
|
|
692
|
-
|
|
693
|
-
|
|
808
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
809
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), converted);
|
|
694
810
|
}
|
|
695
811
|
continue;
|
|
696
812
|
}
|
|
697
813
|
// Flat top-level skill (default behaviour; also the unrouted fallback when
|
|
698
814
|
// nesting is active).
|
|
699
815
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
700
|
-
|
|
701
|
-
|
|
816
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
817
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), converted);
|
|
702
818
|
}
|
|
703
819
|
// #2322: materialize installed THIRD-PARTY capability skills, bound to
|
|
704
820
|
// their DECLARING capability via the registry's capabilityClusters view
|
|
@@ -740,25 +856,24 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
740
856
|
if (!(0, external_descriptor_trust_cjs_1.isPathConfined)(skillName, stageDir))
|
|
741
857
|
continue; // defense-in-depth
|
|
742
858
|
const destDir = node_path_1.default.join(stageDir, skillName);
|
|
743
|
-
|
|
744
|
-
|
|
859
|
+
installFs().mkdirSync(destDir, { recursive: true });
|
|
860
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, 'SKILL.md'), found.content);
|
|
745
861
|
// #2322 HIGH-3: persist the capability-owned marker so a later prune
|
|
746
862
|
// pass (surface.cts pruneSkillDirs) can identify — and remove — this
|
|
747
863
|
// directory even once the owning capability is uninstalled/unsurfaced
|
|
748
864
|
// and no longer appears in any registry view.
|
|
749
|
-
|
|
865
|
+
installFs().writeFileSync(node_path_1.default.join(destDir, CAPABILITY_SKILL_MARKER), found.capId + '\n', 'utf8');
|
|
750
866
|
}
|
|
751
867
|
}
|
|
752
868
|
}
|
|
753
869
|
catch (err) {
|
|
754
870
|
try {
|
|
755
|
-
|
|
871
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
756
872
|
}
|
|
757
873
|
catch { /* best-effort */ }
|
|
758
874
|
throw err;
|
|
759
875
|
}
|
|
760
|
-
|
|
761
|
-
ensureExitCleanup();
|
|
876
|
+
registerStagedDir(stageDir);
|
|
762
877
|
return stageDir;
|
|
763
878
|
}
|
|
764
879
|
/**
|
|
@@ -782,26 +897,57 @@ function stageSkillsForRuntimeAsSkills(srcCommandsDir, resolvedProfile, converte
|
|
|
782
897
|
* 1. applyAgentPathRewrites (4 base ~/.claude/ regexes; skipped for copilot/antigravity)
|
|
783
898
|
* 2. processAttribution (Co-Authored-By policy)
|
|
784
899
|
* 3. converter (runtime-specific frontmatter/body transform)
|
|
785
|
-
* 4.
|
|
900
|
+
* 4. applyAgentFrontmatterExtensions (#2875 Part 2: effort/disallowedTools,
|
|
901
|
+
* gated by hostBehaviors.agentFrontmatterExtensions — no-op for a runtime
|
|
902
|
+
* that declares nothing, e.g. every non-Claude runtime today)
|
|
903
|
+
* 5. normalizeAgentBodyForRuntime (colon→hyphen refs; no-op for trivial group)
|
|
786
904
|
* When `agentCtx` is absent, only the converter is applied (backward-compat for
|
|
787
905
|
* the feat-1173 synthetic-descriptor tests and the copilot/antigravity paths
|
|
788
906
|
* that handle cross-cutting inside their converters).
|
|
789
907
|
*
|
|
790
908
|
* @param srcAgentsDir source agents directory (e.g. agents/)
|
|
791
909
|
* @param resolvedProfile profile filter from resolveProfile()
|
|
792
|
-
* @param converter (content: string, isGlobal?: boolean) → string
|
|
793
|
-
* converter; scope-aware converters (copilot/antigravity)
|
|
794
|
-
* read isGlobal, single-arg converters ignore
|
|
910
|
+
* @param converter (content: string, isGlobal?: boolean, meta?: {agentName: string}) → string
|
|
911
|
+
* per-file converter; scope-aware converters (copilot/antigravity)
|
|
912
|
+
* read isGlobal, single-arg converters ignore both extra args (#1173).
|
|
913
|
+
* `meta.agentName` (#2875 Part 2) is passed ONLY when `agentCtx` is
|
|
914
|
+
* present, letting a converter close over per-agent config
|
|
915
|
+
* (e.g. kilo/opencode model-override resolution in
|
|
916
|
+
* runtime-artifact-layout.cts's convertedAgentsKind) without widening
|
|
917
|
+
* every OTHER converter's contract — converters that don't declare a
|
|
918
|
+
* 3rd parameter simply never read it.
|
|
795
919
|
* @param isGlobal install scope passed through to the converter
|
|
796
920
|
* @param agentCtx optional cross-cutting context (ADR-1235 §1); when absent,
|
|
797
921
|
* only the converter is applied (backward compat)
|
|
798
922
|
*/
|
|
799
923
|
function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, converter, isGlobal = false, agentCtx) {
|
|
800
|
-
if (!
|
|
924
|
+
if (!installFs().existsSync(srcAgentsDir))
|
|
801
925
|
return srcAgentsDir;
|
|
802
|
-
const stageDir =
|
|
926
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-agents-');
|
|
927
|
+
let entries;
|
|
928
|
+
try {
|
|
929
|
+
// #2284/#2875: readdirSync-ing the shipped agents/ source is isolated in
|
|
930
|
+
// its own try/catch so an unreadable source directory (permissions, a
|
|
931
|
+
// corrupted install, or — as the #2284 test suite demonstrates — the
|
|
932
|
+
// fail-closed injection harness) produces the SAME "refusing to install"
|
|
933
|
+
// fail-closed wording every other agents-dir-unreadable path in this
|
|
934
|
+
// codebase uses (bin/install.js's `_resolveAvailableGsdRoles` /
|
|
935
|
+
// `_assertRoleResolvable`), instead of an unrelated raw fs error message
|
|
936
|
+
// escaping uncaught. Hermes's role-dispatch validation depends on the
|
|
937
|
+
// SAME shipped agents/ directory being readable; before this runtime also
|
|
938
|
+
// declared an `agents` kind, this function was never reached on a Hermes
|
|
939
|
+
// install, so an unreadable source here silently surfaced as a raw error
|
|
940
|
+
// rather than the deliberate fail-closed contract #2284 established.
|
|
941
|
+
entries = installFs().readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
942
|
+
}
|
|
943
|
+
catch (err) {
|
|
944
|
+
try {
|
|
945
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
946
|
+
}
|
|
947
|
+
catch { /* best-effort */ }
|
|
948
|
+
throw new Error(`stageAgentsForRuntimeWithConverter: could not resolve the shipped agents/ directory "${srcAgentsDir}" to stage — refusing to install (fail-closed, #2284/#2875): ${err.message}`);
|
|
949
|
+
}
|
|
803
950
|
try {
|
|
804
|
-
const entries = node_fs_1.default.readdirSync(srcAgentsDir, { withFileTypes: true });
|
|
805
951
|
// Resolve cmdNames once per staging call (not per file) for performance.
|
|
806
952
|
const cmdNames = agentCtx ? _readGsdCommandNames() : [];
|
|
807
953
|
for (const entry of entries) {
|
|
@@ -817,39 +963,44 @@ function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, conve
|
|
|
817
963
|
}
|
|
818
964
|
}
|
|
819
965
|
const agentSourcePath = node_path_1.default.join(srcAgentsDir, entry.name);
|
|
820
|
-
let content =
|
|
966
|
+
let content = installFs().readFileSync(agentSourcePath, 'utf8');
|
|
821
967
|
// #2995: strip gsd:section markers FIRST — before path rewrites, attribution,
|
|
822
968
|
// and the per-runtime converter. Byte-identical (no-op) for an unmarked agent;
|
|
823
969
|
// throws loudly naming the file for a malformed marker, never emitting a
|
|
824
970
|
// half-composed agent.
|
|
825
971
|
content = _composeWorkflow(content, { sourcePath: agentSourcePath });
|
|
826
972
|
if (agentCtx) {
|
|
973
|
+
// #2875 Part 2 / row I3: derived exactly as the inline loop does —
|
|
974
|
+
// single-sourced via deriveAgentName (runtime-artifact-conversion.cts).
|
|
975
|
+
const agentName = _deriveAgentName(entry.name);
|
|
827
976
|
// ADR-1235 §1: pre-converter cross-cutting (matches inline loop order exactly)
|
|
828
977
|
// Step 1: path rewrites (4 base ~/.claude/ regexes; skipped for copilot/antigravity)
|
|
829
978
|
content = _applyAgentPathRewrites(content, agentCtx.runtime, agentCtx.pathPrefix);
|
|
830
979
|
// Step 2: attribution
|
|
831
980
|
content = _processAttribution(content, agentCtx.attribution);
|
|
832
981
|
// Step 3: converter (runtime-specific frontmatter/body transform)
|
|
833
|
-
content = converter(content, isGlobal);
|
|
834
|
-
// Step 4:
|
|
982
|
+
content = converter(content, isGlobal, { agentName });
|
|
983
|
+
// Step 4: frontmatter extensions (effort/disallowedTools; no-op unless
|
|
984
|
+
// the runtime declares hostBehaviors.agentFrontmatterExtensions)
|
|
985
|
+
content = _applyAgentFrontmatterExtensions(content, { runtime: agentCtx.runtime, agentName, targetDir: agentCtx.targetDir });
|
|
986
|
+
// Step 5: normalize colon→hyphen refs (no-op for trivial group)
|
|
835
987
|
content = _normalizeAgentBodyForRuntime(content, agentCtx.runtime, cmdNames);
|
|
836
988
|
}
|
|
837
989
|
else {
|
|
838
990
|
// Backward-compat: only apply the converter (no cross-cutting)
|
|
839
991
|
content = converter(content, isGlobal);
|
|
840
992
|
}
|
|
841
|
-
|
|
993
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, entry.name), content, 'utf8');
|
|
842
994
|
}
|
|
843
995
|
}
|
|
844
996
|
catch (err) {
|
|
845
997
|
try {
|
|
846
|
-
|
|
998
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
847
999
|
}
|
|
848
1000
|
catch { /* best-effort */ }
|
|
849
1001
|
throw err;
|
|
850
1002
|
}
|
|
851
|
-
|
|
852
|
-
ensureExitCleanup();
|
|
1003
|
+
registerStagedDir(stageDir);
|
|
853
1004
|
return stageDir;
|
|
854
1005
|
}
|
|
855
1006
|
/**
|
|
@@ -876,11 +1027,11 @@ function stageAgentsForRuntimeWithConverter(srcAgentsDir, resolvedProfile, conve
|
|
|
876
1027
|
* @param prefix command name prefix (for converter arg), e.g. 'gsd-'
|
|
877
1028
|
*/
|
|
878
1029
|
function stageCommandsForRuntimeFlat(srcCommandsDir, resolvedProfile, converter, prefix) {
|
|
879
|
-
if (!
|
|
1030
|
+
if (!installFs().existsSync(srcCommandsDir))
|
|
880
1031
|
return srcCommandsDir;
|
|
881
|
-
const stageDir =
|
|
1032
|
+
const stageDir = mkInstallTempDir('gsd-profile-runtime-commands-');
|
|
882
1033
|
try {
|
|
883
|
-
const entries =
|
|
1034
|
+
const entries = installFs().readdirSync(srcCommandsDir, { withFileTypes: true });
|
|
884
1035
|
for (const entry of entries) {
|
|
885
1036
|
if (!entry.isFile())
|
|
886
1037
|
continue;
|
|
@@ -889,24 +1040,23 @@ function stageCommandsForRuntimeFlat(srcCommandsDir, resolvedProfile, converter,
|
|
|
889
1040
|
const stem = entry.name.slice(0, -3);
|
|
890
1041
|
if (resolvedProfile.skills !== '*' && !(resolvedProfile.skills).has(stem))
|
|
891
1042
|
continue;
|
|
892
|
-
const content =
|
|
1043
|
+
const content = installFs().readFileSync(node_path_1.default.join(srcCommandsDir, entry.name), 'utf8');
|
|
893
1044
|
// Pass the full command name (with prefix) to the converter so it can
|
|
894
1045
|
// reference the installed command name in the body (e.g. for descriptions).
|
|
895
1046
|
// The staged file itself is named without the prefix; _copyStaged adds it.
|
|
896
1047
|
const commandName = `${prefix}${stem}`;
|
|
897
1048
|
const converted = converter(content, commandName);
|
|
898
|
-
|
|
1049
|
+
installFs().writeFileSync(node_path_1.default.join(stageDir, `${stem}.md`), converted);
|
|
899
1050
|
}
|
|
900
1051
|
}
|
|
901
1052
|
catch (err) {
|
|
902
1053
|
try {
|
|
903
|
-
|
|
1054
|
+
installFs().rmSync(stageDir, { recursive: true, force: true });
|
|
904
1055
|
}
|
|
905
1056
|
catch { /* best-effort */ }
|
|
906
1057
|
throw err;
|
|
907
1058
|
}
|
|
908
|
-
|
|
909
|
-
ensureExitCleanup();
|
|
1059
|
+
registerStagedDir(stageDir);
|
|
910
1060
|
return stageDir;
|
|
911
1061
|
}
|
|
912
1062
|
// ---------------------------------------------------------------------------
|
|
@@ -1079,6 +1229,7 @@ module.exports = {
|
|
|
1079
1229
|
// Shared internals
|
|
1080
1230
|
parseRequires,
|
|
1081
1231
|
parseCallsAgents,
|
|
1232
|
+
workflowAgentRefs,
|
|
1082
1233
|
cleanupStagedSkills,
|
|
1083
1234
|
// #2322: capability-skill security seams — exported for direct unit-testing
|
|
1084
1235
|
// and for surface.cts's prune pass (CAPABILITY_SKILL_MARKER parity).
|