@opengsd/gsd-core 1.15.0 → 1.16.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/.opencode/plugins/gsd-core.js +85 -5
- 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 +1 -1
- package/agents/gsd-debug-session-manager.md +1 -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/install.js +126 -196
- 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 +142 -56
- package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
- 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 +183 -103
- package/gsd-core/bin/lib/capability-validator.cjs +16 -0
- 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 +173 -170
- 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 +141 -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 +80 -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/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 +162 -96
- package/gsd-core/bin/lib/install-engine.cjs +19 -35
- package/gsd-core/bin/lib/install-profiles.cjs +7 -4
- package/gsd-core/bin/lib/io.cjs +122 -3
- 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/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/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 +280 -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 +11 -8
- 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 +91 -157
- 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 +307 -591
- package/gsd-core/bin/lib/runtime-name-policy.cjs +142 -27
- package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
- package/gsd-core/bin/lib/shell-command-projection.cjs +37 -2
- package/gsd-core/bin/lib/smart-entry.cjs +19 -3
- 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.cjs +214 -105
- 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/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 +1165 -314
- 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 +84 -90
- 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 +1 -1
- 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 +78 -170
- 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 +3 -2
- 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 +8 -0
- package/hooks/dist/gsd-context-monitor.js +31 -8
- package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
- package/hooks/dist/gsd-secret-read-guard.js +147 -16
- package/hooks/dist/gsd-statusline.js +15 -7
- 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 +8 -0
- package/hooks/gsd-context-monitor.js +31 -8
- package/hooks/gsd-cursor-subagent-start.js +8 -0
- package/hooks/gsd-secret-read-guard.js +147 -16
- package/hooks/gsd-statusline.js +15 -7
- 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-features.cjs +13 -8
- package/scripts/gen-hooks-cli-exit.cjs +12 -28
- package/scripts/gen-loop-host-contract.cjs +10 -1
- 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 +20 -2
- package/scripts/lib/ndjson-reporter.cjs +28 -3
- package/scripts/lib/platform-conformance-tier.generated.cjs +34 -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 +50 -5
- 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
|
@@ -71,7 +71,7 @@ const planningScopeMod = require("./planning-scope.cjs");
|
|
|
71
71
|
const { SCOPE } = planningScopeMod;
|
|
72
72
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
73
73
|
const verificationMod = require("./verification.cjs");
|
|
74
|
-
const { readVerificationStatus } = verificationMod;
|
|
74
|
+
const { readVerificationStatus, VerificationStatusError, failOnVerificationStatusError } = verificationMod;
|
|
75
75
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
76
76
|
const phaseIdMod = require("./phase-id.cjs");
|
|
77
77
|
const { phaseKeyFromDir, phaseKeyFromToken, phaseMarkdownRegexSource } = phaseIdMod;
|
|
@@ -304,6 +304,8 @@ function containmentEnforcingVerificationFs(planningRoot) {
|
|
|
304
304
|
return node_fs_1.default.readFileSync(filePath, encoding);
|
|
305
305
|
},
|
|
306
306
|
statSync(filePath) {
|
|
307
|
+
// #5118: a code-less containment throw here is NOT "phase directory
|
|
308
|
+
// not found" — readVerificationStatus falls through to `missing`.
|
|
307
309
|
assertContained(filePath);
|
|
308
310
|
return node_fs_1.default.statSync(filePath);
|
|
309
311
|
},
|
|
@@ -1016,6 +1018,17 @@ function buildPhaseGoalAndDependencies(cwd, roadmapDoc, phaseId, phaseDirLabel,
|
|
|
1016
1018
|
}
|
|
1017
1019
|
// ─── Entry points ─────────────────────────────────────────────────────────────
|
|
1018
1020
|
function buildPlanningInspect(cwd) {
|
|
1021
|
+
return buildPlanningInspectResult(cwd).payload;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* #5118: the inspect payload plus the first verification report whose
|
|
1025
|
+
* `status` is outside the closed set (`statusError`, or `null`) — the
|
|
1026
|
+
* aggregate CARRIES the owner's error in its own result, and `planning
|
|
1027
|
+
* inspect` fails with it instead of printing an answer computed over a
|
|
1028
|
+
* report the owner refused.
|
|
1029
|
+
*/
|
|
1030
|
+
function buildPlanningInspectResult(cwd) {
|
|
1031
|
+
let statusError = null;
|
|
1019
1032
|
const diagnostics = [];
|
|
1020
1033
|
const paths = planningPaths(cwd);
|
|
1021
1034
|
const planningExists = node_fs_1.default.existsSync(paths.planning);
|
|
@@ -1078,8 +1091,8 @@ function buildPlanningInspect(cwd) {
|
|
|
1078
1091
|
// GAP 2 (#2790 follow-up security review): `readVerificationStatus`
|
|
1079
1092
|
// (`src/verification.cts`) is a shared owner with its own unguarded
|
|
1080
1093
|
// `readFileSync` — a `*-VERIFICATION.md` symlinked outside the planning
|
|
1081
|
-
// root would leak
|
|
1082
|
-
//
|
|
1094
|
+
// root would leak its unrecognized `status:` value verbatim (today via
|
|
1095
|
+
// the VerificationStatusError message, #5118). Fixed
|
|
1083
1096
|
// from THIS consumer's side via the injectable `opts.fs` seam that
|
|
1084
1097
|
// function already exposes, never by touching its signature — see
|
|
1085
1098
|
// `containmentEnforcingVerificationFs`'s doc comment. This same seam's
|
|
@@ -1094,9 +1107,22 @@ function buildPlanningInspect(cwd) {
|
|
|
1094
1107
|
// (`superseded`) rather than document text, and GAP 1's directory
|
|
1095
1108
|
// containment check already covers the escaped-DIRECTORY case for it —
|
|
1096
1109
|
// so it needs no fix of its own.
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1110
|
+
// #5118: an out-of-set report status is carried, not thrown past the
|
|
1111
|
+
// other phases — the row reads `status: null` and the command fails with
|
|
1112
|
+
// the first such error once the payload is built.
|
|
1113
|
+
let verification;
|
|
1114
|
+
try {
|
|
1115
|
+
verification = readVerificationStatus(phaseDir, {
|
|
1116
|
+
fs: containmentEnforcingVerificationFs(paths.planning),
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
catch (err) {
|
|
1120
|
+
if (!(err instanceof VerificationStatusError))
|
|
1121
|
+
throw err;
|
|
1122
|
+
if (statusError === null)
|
|
1123
|
+
statusError = err;
|
|
1124
|
+
verification = { status: null, next_action: err.message, route: '' };
|
|
1125
|
+
}
|
|
1100
1126
|
const token = /^(\d+(?:\.\d+)*)/.exec(phase.dir);
|
|
1101
1127
|
const phaseId = token ? token[1] : null;
|
|
1102
1128
|
const { goal, dependencies } = buildPhaseGoalAndDependencies(cwd, roadmapDoc, phaseId, phase.dir, diagnostics);
|
|
@@ -1129,6 +1155,8 @@ function buildPlanningInspect(cwd) {
|
|
|
1129
1155
|
verification: {
|
|
1130
1156
|
status: verification.status,
|
|
1131
1157
|
next_action: verification.next_action ?? null,
|
|
1158
|
+
// #5118: additive — the bare command the owner routes this status to.
|
|
1159
|
+
route: verification.route,
|
|
1132
1160
|
},
|
|
1133
1161
|
roadmap_acceptance: {
|
|
1134
1162
|
checkbox: checkboxByPhaseKey.has(phaseKeyFromDir(phase.dir))
|
|
@@ -1150,7 +1178,7 @@ function buildPlanningInspect(cwd) {
|
|
|
1150
1178
|
const phaseScope = worstScope(snapshot.phaseDirs.scope, snapshot.phases.scope, ...phaseRows.map((p) => p.scope));
|
|
1151
1179
|
const acceptedPhases = makeFraction(phaseRows.filter((p) => p.complete).length, phaseRows.length, phaseScope, 'progress.accepted_phases', diagnostics);
|
|
1152
1180
|
const completedPlans = makeFraction(phaseRows.reduce((sum, p) => sum + p.summary_count, 0), phaseRows.reduce((sum, p) => sum + p.plan_count, 0), phaseScope, 'progress.completed_plans', diagnostics);
|
|
1153
|
-
|
|
1181
|
+
const payload = {
|
|
1154
1182
|
schema_version: PLANNING_INSPECT_SCHEMA_VERSION,
|
|
1155
1183
|
generated_from: {
|
|
1156
1184
|
cwd: toPosix(cwd),
|
|
@@ -1178,6 +1206,7 @@ function buildPlanningInspect(cwd) {
|
|
|
1178
1206
|
},
|
|
1179
1207
|
diagnostics,
|
|
1180
1208
|
};
|
|
1209
|
+
return { payload, statusError };
|
|
1181
1210
|
}
|
|
1182
1211
|
/**
|
|
1183
1212
|
* `planning inspect` — emit the schema-v1 snapshot.
|
|
@@ -1187,7 +1216,12 @@ function buildPlanningInspect(cwd) {
|
|
|
1187
1216
|
* transparently on stdout. Bypassing `output()` would lose that for free.
|
|
1188
1217
|
*/
|
|
1189
1218
|
function cmdPlanningInspect(cwd, raw) {
|
|
1190
|
-
|
|
1219
|
+
const { payload, statusError } = buildPlanningInspectResult(cwd);
|
|
1220
|
+
// #5118: a read-only aggregate over a refused report prints nothing and
|
|
1221
|
+
// fails with the error's own reason (`verification_status_invalid`).
|
|
1222
|
+
if (statusError)
|
|
1223
|
+
failOnVerificationStatusError(statusError);
|
|
1224
|
+
output(payload, raw);
|
|
1191
1225
|
}
|
|
1192
1226
|
const planningInspect = {
|
|
1193
1227
|
PLANNING_INSPECT_SCHEMA_VERSION,
|
|
@@ -124,10 +124,12 @@ function buildPhaseSnapshot(phasesDir, dir, convention) {
|
|
|
124
124
|
// report exactly like its legacy twin.
|
|
125
125
|
const completionResult = isPhaseComplete(fullPhaseDir, { convention });
|
|
126
126
|
const scanResult = scanPhasePlans(fullPhaseDir);
|
|
127
|
+
const statusError = completionResult.value.statusError;
|
|
127
128
|
return {
|
|
128
129
|
dir,
|
|
129
130
|
complete: completionResult.value.complete,
|
|
130
131
|
verificationStatus: completionResult.value.verification.status,
|
|
132
|
+
verificationStatusError: statusError ? { file: statusError.file, message: statusError.message } : null,
|
|
131
133
|
planCount: scanResult.planCount,
|
|
132
134
|
summaryCount: scanResult.summaryCount,
|
|
133
135
|
scope: worstScope(completionResult.scope, scanResult.scope),
|
|
@@ -882,6 +884,22 @@ function buildCurrentMilestoneRoadmapPhaseIdsField(cwd, roadmapPath, convention)
|
|
|
882
884
|
// and `bracketGroup` is 0. Inferring the convention from a matched bracket's
|
|
883
885
|
// shape would run a repo-failing check against a repo that never opted in.
|
|
884
886
|
const bracketGroup = convention === 'bracket' ? 1 : 0;
|
|
887
|
+
// #5007 (Phase 6 / ADR-4910 §8): already composed from `phaseHeadingPrefixSrcFor`
|
|
888
|
+
// directly, not a hand-rolled literal — the site's only marked defect was
|
|
889
|
+
// this doc comment's own prose quoting the pattern verbatim (fixed above),
|
|
890
|
+
// which is exactly what the drift detector matched. Audited against the
|
|
891
|
+
// design doc's suggested further swap onto `buildPhaseHeadingScanRegex`
|
|
892
|
+
// (the same owner `bracketGroup`/`phaseNumGroup` above hand-derives) and
|
|
893
|
+
// deliberately did NOT make that swap: the owner's regex requires a title
|
|
894
|
+
// (`${OPTIONAL_PHASE_TAG_SOURCE}\s*:\s*([^\n]+)` — at least one non-newline
|
|
895
|
+
// character after the colon), while this site's own tail is bare `:` with
|
|
896
|
+
// no title requirement. A live probe against this function (a `### Phase 3:`
|
|
897
|
+
// heading with no title text) confirms the current, pre-migration behavior
|
|
898
|
+
// DOES count that phase — swapping to the owner would silently drop it from
|
|
899
|
+
// W026's scan, and no existing test (including the ADR-612 census test
|
|
900
|
+
// pinned to this site by name) would catch that narrowing, since the census
|
|
901
|
+
// only pins `phaseHeadingPrefixSrcFor`'s own output, not this regex's tail.
|
|
902
|
+
// Kept as its own composition to preserve this exact byte-for-behavior.
|
|
885
903
|
const phasePattern = new RegExp(`#{2,4}\\s*${phaseHeadingPrefixSrcFor(PHASE_HEADING_BASELINE.LABEL_ONLY, convention, Boolean(bracketGroup))}(${PHASE_NUMBER_TOKEN_SOURCE})(?:\\s*\\([^)\\n]{0,200}\\))?\\s*:`, 'gi');
|
|
886
904
|
const value = [];
|
|
887
905
|
for (const m of scoped.matchAll(phasePattern)) {
|
|
@@ -144,60 +144,73 @@ function planningDir(cwd, ws, project) {
|
|
|
144
144
|
function planningRoot(cwd) {
|
|
145
145
|
return node_path_1.default.join(cwd, '.planning');
|
|
146
146
|
}
|
|
147
|
+
const CONFIG_VALUE_ABSENT = Object.freeze({ present: false, value: undefined });
|
|
147
148
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* project- and workstream-aware); otherwise the flat root's key, but only
|
|
153
|
-
* under the GSD_WORKSTREAM env gate — config-get deliberately does NOT
|
|
154
|
-
* inherit root under GSD_PROJECT alone, and this read must not diverge
|
|
155
|
-
* (#3963). Strict `=== false` (never coerced); any read failure degrades to
|
|
156
|
-
* "not opted out" (worktrees on — the fail-safe direction: the guard keeps
|
|
157
|
-
* enforcing). Direct file reads only — never loadConfig, which normalizes
|
|
158
|
-
* and rewrites config on paths that back sentinel writes.
|
|
149
|
+
* The value one config file sets at `keyPath`, if it sets one at all. Every
|
|
150
|
+
* segment must be an OWN property of a plain (non-null, non-array) object, so
|
|
151
|
+
* an absent, unreadable, or unparseable file — or a non-object anywhere on the
|
|
152
|
+
* path — does not set the key.
|
|
159
153
|
*/
|
|
160
|
-
function
|
|
161
|
-
|
|
162
|
-
// themselves throw on a GSD_PROJECT/GSD_WORKSTREAM value containing path
|
|
163
|
-
// separators or `..`, and this contract ("any failure degrades to not
|
|
164
|
-
// opted out — worktrees on, keep enforcing") must hold for that shape too.
|
|
154
|
+
function ownConfigValue(configPath, keyPath) {
|
|
155
|
+
let node;
|
|
165
156
|
try {
|
|
166
|
-
|
|
157
|
+
node = JSON.parse(String(node_fs_1.default.readFileSync(configPath, 'utf8')));
|
|
167
158
|
}
|
|
168
159
|
catch {
|
|
169
|
-
return
|
|
160
|
+
return CONFIG_VALUE_ABSENT;
|
|
161
|
+
}
|
|
162
|
+
for (const key of keyPath) {
|
|
163
|
+
if (node === null || typeof node !== 'object' || Array.isArray(node))
|
|
164
|
+
return CONFIG_VALUE_ABSENT;
|
|
165
|
+
if (!Object.prototype.hasOwnProperty.call(node, key))
|
|
166
|
+
return CONFIG_VALUE_ABSENT;
|
|
167
|
+
node = node[key];
|
|
170
168
|
}
|
|
169
|
+
return { present: true, value: node };
|
|
171
170
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
171
|
+
/**
|
|
172
|
+
* #3972/#4975: the ONE scope-aware config read for surfaces that must answer
|
|
173
|
+
* with the value `config-get <keyPath>` reports but may not call loadConfig
|
|
174
|
+
* (it normalizes and rewrites config.json, spawns git, and prints warnings).
|
|
175
|
+
* Ladder: the scoped config's OWN key wins (planningDir is project- and
|
|
176
|
+
* workstream-aware); otherwise the flat root's key, but only under the
|
|
177
|
+
* GSD_WORKSTREAM env gate — config-get deliberately does NOT inherit root
|
|
178
|
+
* under GSD_PROJECT alone, and no reader of this ladder may diverge (#3963).
|
|
179
|
+
* An unreadable or unparseable file sets nothing, so the ladder moves on:
|
|
180
|
+
* under GSD_WORKSTREAM a broken workstream config inherits the root's key.
|
|
181
|
+
* That is the one place this read and config-get part ways — for a scoped
|
|
182
|
+
* config.json that exists but cannot be read or parsed, config-get fails
|
|
183
|
+
* with CONFIG_PARSE_FAILED instead of reporting a value.
|
|
184
|
+
* The value is returned uncoerced; each caller applies its own strict
|
|
185
|
+
* comparison. Never throws: planningDir/planningRoot reject a
|
|
186
|
+
* GSD_PROJECT/GSD_WORKSTREAM value containing path separators or `..`, and
|
|
187
|
+
* that shape resolves to "not present".
|
|
188
|
+
*/
|
|
189
|
+
function readScopedConfigValue(cwd, keyPath) {
|
|
190
|
+
try {
|
|
191
|
+
const scoped = ownConfigValue(node_path_1.default.join(planningDir(cwd), 'config.json'), keyPath);
|
|
192
|
+
if (scoped.present)
|
|
193
|
+
return scoped;
|
|
194
|
+
if (resolveEnvWorkstream() !== null) {
|
|
195
|
+
return ownConfigValue(node_path_1.default.join(planningRoot(cwd), 'config.json'), keyPath);
|
|
179
196
|
}
|
|
180
|
-
};
|
|
181
|
-
const ownKey = (cfg) => {
|
|
182
|
-
if (cfg === null || typeof cfg !== 'object')
|
|
183
|
-
return { present: false, value: undefined };
|
|
184
|
-
const wf = cfg.workflow;
|
|
185
|
-
if (wf === null || typeof wf !== 'object' || Array.isArray(wf))
|
|
186
|
-
return { present: false, value: undefined };
|
|
187
|
-
const wfRec = wf;
|
|
188
|
-
return Object.prototype.hasOwnProperty.call(wfRec, 'use_worktrees')
|
|
189
|
-
? { present: true, value: wfRec['use_worktrees'] }
|
|
190
|
-
: { present: false, value: undefined };
|
|
191
|
-
};
|
|
192
|
-
const scoped = ownKey(readCfg(node_path_1.default.join(planningDir(cwd), 'config.json')));
|
|
193
|
-
if (scoped.present)
|
|
194
|
-
return scoped.value === false;
|
|
195
|
-
if (resolveEnvWorkstream() !== null) {
|
|
196
|
-
const root = ownKey(readCfg(node_path_1.default.join(planningRoot(cwd), 'config.json')));
|
|
197
|
-
if (root.present)
|
|
198
|
-
return root.value === false;
|
|
199
197
|
}
|
|
200
|
-
|
|
198
|
+
catch {
|
|
199
|
+
// Degrade to "not present" — see the contract above.
|
|
200
|
+
}
|
|
201
|
+
return CONFIG_VALUE_ABSENT;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* #3972: the ONE owner of "is this planning scope opted out of worktrees?" —
|
|
205
|
+
* the effective `workflow.use_worktrees === false` read every
|
|
206
|
+
* isolation-deciding surface must share (config-get's merged view is the
|
|
207
|
+
* contract), resolved on the readScopedConfigValue ladder. Strict `=== false`
|
|
208
|
+
* (never coerced); a config that cannot be read never opts out by itself
|
|
209
|
+
* (worktrees on — the fail-safe direction: the guard keeps enforcing).
|
|
210
|
+
*/
|
|
211
|
+
function worktreesOptedOut(cwd) {
|
|
212
|
+
const { present, value } = readScopedConfigValue(cwd, ['workflow', 'use_worktrees']);
|
|
213
|
+
return present && value === false;
|
|
201
214
|
}
|
|
202
215
|
/**
|
|
203
216
|
* #612: resolve `phase_id_convention` with the SAME workstream->root federation
|
|
@@ -305,8 +318,8 @@ function listAvailableWorkstreams(cwd) {
|
|
|
305
318
|
function quickDirFrom(planningBase) {
|
|
306
319
|
return node_path_1.default.join(planningBase, 'quick');
|
|
307
320
|
}
|
|
308
|
-
// #4256: the todos directory — deliberately ROOT-SCOPED,
|
|
309
|
-
//
|
|
321
|
+
// #4256: the todos directory — deliberately ROOT-SCOPED, like debug (#5042).
|
|
322
|
+
// Todos are shared project state by construction: the
|
|
310
323
|
// migrateToWorkstreams contract keeps them among the shared files that "stay
|
|
311
324
|
// in place" at .planning/todos/ (workstream.cts), and every workflow writer
|
|
312
325
|
// writes that literal cwd-relative root path. The six todos readers
|
|
@@ -330,6 +343,14 @@ function todosDirFrom(planningBase) {
|
|
|
330
343
|
function todosDir(cwd) {
|
|
331
344
|
return todosDirFrom(planningRoot(cwd));
|
|
332
345
|
}
|
|
346
|
+
// Debug sessions are shared project state: the workflow and debugger agent
|
|
347
|
+
// write them under the root .planning/debug directory in every workstream.
|
|
348
|
+
function debugDirFrom(planningBase) {
|
|
349
|
+
return node_path_1.default.join(planningBase, 'debug');
|
|
350
|
+
}
|
|
351
|
+
function debugDir(cwd) {
|
|
352
|
+
return debugDirFrom(planningRoot(cwd));
|
|
353
|
+
}
|
|
333
354
|
function planningPaths(cwd, ws) {
|
|
334
355
|
const base = planningDir(cwd, ws);
|
|
335
356
|
return {
|
|
@@ -340,14 +361,13 @@ function planningPaths(cwd, ws) {
|
|
|
340
361
|
config: node_path_1.default.join(base, 'config.json'),
|
|
341
362
|
phases: node_path_1.default.join(base, 'phases'),
|
|
342
363
|
requirements: node_path_1.default.join(base, 'REQUIREMENTS.md'),
|
|
343
|
-
// #3149: the debug-session directory
|
|
344
|
-
//
|
|
345
|
-
|
|
346
|
-
debug: node_path_1.default.join(base, 'debug'),
|
|
364
|
+
// #3149/#5042: the debug-session directory shared by state.load,
|
|
365
|
+
// init.debug, and the root-scoped writers.
|
|
366
|
+
debug: debugDir(cwd),
|
|
347
367
|
// #2142: quick-task directory, composed via the shared quickDirFrom helper.
|
|
348
368
|
quick: quickDirFrom(base),
|
|
349
|
-
// #4256: todos directory — deliberately ROOT-scoped
|
|
350
|
-
//
|
|
369
|
+
// #4256: todos directory — deliberately ROOT-scoped like debug, while
|
|
370
|
+
// most other keys follow the active workstream/project (todos are shared
|
|
351
371
|
// project state per the migrateToWorkstreams contract), composed via the
|
|
352
372
|
// shared todosDir helper so this key and every direct caller agree.
|
|
353
373
|
todos: todosDir(cwd),
|
|
@@ -612,6 +632,7 @@ function findContextMdIn(absDirOrFiles) {
|
|
|
612
632
|
}
|
|
613
633
|
module.exports = {
|
|
614
634
|
worktreesOptedOut,
|
|
635
|
+
readScopedConfigValue,
|
|
615
636
|
createPlanningWorkspace,
|
|
616
637
|
createSharedPointerAdapter,
|
|
617
638
|
createSessionScopedPointerAdapter,
|
|
@@ -623,6 +644,8 @@ module.exports = {
|
|
|
623
644
|
listAvailableWorkstreams,
|
|
624
645
|
planningPaths,
|
|
625
646
|
quickDirFrom,
|
|
647
|
+
debugDirFrom,
|
|
648
|
+
debugDir,
|
|
626
649
|
todosDirFrom,
|
|
627
650
|
todosDir,
|
|
628
651
|
withPlanningLock,
|
|
@@ -27,6 +27,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
28
|
exports.sha256File = sha256File;
|
|
29
29
|
exports.findPristineByHash = findPristineByHash;
|
|
30
|
+
exports.isCleanRelativePosixPath = isCleanRelativePosixPath;
|
|
31
|
+
exports.gitExec = gitExec;
|
|
30
32
|
exports.findPristineInGit = findPristineInGit;
|
|
31
33
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
32
34
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -125,6 +127,14 @@ const GIT_MAX_COMMITS_PER_FILE = 100;
|
|
|
125
127
|
const GIT_SUBPROCESS_TIMEOUT_MS = 10_000;
|
|
126
128
|
/** git log --format=%H output cap; 100 full shas are ~4 KB, this is headroom. */
|
|
127
129
|
const GIT_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
130
|
+
/**
|
|
131
|
+
* #5105 review finding 1/4: shared containment guard AND the shared
|
|
132
|
+
* non-trimming `git` subprocess runner, exported so `uat.cts`'s
|
|
133
|
+
* `readBaselineAtHead` (byte-exact `git show HEAD:<path>` read) can route
|
|
134
|
+
* through the same bounded, `windowsHide`d, stderr-discarding call this
|
|
135
|
+
* module already uses, rather than maintaining a second private
|
|
136
|
+
* `execFileSync` wrapper that can drift from this one's timeout/maxBuffer.
|
|
137
|
+
*/
|
|
128
138
|
function isCleanRelativePosixPath(relPath) {
|
|
129
139
|
if (!relPath || relPath.startsWith('/') || relPath.includes('\\') || relPath.includes('\0')) {
|
|
130
140
|
return false;
|
|
@@ -29,6 +29,7 @@ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs")
|
|
|
29
29
|
const runtime_homes_cjs_1 = require("./runtime-homes.cjs");
|
|
30
30
|
const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
|
|
31
31
|
const runtime_name_policy_cjs_1 = require("./runtime-name-policy.cjs");
|
|
32
|
+
const frontmatter_fence_cjs_1 = require("./frontmatter-fence.cjs");
|
|
32
33
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
33
34
|
const DIMENSION_KEYS = [
|
|
34
35
|
'communication_style', 'decision_speed', 'explanation_depth',
|
|
@@ -203,6 +204,7 @@ function buildClaudeMdWorkflowEnforcement(runtime) {
|
|
|
203
204
|
'Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.',
|
|
204
205
|
'',
|
|
205
206
|
'Use these entry points:',
|
|
207
|
+
`- \`${String((0, runtime_slash_cjs_1.formatGsdSlash)('fast', runtime))}\` for a trivial task inline, with no subagents and no PLAN.md`,
|
|
206
208
|
`- \`${String((0, runtime_slash_cjs_1.formatGsdSlash)('quick', runtime))}\` for small fixes, doc updates, and ad-hoc tasks`,
|
|
207
209
|
`- \`${String((0, runtime_slash_cjs_1.formatGsdSlash)('debug', runtime))}\` for investigation and bug fixing`,
|
|
208
210
|
`- \`${String((0, runtime_slash_cjs_1.formatGsdSlash)('execute-phase', runtime))}\` for planned phase work`,
|
|
@@ -477,10 +479,11 @@ function generateSkillsSection(cwd) {
|
|
|
477
479
|
*/
|
|
478
480
|
function extractSkillFrontmatter(content) {
|
|
479
481
|
const result = { name: '', description: '' };
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
// The block is the one the one fence owner (`locateFrontmatterFence`) finds.
|
|
483
|
+
const fence = (0, frontmatter_fence_cjs_1.locateFrontmatterFence)(content);
|
|
484
|
+
if (!fence?.closed)
|
|
482
485
|
return result;
|
|
483
|
-
const fmBlock =
|
|
486
|
+
const fmBlock = content.slice(fence.openEnd, fence.bodyEnd);
|
|
484
487
|
const lines = fmBlock.split('\n');
|
|
485
488
|
let currentKey = '';
|
|
486
489
|
for (const line of lines) {
|
|
@@ -58,14 +58,9 @@ exports.eslintHasFatalError = eslintHasFatalError;
|
|
|
58
58
|
exports.eslintJsonHasRule = eslintJsonHasRule;
|
|
59
59
|
exports.defaultProveFailFirst = defaultProveFailFirst;
|
|
60
60
|
exports.runProhibitionEnforcement = runProhibitionEnforcement;
|
|
61
|
-
exports.routeProhibitionEnforcement = routeProhibitionEnforcement;
|
|
62
61
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
63
62
|
const node_path_1 = __importDefault(require("node:path"));
|
|
64
63
|
const node_child_process_1 = require("node:child_process");
|
|
65
|
-
// Import the leaf I/O module directly (core.cjs re-export spine retired in epic #1267).
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
67
|
-
const io = require("./io.cjs");
|
|
68
|
-
const { output, error, ERROR_REASON } = io;
|
|
69
64
|
const probe_core_cjs_1 = require("./probe-core.cjs");
|
|
70
65
|
/**
|
|
71
66
|
* READ-BACK ADAPTER (#1278, plan 01-03): reconstruct a `CheckDescriptor` from the flat scalar keys
|
|
@@ -730,53 +725,3 @@ function runProhibitionEnforcement(prohibition, check, options = {}) {
|
|
|
730
725
|
...(mode ? { mode } : {}),
|
|
731
726
|
};
|
|
732
727
|
}
|
|
733
|
-
/**
|
|
734
|
-
* Parse a `{ prohibition, check, mode }` request from a JSON file path or inline `--json` string.
|
|
735
|
-
* Returns null on any parse failure (the caller surfaces a structured error, never a throw).
|
|
736
|
-
*/
|
|
737
|
-
function parseRequest(args) {
|
|
738
|
-
// args[0] = 'check', args[1] = 'prohibition-enforcement', args[2] = <json-file-path | --json>
|
|
739
|
-
const jsonFlagIdx = args.indexOf('--json');
|
|
740
|
-
let payload = '';
|
|
741
|
-
if (jsonFlagIdx !== -1 && typeof args[jsonFlagIdx + 1] === 'string') {
|
|
742
|
-
payload = args[jsonFlagIdx + 1];
|
|
743
|
-
}
|
|
744
|
-
else if (typeof args[2] === 'string' && args[2]) {
|
|
745
|
-
try {
|
|
746
|
-
payload = node_fs_1.default.readFileSync(args[2], 'utf-8');
|
|
747
|
-
}
|
|
748
|
-
catch {
|
|
749
|
-
return null;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
return null;
|
|
754
|
-
}
|
|
755
|
-
try {
|
|
756
|
-
const parsed = JSON.parse(payload);
|
|
757
|
-
const checkRaw = parsed['check'];
|
|
758
|
-
const check = (checkRaw && typeof checkRaw === 'object')
|
|
759
|
-
? checkRaw
|
|
760
|
-
: null;
|
|
761
|
-
const modeRaw = parsed['mode'];
|
|
762
|
-
const mode = typeof modeRaw === 'string' ? modeRaw : undefined;
|
|
763
|
-
return { prohibition: parsed['prohibition'] ?? null, check, ...(mode ? { mode } : {}) };
|
|
764
|
-
}
|
|
765
|
-
catch {
|
|
766
|
-
return null;
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* CLI surface: `gsd_run check prohibition-enforcement <request.json>` (or `--json '<inline>'`).
|
|
771
|
-
* Parses the request, runs the producer, and emits the result as JSON. Honors the no-throw
|
|
772
|
-
* contract: malformed input -> structured `error(...)`, never an uncaught throw.
|
|
773
|
-
*/
|
|
774
|
-
function routeProhibitionEnforcement(args, raw) {
|
|
775
|
-
const req = parseRequest(args);
|
|
776
|
-
if (!req) {
|
|
777
|
-
error('prohibition-enforcement requires a JSON request: check prohibition-enforcement <request.json> | --json \'{"prohibition":{...},"check":{...}}\'', ERROR_REASON.SDK_MISSING_ARG);
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
const result = runProhibitionEnforcement(req.prohibition, req.check, req.mode ? { mode: req.mode } : {});
|
|
781
|
-
output(result, raw, undefined);
|
|
782
|
-
}
|
|
@@ -35,9 +35,19 @@ const commandRoutingHub = require("./command-routing-hub.cjs");
|
|
|
35
35
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
36
|
const cjsCommandRouterAdapter = require("./cjs-command-router-adapter.cjs");
|
|
37
37
|
const security_cjs_1 = require("./security.cjs");
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
39
|
+
const nodeFs = require("node:fs");
|
|
40
|
+
// #5118: the writer set is owned by src/verification.cts.
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
42
|
+
const verificationMod = require("./verification.cjs");
|
|
38
43
|
const { output, ERROR_REASON } = io;
|
|
44
|
+
const { VERIFIER_STATUSES } = verificationMod;
|
|
39
45
|
const { makeInvalidArgs } = commandRoutingHub;
|
|
40
46
|
const { routeHubCommandFamily } = cjsCommandRouterAdapter;
|
|
47
|
+
/** Default stdin reader for `parse-args --stdin` (fd 0, UTF-8, whole stream). */
|
|
48
|
+
function readProcessStdin() {
|
|
49
|
+
return nodeFs.readFileSync(0, 'utf8');
|
|
50
|
+
}
|
|
41
51
|
// ─── Small arg-parsing helpers (local — no new shared convention needed) ────
|
|
42
52
|
/** `--flag value` lookup; undefined when the flag is absent. */
|
|
43
53
|
function argValue(args, flag) {
|
|
@@ -57,7 +67,7 @@ function parseJsonArg(raw, label) {
|
|
|
57
67
|
return { ok: true, value: parsed.value };
|
|
58
68
|
}
|
|
59
69
|
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
60
|
-
function routeQuickBatchCommand({ args, cwd, raw, error, _quickBatch, _quickBatchDispatch }) {
|
|
70
|
+
function routeQuickBatchCommand({ args, cwd, raw, error, _quickBatch, _quickBatchDispatch, _readStdin }) {
|
|
61
71
|
const qb = _quickBatch ?? quickBatch;
|
|
62
72
|
const dispatch = _quickBatchDispatch ?? quickBatchDispatch;
|
|
63
73
|
/** Forward a `Result<T>` from either module straight to output()/error(). */
|
|
@@ -211,7 +221,7 @@ function routeQuickBatchCommand({ args, cwd, raw, error, _quickBatch, _quickBatc
|
|
|
211
221
|
// `quick-batch verification-routing --status <passed|gaps_found|human_needed>`
|
|
212
222
|
'verification-routing': () => {
|
|
213
223
|
const status = argValue(args, '--status');
|
|
214
|
-
if (
|
|
224
|
+
if (typeof status !== 'string' || !VERIFIER_STATUSES.has(status)) {
|
|
215
225
|
return makeInvalidArgs('--status', 'Usage: gsd-tools quick-batch verification-routing --status <passed|gaps_found|human_needed>', ERROR_REASON.USAGE);
|
|
216
226
|
}
|
|
217
227
|
output(dispatch.routeVerificationOutcome(status), raw);
|
|
@@ -252,17 +262,33 @@ function routeQuickBatchCommand({ args, cwd, raw, error, _quickBatch, _quickBatc
|
|
|
252
262
|
planContent,
|
|
253
263
|
}), raw);
|
|
254
264
|
},
|
|
255
|
-
// `quick-batch parse-args --
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
// the
|
|
265
|
+
// `quick-batch parse-args --stdin` (preferred, #4780 — the caller feeds
|
|
266
|
+
// the typed text through a QUOTED heredoc, so the shell never parses it:
|
|
267
|
+
// quotes, `$(...)`, backticks and newlines in attacker-influenced task
|
|
268
|
+
// text cannot break out of any shell position, because there is no
|
|
269
|
+
// shell position for the text to occupy).
|
|
270
|
+
// `quick-batch parse-args --text "<raw string>"` (still supported for a
|
|
271
|
+
// caller that already holds the text as ONE real argv element with no
|
|
272
|
+
// shell quoting involved, e.g. a test harness; it is NOT safe to build
|
|
273
|
+
// that argument by splicing user text into a shell command line).
|
|
274
|
+
// In both forms this handler does the whitespace split itself, in Node,
|
|
275
|
+
// so shell pathname expansion (globbing) never happens.
|
|
262
276
|
// `quick-batch parse-args -- <already-tokenized args>` (legacy/direct
|
|
263
277
|
// form — still supported for a caller that already has a real argv
|
|
264
278
|
// array with no shell splitting involved, e.g. a test harness).
|
|
265
279
|
'parse-args': () => {
|
|
280
|
+
if (args.includes('--stdin')) {
|
|
281
|
+
let stdinText;
|
|
282
|
+
try {
|
|
283
|
+
stdinText = (_readStdin ?? readProcessStdin)();
|
|
284
|
+
}
|
|
285
|
+
catch (readError) {
|
|
286
|
+
return makeInvalidArgs('--stdin', `could not read standard input: ${readError instanceof Error ? readError.message : String(readError)}`, ERROR_REASON.USAGE);
|
|
287
|
+
}
|
|
288
|
+
const stdinTokens = stdinText.trim().length === 0 ? [] : stdinText.trim().split(/\s+/);
|
|
289
|
+
emit(dispatch.parseQuickBatchArgs(stdinTokens));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
266
292
|
const textArg = argValue(args, '--text');
|
|
267
293
|
if (textArg !== undefined) {
|
|
268
294
|
const rawArgs = textArg.trim().length === 0 ? [] : textArg.trim().split(/\s+/);
|
|
@@ -140,6 +140,16 @@ function computeSpawnPlan(input) {
|
|
|
140
140
|
}
|
|
141
141
|
return { spawn, pending };
|
|
142
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* #5118: one routing entry per writer-set status, keyed by the owner's type —
|
|
145
|
+
* no status literal is compared (local/no-verification-status-literal's
|
|
146
|
+
* type-aware arm), and `Record<VerifierStatus, …>` makes the table total.
|
|
147
|
+
*/
|
|
148
|
+
const VERIFICATION_OUTCOME_ROUTES = Object.freeze({
|
|
149
|
+
passed: { action: 'complete' },
|
|
150
|
+
human_needed: { action: 'human_needed' },
|
|
151
|
+
gaps_found: { action: 'fail', failureReason: 'verification reported gaps_found (no automatic gap-fix retry in v1)' },
|
|
152
|
+
});
|
|
143
153
|
/**
|
|
144
154
|
* Route a verifier's status to an item action. `human_needed` is terminal
|
|
145
155
|
* for the item — the caller must NOT call `completeQuickItem` (row 30, no
|
|
@@ -147,14 +157,7 @@ function computeSpawnPlan(input) {
|
|
|
147
157
|
* WITHOUT an automatic gap-fix retry (row 31,34). `passed` completes it.
|
|
148
158
|
*/
|
|
149
159
|
function routeVerificationOutcome(status) {
|
|
150
|
-
|
|
151
|
-
case 'passed':
|
|
152
|
-
return { action: 'complete' };
|
|
153
|
-
case 'human_needed':
|
|
154
|
-
return { action: 'human_needed' };
|
|
155
|
-
case 'gaps_found':
|
|
156
|
-
return { action: 'fail', failureReason: 'verification reported gaps_found (no automatic gap-fix retry in v1)' };
|
|
157
|
-
}
|
|
160
|
+
return VERIFICATION_OUTCOME_ROUTES[status];
|
|
158
161
|
}
|
|
159
162
|
/**
|
|
160
163
|
* Route a merge attempt's outcome to an item action. Both `merge_failed`
|
|
@@ -105,6 +105,14 @@ const SANDBOX_MARKER = 'GSD_TEST_HOME_SANDBOX';
|
|
|
105
105
|
* `statSync` follows symlinks and reports the inode itself, so a case-variant
|
|
106
106
|
* HOME, a symlinked HOME, and a bind-mounted HOME all compare equal.
|
|
107
107
|
*
|
|
108
|
+
* `identify` calls `fs.statSync(p, { bigint: true })`, not the plain numeric
|
|
109
|
+
* form. Node documents that the default numeric `dev`/`ino` lose precision past
|
|
110
|
+
* `Number.MAX_SAFE_INTEGER` (2^53), and NTFS/ReFS file IDs routinely exceed
|
|
111
|
+
* that — so on Windows two DISTINCT directories can round to the same numeric
|
|
112
|
+
* `ino` and compare equal here, which is a fail-OPEN in a module whose whole
|
|
113
|
+
* job is refusing writes into the real home. `{ bigint: true }` reports the
|
|
114
|
+
* true 64-bit values with no precision loss.
|
|
115
|
+
*
|
|
108
116
|
* Fails CLOSED, and "closed" here means returning FALSE. The sole caller is the
|
|
109
117
|
* passwd-less marker branch, which READS a true as permission to proceed:
|
|
110
118
|
*
|
|
@@ -130,7 +138,7 @@ function sameDirectory(a, b) {
|
|
|
130
138
|
}
|
|
131
139
|
function identify(p) {
|
|
132
140
|
try {
|
|
133
|
-
const st = node_fs_1.default.statSync(p);
|
|
141
|
+
const st = node_fs_1.default.statSync(p, { bigint: true });
|
|
134
142
|
return { kind: 'ok', dev: st.dev, ino: st.ino };
|
|
135
143
|
}
|
|
136
144
|
catch (err) {
|