@opengsd/gsd-core 1.10.0 → 1.11.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-debug-session-manager.md +11 -0
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +5 -5
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +37 -0
- package/agents/gsd-planner.md +44 -46
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +12 -3
- package/bin/install.js +841 -971
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.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 +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +469 -88
- package/gsd-core/bin/lib/active-workstream-store.cjs +138 -22
- package/gsd-core/bin/lib/agent-install-check.cjs +230 -32
- package/gsd-core/bin/lib/api-coverage.cjs +3 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +876 -240
- package/gsd-core/bin/lib/broken-windows.cjs +1 -1
- 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-registry.cjs +575 -101
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +495 -22
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +71 -37
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +651 -86
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +75 -0
- package/gsd-core/bin/lib/config.cjs +10 -1
- package/gsd-core/bin/lib/core-utils.cjs +127 -29
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +155 -20
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/git-base-branch.cjs +102 -0
- 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 +145 -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 +265 -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 +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init.cjs +321 -129
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +745 -258
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +134 -57
- 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-migrations.cjs +138 -31
- package/gsd-core/bin/lib/io.cjs +10 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +754 -70
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +444 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +125 -18
- package/gsd-core/bin/lib/phase.cjs +646 -143
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +13 -4
- 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 +34 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +943 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +385 -94
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +608 -46
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +426 -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 +115 -3
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +275 -3
- package/gsd-core/bin/lib/smart-entry.cjs +142 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +371 -117
- package/gsd-core/bin/lib/state.cjs +1794 -357
- package/gsd-core/bin/lib/surface.cjs +23 -9
- 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 +9 -3
- package/gsd-core/bin/lib/uat.cjs +399 -56
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +24 -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.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -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 +258 -8
- package/gsd-core/bin/lib/verify.cjs +368 -888
- 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.cjs +2 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +176 -9
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +7 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- 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 +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/autonomous.md +1 -1
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +13 -3
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +38 -12
- package/gsd-core/workflows/complete-milestone.md +141 -18
- package/gsd-core/workflows/debug.md +7 -5
- package/gsd-core/workflows/diagnose-issues.md +35 -9
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -1
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +31 -6
- 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 +2 -0
- package/gsd-core/workflows/execute-phase.md +38 -50
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +5 -5
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone.md +14 -9
- package/gsd-core/workflows/new-project.md +14 -14
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase.md +41 -17
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress.md +34 -6
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -4
- package/gsd-core/workflows/quick/steps/quick-verification.md +27 -6
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -2
- package/gsd-core/workflows/quick.md +35 -15
- package/gsd-core/workflows/review.md +26 -5
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/spec-phase.md +30 -12
- package/gsd-core/workflows/sync-skills.md +63 -8
- package/gsd-core/workflows/transition.md +46 -11
- package/gsd-core/workflows/ui-phase.md +5 -5
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update.md +1 -1
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +9 -7
- package/hooks/dist/gsd-agent-isolation-guard.js +103 -14
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +77 -2
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +38 -24
- package/hooks/dist/gsd-statusline.js +18 -0
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/lib/git-cmd.js +92 -59
- 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/gsd-agent-isolation-guard.js +103 -14
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +77 -2
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +38 -24
- package/hooks/gsd-statusline.js +18 -0
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/lib/git-cmd.js +92 -59
- 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/package.json +21 -9
- package/pi/gsd.cjs +19 -5
- 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/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -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-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -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 +434 -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 +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +21 -10
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +25 -0
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- 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 +1 -1
- 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/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/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Static frontend-evidence detector — plan-time structural corroboration for the
|
|
4
|
+
* UI plan gate (#3312).
|
|
5
|
+
*
|
|
6
|
+
* `checkUiPresence` (ui-safety-gate.cjs) is a *vocabulary* signal: a hyphen is a
|
|
7
|
+
* word boundary, so a phase section naming the repo `dashboard-financeiro` matches
|
|
8
|
+
* the token `dashboard` exactly like the real UI compound `micro-frontend` does.
|
|
9
|
+
* That boundary rule is intentional (#3718) and must not be weakened — instead,
|
|
10
|
+
* the plan gate (`computeUiPlanGate` in check-command-router.cjs) corroborates the
|
|
11
|
+
* token match against the static repo tree before blocking.
|
|
12
|
+
*
|
|
13
|
+
* This mirrors what the sibling post-wave gate (`computeUiSafetyGate`) already
|
|
14
|
+
* does dynamically: it blocks only when `git diff HEAD~1 HEAD` touches UI files.
|
|
15
|
+
* Plan time has no diff to inspect, so the corroboration here is static:
|
|
16
|
+
*
|
|
17
|
+
* (a) a `package.json` (root) with a known UI-framework dependency — a project
|
|
18
|
+
* that ships react/vue/svelte/... in its manifest is a frontend regardless
|
|
19
|
+
* of file layout;
|
|
20
|
+
* (b) any `*.tsx` / `*.jsx` / `*.vue` / `*.svelte` file in the tree — the
|
|
21
|
+
* component-framework subset of `UI_FILE_EXTENSIONS_RE`
|
|
22
|
+
* (check-command-router.cjs). The weaker members of that list (css, scss,
|
|
23
|
+
* html, ...) are deliberately NOT static evidence: docs sites and
|
|
24
|
+
* markdown/bash/config repos routinely carry stray `.html`/`.css`, which
|
|
25
|
+
* is precisely the false-positive class #3312 reports.
|
|
26
|
+
*
|
|
27
|
+
* All I/O failures degrade to `false` (no evidence) — never throw.
|
|
28
|
+
*/
|
|
29
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
30
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
|
+
};
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.UI_COMPONENT_FILE_RE = void 0;
|
|
34
|
+
exports.hasStaticFrontendEvidence = hasStaticFrontendEvidence;
|
|
35
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
36
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
37
|
+
/** Component-framework file extensions — the static-evidence subset of UI_FILE_EXTENSIONS_RE. */
|
|
38
|
+
exports.UI_COMPONENT_FILE_RE = /\.(tsx|jsx|vue|svelte)$/i;
|
|
39
|
+
/**
|
|
40
|
+
* UI-framework package.json dependencies (dependencies OR devDependencies).
|
|
41
|
+
* Component frameworks/renderers only — deliberately excludes meta tooling
|
|
42
|
+
* (typescript, eslint, ...) that non-frontend Node projects also carry.
|
|
43
|
+
*/
|
|
44
|
+
const UI_FRAMEWORK_DEPS = new Set([
|
|
45
|
+
'react',
|
|
46
|
+
'react-dom',
|
|
47
|
+
'vue',
|
|
48
|
+
'svelte',
|
|
49
|
+
'@sveltejs/kit',
|
|
50
|
+
'angular',
|
|
51
|
+
'@angular/core',
|
|
52
|
+
'preact',
|
|
53
|
+
'solid-js',
|
|
54
|
+
'lit',
|
|
55
|
+
'lit-element',
|
|
56
|
+
'ember-source',
|
|
57
|
+
'@remix-run/react',
|
|
58
|
+
'react-native',
|
|
59
|
+
'expo',
|
|
60
|
+
'next',
|
|
61
|
+
'nuxt',
|
|
62
|
+
'gatsby',
|
|
63
|
+
'astro',
|
|
64
|
+
'@ionic/react',
|
|
65
|
+
'@ionic/vue',
|
|
66
|
+
'@ionic/angular',
|
|
67
|
+
]);
|
|
68
|
+
/** Directories never walked — dependencies, VCS data, build output, GSD planning state. */
|
|
69
|
+
const SKIP_DIRS = new Set([
|
|
70
|
+
'node_modules',
|
|
71
|
+
'.git',
|
|
72
|
+
'.planning',
|
|
73
|
+
'dist',
|
|
74
|
+
'build',
|
|
75
|
+
'out',
|
|
76
|
+
'.next',
|
|
77
|
+
'.nuxt',
|
|
78
|
+
'.output',
|
|
79
|
+
'coverage',
|
|
80
|
+
'vendor',
|
|
81
|
+
'.cache',
|
|
82
|
+
]);
|
|
83
|
+
/** Walk safety cap — beyond this the tree is treated as scanned (evidence decided by then). */
|
|
84
|
+
const MAX_WALK_ENTRIES = 10_000;
|
|
85
|
+
function packageJsonHasUiFramework(projectDir) {
|
|
86
|
+
let raw;
|
|
87
|
+
try {
|
|
88
|
+
raw = node_fs_1.default.readFileSync(node_path_1.default.join(projectDir, 'package.json'), 'utf8');
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false; // no/unreadable package.json → no evidence from this signal
|
|
92
|
+
}
|
|
93
|
+
let parsed;
|
|
94
|
+
try {
|
|
95
|
+
parsed = JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return false; // malformed package.json → no evidence from this signal
|
|
99
|
+
}
|
|
100
|
+
if (parsed === null || typeof parsed !== 'object')
|
|
101
|
+
return false;
|
|
102
|
+
const pkg = parsed;
|
|
103
|
+
for (const field of ['dependencies', 'devDependencies', 'peerDependencies']) {
|
|
104
|
+
const deps = pkg[field];
|
|
105
|
+
if (deps === null || typeof deps !== 'object')
|
|
106
|
+
continue;
|
|
107
|
+
for (const name of Object.keys(deps)) {
|
|
108
|
+
if (UI_FRAMEWORK_DEPS.has(name))
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
function treeHasComponentFile(projectDir) {
|
|
115
|
+
// Iterative BFS — bounded by MAX_WALK_ENTRIES so a pathological tree cannot
|
|
116
|
+
// stall the gate. Symlinks are never followed (withFileTypes + isDirectory).
|
|
117
|
+
const queue = [projectDir];
|
|
118
|
+
let visited = 0;
|
|
119
|
+
while (queue.length > 0 && visited < MAX_WALK_ENTRIES) {
|
|
120
|
+
const dir = queue.shift();
|
|
121
|
+
let entries;
|
|
122
|
+
try {
|
|
123
|
+
entries = node_fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
continue; // unreadable directory → skip it
|
|
127
|
+
}
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
visited++;
|
|
130
|
+
if (visited >= MAX_WALK_ENTRIES)
|
|
131
|
+
return false;
|
|
132
|
+
if (entry.isDirectory()) {
|
|
133
|
+
if (!SKIP_DIRS.has(entry.name))
|
|
134
|
+
queue.push(node_path_1.default.join(dir, entry.name));
|
|
135
|
+
}
|
|
136
|
+
else if (entry.isFile() && exports.UI_COMPONENT_FILE_RE.test(entry.name)) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Does the project tree carry static evidence of a frontend?
|
|
145
|
+
*
|
|
146
|
+
* @param projectDir - Absolute path to the project root (the gate's cwd).
|
|
147
|
+
* @returns true when package.json declares a UI-framework dependency or the
|
|
148
|
+
* tree contains a component-framework file; false otherwise (including
|
|
149
|
+
* on any I/O failure — evidence must be affirmative).
|
|
150
|
+
*/
|
|
151
|
+
function hasStaticFrontendEvidence(projectDir) {
|
|
152
|
+
if (typeof projectDir !== 'string' || projectDir === '')
|
|
153
|
+
return false;
|
|
154
|
+
if (packageJsonHasUiFramework(projectDir))
|
|
155
|
+
return true;
|
|
156
|
+
return treeHasComponentFile(projectDir);
|
|
157
|
+
}
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
* matched; "micro-frontend" and "micro frontend" ARE matched).
|
|
18
18
|
*
|
|
19
19
|
* Public API:
|
|
20
|
-
* checkUiPresence(text: string): { hasUI: boolean, tokens: string[]
|
|
20
|
+
* checkUiPresence(text: string): { hasUI: boolean, tokens: string[],
|
|
21
|
+
* matchedToken: string|null, matchedLine: string|null }
|
|
21
22
|
*
|
|
22
23
|
* CLI usage — reads phase-section text from STDIN to avoid ARG_MAX limits:
|
|
23
24
|
* echo "$PHASE_SECTION" | node gsd-core/bin/lib/ui-safety-gate.cjs
|
|
@@ -63,7 +64,7 @@ const UI_GATE_PATTERN_GLOBAL = new RegExp(UI_GATE_PATTERN.source, 'gi');
|
|
|
63
64
|
*/
|
|
64
65
|
function checkUiPresence(text) {
|
|
65
66
|
if (typeof text !== 'string') {
|
|
66
|
-
return { hasUI: false, tokens: [] };
|
|
67
|
+
return { hasUI: false, tokens: [], matchedToken: null, matchedLine: null };
|
|
67
68
|
}
|
|
68
69
|
// Normalise CRLF so the pattern sees consistent line boundaries.
|
|
69
70
|
const normalised = text.replace(/\r\n/g, '\n');
|
|
@@ -84,20 +85,28 @@ function checkUiPresence(text) {
|
|
|
84
85
|
.filter((line) => !/^\s*\*\*UI hint\*\*\s*:/i.test(line))
|
|
85
86
|
.join('\n');
|
|
86
87
|
const found = new Set();
|
|
88
|
+
let matchedToken = null;
|
|
89
|
+
let matchedLine = null;
|
|
87
90
|
for (const line of sniffable.split('\n')) {
|
|
88
91
|
// Reset lastIndex before each line so the global pattern restarts from 0.
|
|
89
92
|
UI_GATE_PATTERN_GLOBAL.lastIndex = 0;
|
|
90
93
|
for (const m of line.matchAll(UI_GATE_PATTERN_GLOBAL)) {
|
|
94
|
+
if (matchedToken === null) {
|
|
95
|
+
// #3312: record the FIRST match so gate consumers can surface the
|
|
96
|
+
// triggering token/line for one-second operator triage.
|
|
97
|
+
matchedToken = m[2].toLowerCase();
|
|
98
|
+
matchedLine = line;
|
|
99
|
+
}
|
|
91
100
|
found.add(m[2].toLowerCase());
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
103
|
if (hint === 'no') {
|
|
95
|
-
return { hasUI: false, tokens: [] };
|
|
104
|
+
return { hasUI: false, tokens: [], matchedToken: null, matchedLine: null };
|
|
96
105
|
}
|
|
97
106
|
if (hint === 'yes') {
|
|
98
|
-
return { hasUI: true, tokens: [...found] };
|
|
107
|
+
return { hasUI: true, tokens: [...found], matchedToken, matchedLine };
|
|
99
108
|
}
|
|
100
|
-
return { hasUI: found.size > 0, tokens: [...found] };
|
|
109
|
+
return { hasUI: found.size > 0, tokens: [...found], matchedToken, matchedLine };
|
|
101
110
|
}
|
|
102
111
|
// ── CLI entry point ─────────────────────────────────────────────────────────
|
|
103
112
|
// Reads phase-section text from STDIN (not argv) to avoid OS ARG_MAX limits.
|
|
@@ -58,12 +58,36 @@ const UNUSABLE_REASON = Object.freeze({
|
|
|
58
58
|
* silent degradation is visible. (#3099, sixth #1879 site)
|
|
59
59
|
*/
|
|
60
60
|
LAST_ACTIVITY_UNPARSEABLE: 'last_activity_unparseable',
|
|
61
|
+
/**
|
|
62
|
+
* A STATE.md exists but could not be read (EACCES/EIO/…). Distinct from a project that has
|
|
63
|
+
* not run `state.init` yet: absence returns the same non-answer, silently — only an
|
|
64
|
+
* exists-but-unreadable STATE.md is corruption. (#3308, seventh #1879 site —
|
|
65
|
+
* planning-snapshot's current-phase field)
|
|
66
|
+
*/
|
|
67
|
+
STATE_UNREADABLE: 'state_unreadable',
|
|
68
|
+
/**
|
|
69
|
+
* A config.json exists but could not be read/parsed (EACCES/EIO/malformed JSON/…).
|
|
70
|
+
* Distinct from a project that has not run any config-writing command yet: absence
|
|
71
|
+
* returns the same non-answer, silently — only an exists-but-unreadable config.json
|
|
72
|
+
* is corruption. (#3309, eighth #1879 site — planning-snapshot's config field)
|
|
73
|
+
*/
|
|
74
|
+
CONFIG_UNREADABLE: 'config_unreadable',
|
|
75
|
+
/**
|
|
76
|
+
* A PROJECT.md exists but could not be read (EACCES/EIO/…). Distinct from a project that has
|
|
77
|
+
* not run any project-writing command yet: absence returns the same non-answer, silently —
|
|
78
|
+
* only an exists-but-unreadable PROJECT.md is corruption. (#3309, ninth #1879 site —
|
|
79
|
+
* planning-snapshot's projectSections field)
|
|
80
|
+
*/
|
|
81
|
+
PROJECT_UNREADABLE: 'project_unreadable',
|
|
61
82
|
});
|
|
62
83
|
/** One human-readable clause per reason. Prose lives here, never in a test assertion. */
|
|
63
84
|
const REASON_PROSE = Object.freeze({
|
|
64
85
|
[UNUSABLE_REASON.FRONTMATTER_UNTERMINATED]: 'frontmatter opens with "---" but never closes; metadata was NOT applied',
|
|
65
86
|
[UNUSABLE_REASON.ROADMAP_UNREADABLE]: 'ROADMAP.md exists but could not be read; phase and milestone lookups fell back to defaults',
|
|
66
87
|
[UNUSABLE_REASON.LAST_ACTIVITY_UNPARSEABLE]: 'last_activity in STATE.md is present but unparseable as a date; stale_activity fell back to false (idle-stranded suppressed)',
|
|
88
|
+
[UNUSABLE_REASON.STATE_UNREADABLE]: 'STATE.md exists but could not be read; the current-phase label fell back to unavailable',
|
|
89
|
+
[UNUSABLE_REASON.CONFIG_UNREADABLE]: 'config.json exists but could not be read or parsed; the config field fell back to unavailable',
|
|
90
|
+
[UNUSABLE_REASON.PROJECT_UNREADABLE]: 'PROJECT.md exists but could not be read; the projectSections field fell back to unavailable',
|
|
67
91
|
});
|
|
68
92
|
// ─── Dedup state ──────────────────────────────────────────────────────────────
|
|
69
93
|
/**
|
|
@@ -10,7 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.RUNTIME_DIRS = void 0;
|
|
13
|
+
exports.CODEX_CONFIG_MARKER = exports.RUNTIME_DIRS = void 0;
|
|
14
14
|
exports.inferPreferredRuntime = inferPreferredRuntime;
|
|
15
15
|
exports.envRuntimeDirs = envRuntimeDirs;
|
|
16
16
|
exports.resolveUpdateContext = resolveUpdateContext;
|
|
@@ -38,6 +38,12 @@ exports.RUNTIME_DIRS = [
|
|
|
38
38
|
['codex', '.codex'],
|
|
39
39
|
];
|
|
40
40
|
const SEMVER_PREFIX = /^\d+\.\d+\.\d+/;
|
|
41
|
+
// Shared Codex config-root marker filename. Single-sourced here (this module
|
|
42
|
+
// is the pre-existing, dependency-free owner) and re-exported by
|
|
43
|
+
// host-runtime-detection.cts, whose detection rung reuses this exact probe
|
|
44
|
+
// filename (though NOT the truthiness rule below — see that module's header
|
|
45
|
+
// comment for the deliberate divergence).
|
|
46
|
+
exports.CODEX_CONFIG_MARKER = 'config.toml';
|
|
41
47
|
function expandHome(p, home) {
|
|
42
48
|
if (!p)
|
|
43
49
|
return '';
|
|
@@ -72,7 +78,7 @@ function inferPreferredRuntime({ fs, env, preferredConfigDir }) {
|
|
|
72
78
|
if (fs.exists(node_path_1.default.join(preferredConfigDir, 'opencode.json')) ||
|
|
73
79
|
fs.exists(node_path_1.default.join(preferredConfigDir, 'opencode.jsonc')))
|
|
74
80
|
return 'opencode';
|
|
75
|
-
if (fs.exists(node_path_1.default.join(preferredConfigDir,
|
|
81
|
+
if (fs.exists(node_path_1.default.join(preferredConfigDir, exports.CODEX_CONFIG_MARKER)))
|
|
76
82
|
return 'codex';
|
|
77
83
|
}
|
|
78
84
|
if (env['CODEX_HOME'])
|