@opengsd/gsd-core 1.18.0 → 1.19.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 +2 -1
- package/.opencode/plugins/gsd-core.js +2 -3
- package/agents/gsd-code-fixer.compact.md +2 -2
- package/agents/gsd-code-fixer.md +4 -3
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +422 -103
- package/gsd-core/bin/gsd-tools.cjs +106 -7
- package/gsd-core/bin/lib/agent-install-check.cjs +29 -3
- package/gsd-core/bin/lib/args-terminator.cjs +114 -0
- package/gsd-core/bin/lib/broken-windows.cjs +59 -1
- package/gsd-core/bin/lib/capability-lock.cjs +13 -2
- package/gsd-core/bin/lib/capability-registry.cjs +156 -74
- package/gsd-core/bin/lib/capability-state.cjs +14 -8
- package/gsd-core/bin/lib/capability-validator.cjs +17 -0
- package/gsd-core/bin/lib/config-loader.cjs +10 -0
- package/gsd-core/bin/lib/config.cjs +256 -58
- package/gsd-core/bin/lib/core-utils.cjs +34 -0
- package/gsd-core/bin/lib/decision-coverage-support.cjs +74 -0
- package/gsd-core/bin/lib/gate-context-drift.cjs +8 -3
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +6 -1
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +6 -1
- package/gsd-core/bin/lib/gate-evaluation-scope.cjs +134 -13
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +63 -22
- package/gsd-core/bin/lib/gate-ui-safety.cjs +23 -5
- package/gsd-core/bin/lib/git-info-exclude.cjs +57 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +18 -3
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +4 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +52 -1
- package/gsd-core/bin/lib/host-integration.cjs +13 -6
- package/gsd-core/bin/lib/init.cjs +65 -1
- package/gsd-core/bin/lib/install-engine.cjs +246 -32
- package/gsd-core/bin/lib/install-profiles.cjs +9 -4
- package/gsd-core/bin/lib/installer-migration-report.cjs +2 -0
- package/gsd-core/bin/lib/markdown-line-diff.cjs +147 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +113 -0
- package/gsd-core/bin/lib/milestone-lock.cjs +8 -1
- package/gsd-core/bin/lib/milestone-release-map.cjs +244 -0
- package/gsd-core/bin/lib/milestone-release-tags.cjs +440 -0
- package/gsd-core/bin/lib/milestone.cjs +43 -1
- package/gsd-core/bin/lib/model-catalog.cjs +8 -0
- package/gsd-core/bin/lib/normalize-test-command.cjs +67 -0
- package/gsd-core/bin/lib/phase-id.cjs +21 -4
- package/gsd-core/bin/lib/phase-lifecycle.cjs +37 -4
- package/gsd-core/bin/lib/phase.cjs +115 -26
- package/gsd-core/bin/lib/planning-snapshot.cjs +3 -1
- package/gsd-core/bin/lib/planning-workspace.cjs +18 -0
- package/gsd-core/bin/lib/pristine-baseline.cjs +11 -3
- package/gsd-core/bin/lib/read-only-git-env.cjs +58 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +35 -2
- package/gsd-core/bin/lib/review-lane-runner.cjs +33 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +12 -0
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +39 -2
- package/gsd-core/bin/lib/roadmap.cjs +33 -25
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +381 -14
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +8 -4
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +60 -16
- package/gsd-core/bin/lib/shell-command-projection.cjs +121 -16
- package/gsd-core/bin/lib/smart-entry.cjs +13 -0
- package/gsd-core/bin/lib/state-contract.cjs +29 -9
- package/gsd-core/bin/lib/state-document.cjs +12 -4
- package/gsd-core/bin/lib/state-transition.cjs +119 -24
- package/gsd-core/bin/lib/state.cjs +50 -28
- package/gsd-core/bin/lib/surface.cjs +9 -0
- package/gsd-core/bin/lib/task-command-router.cjs +5 -25
- package/gsd-core/bin/lib/task-content-resolution.cjs +46 -1
- package/gsd-core/bin/lib/verification.cjs +96 -9
- package/gsd-core/bin/lib/verify.cjs +2 -0
- package/gsd-core/bin/lib/worktree-safety.cjs +22 -1
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
- package/gsd-core/references/git-integration.md +11 -0
- package/gsd-core/references/loop-hook-dispatch.md +13 -6
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/tdd.md +2 -2
- package/gsd-core/templates/DEBUG.md +16 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/templates/verification-report.md +1 -1
- package/gsd-core/workflows/audit-fix.md +2 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +10 -1
- package/gsd-core/workflows/code-review.md +61 -7
- package/gsd-core/workflows/complete-milestone/steps/project-md-evolution-review.md +145 -0
- package/gsd-core/workflows/complete-milestone/steps/release-map.md +80 -0
- package/gsd-core/workflows/complete-milestone.md +37 -150
- package/gsd-core/workflows/diagnose-issues.md +29 -5
- package/gsd-core/workflows/discuss-phase/modes/power.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +33 -2
- package/gsd-core/workflows/discuss-phase-power.md +19 -2
- package/gsd-core/workflows/discuss-phase.md +6 -10
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +13 -7
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +7 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +2 -2
- package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +11 -2
- package/gsd-core/workflows/execute-phase.md +9 -5
- package/gsd-core/workflows/health.md +2 -1
- package/gsd-core/workflows/import.md +1 -1
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +2 -2
- package/gsd-core/workflows/plan-phase.md +13 -13
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +1 -1
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +8 -1
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +2 -1
- package/gsd-core/workflows/quick.md +1 -1
- package/gsd-core/workflows/review.md +16 -13
- package/gsd-core/workflows/section-manifest.json +5 -0
- package/gsd-core/workflows/settings.md +1 -0
- package/gsd-core/workflows/ship.md +3 -4
- package/gsd-core/workflows/spec-phase.md +3 -6
- package/gsd-core/workflows/verify-work.md +4 -3
- package/hooks/dist/gsd-agent-isolation-guard.js +11 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-path-export.js +95 -0
- package/hooks/dist/gsd-secret-read-guard.js +172 -39
- package/hooks/dist/gsd-statusline.js +35 -2
- package/hooks/dist/gsd-windsurf-pre-write.js +28 -1
- package/hooks/dist/gsd-workflow-guard.js +1 -1
- package/hooks/dist/gsd-worktree-path-guard.js +28 -1
- package/hooks/dist/lib/isolation-sentinel.js +44 -0
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +11 -1
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-path-export.js +95 -0
- package/hooks/gsd-secret-read-guard.js +172 -39
- package/hooks/gsd-statusline.js +35 -2
- package/hooks/gsd-windsurf-pre-write.js +28 -1
- package/hooks/gsd-workflow-guard.js +1 -1
- package/hooks/gsd-worktree-path-guard.js +28 -1
- package/hooks/hooks.json +1 -0
- package/hooks/lib/isolation-sentinel.js +44 -0
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -6
- package/pi/gsd.cjs +1047 -10
- package/pi/package-agents/gsd-advisor-researcher.md +113 -0
- package/pi/package-agents/gsd-ai-researcher.md +111 -0
- package/pi/package-agents/gsd-assumptions-analyzer.md +110 -0
- package/pi/package-agents/gsd-code-fixer.md +769 -0
- package/pi/package-agents/gsd-code-reviewer.md +402 -0
- package/pi/package-agents/gsd-codebase-mapper.md +850 -0
- package/pi/package-agents/gsd-debug-session-manager.md +416 -0
- package/pi/package-agents/gsd-debugger.md +1274 -0
- package/pi/package-agents/gsd-doc-classifier.md +269 -0
- package/pi/package-agents/gsd-doc-synthesizer.md +259 -0
- package/pi/package-agents/gsd-doc-verifier.md +212 -0
- package/pi/package-agents/gsd-doc-writer.md +626 -0
- package/pi/package-agents/gsd-dom-verifier.md +164 -0
- package/pi/package-agents/gsd-domain-researcher.md +144 -0
- package/pi/package-agents/gsd-eval-auditor.md +185 -0
- package/pi/package-agents/gsd-eval-planner.md +149 -0
- package/pi/package-agents/gsd-executor.md +894 -0
- package/pi/package-agents/gsd-framework-selector.md +159 -0
- package/pi/package-agents/gsd-integration-checker.md +476 -0
- package/pi/package-agents/gsd-intel-updater.md +338 -0
- package/pi/package-agents/gsd-mempalace-curator.md +49 -0
- package/pi/package-agents/gsd-nyquist-auditor.md +200 -0
- package/pi/package-agents/gsd-pattern-mapper.md +340 -0
- package/pi/package-agents/gsd-phase-researcher.md +897 -0
- package/pi/package-agents/gsd-plan-checker.md +1077 -0
- package/pi/package-agents/gsd-planner.md +1003 -0
- package/pi/package-agents/gsd-project-researcher.md +611 -0
- package/pi/package-agents/gsd-research-synthesizer.md +259 -0
- package/pi/package-agents/gsd-roadmapper.md +779 -0
- package/pi/package-agents/gsd-security-auditor.md +171 -0
- package/pi/package-agents/gsd-ui-auditor.md +581 -0
- package/pi/package-agents/gsd-ui-checker.md +417 -0
- package/pi/package-agents/gsd-ui-researcher.md +469 -0
- package/pi/package-agents/gsd-user-profiler.md +174 -0
- package/pi/package-agents/gsd-verifier.md +963 -0
- package/pi/package-agents/manifest.json +39 -0
- package/pi/package-skills/gsd-add-tests/SKILL.md +39 -0
- package/pi/package-skills/gsd-ai-integration-phase/SKILL.md +36 -0
- package/pi/package-skills/gsd-audit-fix/SKILL.md +34 -0
- package/pi/package-skills/gsd-audit-milestone/SKILL.md +40 -0
- package/pi/package-skills/gsd-audit-uat/SKILL.md +26 -0
- package/pi/package-skills/gsd-autonomous/SKILL.md +52 -0
- package/pi/package-skills/gsd-capture/SKILL.md +68 -0
- package/pi/package-skills/gsd-cleanup/SKILL.md +25 -0
- package/pi/package-skills/gsd-code-review/SKILL.md +71 -0
- package/pi/package-skills/gsd-complete-milestone/SKILL.md +147 -0
- package/pi/package-skills/gsd-config/SKILL.md +60 -0
- package/pi/package-skills/gsd-debug/SKILL.md +64 -0
- package/pi/package-skills/gsd-discuss-phase/SKILL.md +74 -0
- package/pi/package-skills/gsd-docs-update/SKILL.md +50 -0
- package/pi/package-skills/gsd-eval-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-execute-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-explore/SKILL.md +26 -0
- package/pi/package-skills/gsd-extract-learnings/SKILL.md +25 -0
- package/pi/package-skills/gsd-fast/SKILL.md +33 -0
- package/pi/package-skills/gsd-forensics/SKILL.md +59 -0
- package/pi/package-skills/gsd-graphify/SKILL.md +210 -0
- package/pi/package-skills/gsd-health/SKILL.md +36 -0
- package/pi/package-skills/gsd-help/SKILL.md +37 -0
- package/pi/package-skills/gsd-import/SKILL.md +46 -0
- package/pi/package-skills/gsd-inbox/SKILL.md +42 -0
- package/pi/package-skills/gsd-ingest-docs/SKILL.md +43 -0
- package/pi/package-skills/gsd-manager/SKILL.md +46 -0
- package/pi/package-skills/gsd-map-codebase/SKILL.md +85 -0
- package/pi/package-skills/gsd-mempalace-capture/SKILL.md +111 -0
- package/pi/package-skills/gsd-mempalace-recall/SKILL.md +111 -0
- package/pi/package-skills/gsd-milestone-summary/SKILL.md +54 -0
- package/pi/package-skills/gsd-mvp-phase/SKILL.md +45 -0
- package/pi/package-skills/gsd-new-milestone/SKILL.md +49 -0
- package/pi/package-skills/gsd-new-project/SKILL.md +49 -0
- package/pi/package-skills/gsd-next/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-context/SKILL.md +31 -0
- package/pi/package-skills/gsd-ns-ideate/SKILL.md +30 -0
- package/pi/package-skills/gsd-ns-manage/SKILL.md +42 -0
- package/pi/package-skills/gsd-ns-project/SKILL.md +34 -0
- package/pi/package-skills/gsd-ns-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ns-workflow/SKILL.md +44 -0
- package/pi/package-skills/gsd-onboard/SKILL.md +46 -0
- package/pi/package-skills/gsd-pause-work/SKILL.md +48 -0
- package/pi/package-skills/gsd-phase/SKILL.md +61 -0
- package/pi/package-skills/gsd-plan-phase/SKILL.md +62 -0
- package/pi/package-skills/gsd-plan-review-convergence/SKILL.md +63 -0
- package/pi/package-skills/gsd-pr-branch/SKILL.md +31 -0
- package/pi/package-skills/gsd-profile-user/SKILL.md +48 -0
- package/pi/package-skills/gsd-progress/SKILL.md +51 -0
- package/pi/package-skills/gsd-quick/SKILL.md +179 -0
- package/pi/package-skills/gsd-quick-batch/SKILL.md +114 -0
- package/pi/package-skills/gsd-resume-work/SKILL.md +31 -0
- package/pi/package-skills/gsd-review/SKILL.md +50 -0
- package/pi/package-skills/gsd-review-backlog/SKILL.md +65 -0
- package/pi/package-skills/gsd-secure-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-settings/SKILL.md +30 -0
- package/pi/package-skills/gsd-ship/SKILL.md +27 -0
- package/pi/package-skills/gsd-sketch/SKILL.md +56 -0
- package/pi/package-skills/gsd-spec-phase/SKILL.md +63 -0
- package/pi/package-skills/gsd-spike/SKILL.md +53 -0
- package/pi/package-skills/gsd-stats/SKILL.md +22 -0
- package/pi/package-skills/gsd-surface/SKILL.md +177 -0
- package/pi/package-skills/gsd-thread/SKILL.md +29 -0
- package/pi/package-skills/gsd-ui-phase/SKILL.md +35 -0
- package/pi/package-skills/gsd-ui-review/SKILL.md +35 -0
- package/pi/package-skills/gsd-ultraplan-phase/SKILL.md +38 -0
- package/pi/package-skills/gsd-undo/SKILL.md +38 -0
- package/pi/package-skills/gsd-update/SKILL.md +51 -0
- package/pi/package-skills/gsd-validate-phase/SKILL.md +37 -0
- package/pi/package-skills/gsd-verify-work/SKILL.md +41 -0
- package/pi/package-skills/gsd-workspace/SKILL.md +57 -0
- package/pi/package-skills/gsd-workstreams/SKILL.md +73 -0
- package/scripts/build-hooks.js +4 -0
- package/scripts/command-contract-helpers.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +20 -7
- package/scripts/gen-health-docs.cjs +13 -1
- package/scripts/gen-pi-package-skills.cjs +217 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +11 -1
- package/scripts/lib/platform-conformance-tier.generated.cjs +26 -1
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +3 -3
- package/scripts/lint-retired-runtime-name.cjs +5 -0
- package/scripts/npm-audit-baseline.cjs +41 -7
- package/scripts/reviewed-or-maintainer-policy.cjs +181 -0
- package/scripts/select-docs-guards.cjs +1 -1
- package/scripts/self-test-report-policy.cjs +350 -0
- package/vscode/package.json +1 -1
- package/scripts/diagnose-validate-commit-in-tier.cjs +0 -270
- package/scripts/diagnose-validate-commit-phases.cjs +0 -348
- package/scripts/xtrace-phase-timing.cjs +0 -205
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
*/
|
|
43
43
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
44
44
|
const healthDiagnosticMod = require("../health-diagnostic-types.cjs");
|
|
45
|
-
const { SEVERITY, adviseRemedy } = healthDiagnosticMod;
|
|
45
|
+
const { SEVERITY, REMEDY_ACTION, REMEDY_RISK, adviseRemedy } = healthDiagnosticMod;
|
|
46
46
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
47
47
|
const validateMod = require("../validate.cjs");
|
|
48
48
|
// #612: `isPhaseDirName` is the convention-SELECTED shape test wrapping
|
|
@@ -57,6 +57,9 @@ const phaseIdMod = require("../phase-id.cjs");
|
|
|
57
57
|
const { extractPhaseToken, normalizePhaseName, comparePhaseNum } = phaseIdMod;
|
|
58
58
|
// #5060: the Phase Status Module owns the status-label ladder.
|
|
59
59
|
const phase_status_cjs_1 = require("../phase-status.cjs");
|
|
60
|
+
// #5291: W030 asks whether a raw report status has a known repair. The lookup is
|
|
61
|
+
// a pure read of a frozen table, so `check` stays free of ambient I/O (§8.1 rule 1).
|
|
62
|
+
const verification_cjs_1 = require("../verification.cjs");
|
|
60
63
|
// ─── W005 — phase directory doesn't follow NN-name format (verify.cts:1893-1902) ─
|
|
61
64
|
function checkW005(snapshot) {
|
|
62
65
|
const diagnostics = [];
|
|
@@ -174,11 +177,21 @@ function checkW030(snapshot) {
|
|
|
174
177
|
const invalid = phase.verificationStatusError;
|
|
175
178
|
if (!invalid)
|
|
176
179
|
continue;
|
|
180
|
+
// #5291: a KNOWN legacy status is repairable (rewritten to its closed-set
|
|
181
|
+
// equivalent, original kept in `legacy_status`); any other value has no
|
|
182
|
+
// mapping and keeps the advise-only remedy — it stays refused.
|
|
183
|
+
const target = (0, verification_cjs_1.legacyStatusRepairTarget)(invalid.rawStatus);
|
|
177
184
|
diagnostics.push({
|
|
178
185
|
code: 'W030',
|
|
179
186
|
severity: SEVERITY.WARNING,
|
|
180
187
|
message: `Phase ${phase.dir}: ${invalid.message}`,
|
|
181
|
-
remedy:
|
|
188
|
+
remedy: target === null
|
|
189
|
+
? adviseRemedy('Set the report frontmatter `status` to one of passed | gaps_found | human_needed, or delete the report and re-run the phase verification')
|
|
190
|
+
: {
|
|
191
|
+
action: REMEDY_ACTION.REPAIR_VERIFICATION_STATUS,
|
|
192
|
+
risk: REMEDY_RISK.NONE,
|
|
193
|
+
args: { file: invalid.file, from: invalid.rawStatus, to: target },
|
|
194
|
+
},
|
|
182
195
|
});
|
|
183
196
|
}
|
|
184
197
|
return diagnostics;
|
|
@@ -217,7 +230,9 @@ const RULES = [
|
|
|
217
230
|
code: 'W030',
|
|
218
231
|
severity: SEVERITY.WARNING,
|
|
219
232
|
description: 'Phase verification report status is outside the closed set',
|
|
220
|
-
|
|
233
|
+
// #5291: repairable per finding — a KNOWN legacy status (`pass_with_caveats`)
|
|
234
|
+
// is rewritten by `--repair`; any other value stays advise-only.
|
|
235
|
+
repairable: true,
|
|
221
236
|
check: checkW030,
|
|
222
237
|
},
|
|
223
238
|
];
|
|
@@ -38,6 +38,10 @@ const REMEDY_ACTION = Object.freeze({
|
|
|
38
38
|
ADD_NYQUIST_KEY: 'addNyquistKey',
|
|
39
39
|
ADD_AI_INTEGRATION_PHASE_KEY: 'addAiIntegrationPhaseKey',
|
|
40
40
|
BACKFILL_MILESTONES: 'backfillMilestones',
|
|
41
|
+
// #5291: rewrite a KNOWN legacy verification `status` (W030) to its closed-set
|
|
42
|
+
// equivalent, keeping the original in `legacy_status`. Per-finding: only
|
|
43
|
+
// emitted when the raw value has a mapping; every other W030 stays ADVISE.
|
|
44
|
+
REPAIR_VERIFICATION_STATUS: 'repairVerificationStatus',
|
|
41
45
|
// §8.3 rule 5 — every non-repairable finding's `fix` string becomes an
|
|
42
46
|
// ADVISE payload; ADVISE never acts, only describes.
|
|
43
47
|
ADVISE: 'advise',
|
|
@@ -118,6 +118,9 @@ const { getMilestoneInfo } = roadmapParserMod;
|
|
|
118
118
|
const stateMod = require("./state.cjs");
|
|
119
119
|
const { writeStateMd, assertVerificationReportsReadable } = stateMod;
|
|
120
120
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
121
|
+
const verificationMod = require("./verification.cjs");
|
|
122
|
+
const { repairLegacyVerificationStatus } = verificationMod;
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
121
124
|
const frontmatter = require("./frontmatter.cjs");
|
|
122
125
|
const { extractFrontmatter } = frontmatter;
|
|
123
126
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -252,9 +255,27 @@ function computeMissingMilestoneVersions(milestonesArchiveDir, milestonesPath) {
|
|
|
252
255
|
* shape, collapsed to one seam here since every case now shares one
|
|
253
256
|
* caller).
|
|
254
257
|
*/
|
|
255
|
-
function runRepairAction(cwd, action, paths) {
|
|
258
|
+
function runRepairAction(cwd, action, paths, args = {}) {
|
|
256
259
|
const { rootBase, configPath, statePath, milestonesPath, milestonesArchiveDir } = paths;
|
|
257
260
|
switch (action) {
|
|
261
|
+
case REMEDY_ACTION.REPAIR_VERIFICATION_STATUS: {
|
|
262
|
+
// #5291: the report path comes from the finding's own remedy args, not
|
|
263
|
+
// from user input; `repairLegacyVerificationStatus` re-verifies that it is
|
|
264
|
+
// a report contained in its phase directory before it writes a byte.
|
|
265
|
+
const file = typeof args['file'] === 'string' ? args['file'] : '';
|
|
266
|
+
if (file === '')
|
|
267
|
+
return { success: false, error: 'no report path on the finding' };
|
|
268
|
+
const repaired = repairLegacyVerificationStatus(file);
|
|
269
|
+
if (!repaired.ok)
|
|
270
|
+
return { success: false, error: repaired.reason };
|
|
271
|
+
return {
|
|
272
|
+
success: true,
|
|
273
|
+
path: node_path_1.default.relative(cwd, file).split(node_path_1.default.sep).join('/'),
|
|
274
|
+
detail: repaired.legacyStatusKept
|
|
275
|
+
? `status ${repaired.from} -> ${repaired.to}; the report's existing legacy_status was left as it was`
|
|
276
|
+
: `status ${repaired.from} -> ${repaired.to}; original kept as legacy_status`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
258
279
|
case REMEDY_ACTION.CREATE_CONFIG:
|
|
259
280
|
case REMEDY_ACTION.RESET_CONFIG: {
|
|
260
281
|
(0, shell_command_projection_cjs_1.platformWriteSync)(configPath, JSON.stringify(defaultConfigPayload(), null, 2));
|
|
@@ -390,6 +411,34 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
|
|
|
390
411
|
const refused = [];
|
|
391
412
|
const details = [];
|
|
392
413
|
const paths = repairPaths(cwd);
|
|
414
|
+
// #5291: a legacy-status repair is the CURE for the refusal the pre-check
|
|
415
|
+
// below enforces, so it runs first (a report edit is its only write and it
|
|
416
|
+
// validates its own target); the pre-check then sees the repaired reports.
|
|
417
|
+
const statusRepairs = new Set();
|
|
418
|
+
if (repair) {
|
|
419
|
+
for (const diagnostic of diagnostics) {
|
|
420
|
+
const { remedy, code } = diagnostic;
|
|
421
|
+
if (remedy.action !== REMEDY_ACTION.REPAIR_VERIFICATION_STATUS || remedy.risk === REMEDY_RISK.DESTRUCTIVE)
|
|
422
|
+
continue;
|
|
423
|
+
statusRepairs.add(diagnostic);
|
|
424
|
+
try {
|
|
425
|
+
const outcome = runRepairAction(cwd, remedy.action, paths, remedy.args);
|
|
426
|
+
details.push({
|
|
427
|
+
code,
|
|
428
|
+
action: remedy.action,
|
|
429
|
+
success: outcome.success,
|
|
430
|
+
...(outcome.path ? { path: outcome.path } : {}),
|
|
431
|
+
...(outcome.detail ? { detail: outcome.detail } : {}),
|
|
432
|
+
...(outcome.error ? { error: outcome.error } : {}),
|
|
433
|
+
});
|
|
434
|
+
if (outcome.success)
|
|
435
|
+
applied.push(code);
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
details.push({ code, action: remedy.action, success: false, error: err instanceof Error ? err.message : String(err) });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
393
442
|
// #5118 (no write before the error): a requested REGENERATE_STATE rewrites
|
|
394
443
|
// STATE.md from every phase's report and throws on one whose `status` is
|
|
395
444
|
// outside the closed set — but other repairs in the SAME run (config,
|
|
@@ -411,6 +460,8 @@ function applyRepairs(cwd, diagnostics, repair, backfill) {
|
|
|
411
460
|
const { remedy, code } = diagnostic;
|
|
412
461
|
if (remedy.action === REMEDY_ACTION.ADVISE)
|
|
413
462
|
continue;
|
|
463
|
+
if (statusRepairs.has(diagnostic))
|
|
464
|
+
continue;
|
|
414
465
|
const requested = remedy.action === REMEDY_ACTION.BACKFILL_MILESTONES ? repair || backfill : repair;
|
|
415
466
|
if (!requested)
|
|
416
467
|
continue;
|
|
@@ -620,7 +620,7 @@ function hookEventSurfaceFor(hookEvents) {
|
|
|
620
620
|
// event subset (imperative hosts' extension API). They are not the same thing.
|
|
621
621
|
//
|
|
622
622
|
// Values are documentation-sourced (ADR-1239 §research): OpenCode ~25 plugin
|
|
623
|
-
// events (session/tool/file/permission); pi
|
|
623
|
+
// events (session/tool/file/permission); pi 41 fine-grained extension events (pi 1.3.0);
|
|
624
624
|
// 'none' = the host exposes no extension surface and the engine owns the bus
|
|
625
625
|
// (VS Code). Declarative hosts (no plugin API) do not set `extensionEvents`.
|
|
626
626
|
// OpenCode's plugin event surface (ADR-1239 §research; ~25 documented events,
|
|
@@ -655,11 +655,13 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
|
|
|
655
655
|
'pre_gateway_dispatch', 'pre_approval_request',
|
|
656
656
|
'transform_tool_result',
|
|
657
657
|
]),
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
//
|
|
662
|
-
//
|
|
658
|
+
// pi's real ExtensionAPI event vocabulary: the 41 `on(event: "...")` overloads
|
|
659
|
+
// declared by pi 1.3.0 (@earendil-works/pi-coding-agent
|
|
660
|
+
// dist/core/extensions/types.d.ts, sourceCommit 71023aec15, #5557). #2102
|
|
661
|
+
// Stage 2 declared the first 30 from pi.dev prose; the last 11 on the final
|
|
662
|
+
// row group were added when the host's own declarations were read. The
|
|
663
|
+
// pi.dev extensions page lists a lossy subset (it omits session_before_compact,
|
|
664
|
+
// which pi/gsd.cjs binds), so the type declarations are the source of truth.
|
|
663
665
|
pi: Object.freeze([
|
|
664
666
|
'session_start', 'project_trust', 'resources_discover', 'input',
|
|
665
667
|
'before_agent_start', 'agent_start', 'message_start', 'message_update',
|
|
@@ -669,6 +671,11 @@ const EXTENSION_EVENT_SURFACES = Object.freeze({
|
|
|
669
671
|
'session_before_switch', 'session_shutdown', 'session_before_fork',
|
|
670
672
|
'session_info_changed', 'session_before_compact', 'session_compact',
|
|
671
673
|
'session_before_tree', 'session_tree', 'thinking_level_select', 'model_select',
|
|
674
|
+
// Added in pi 1.3.0 (#5557):
|
|
675
|
+
'agent_before_settle', 'agent_settled', 'before_provider_headers',
|
|
676
|
+
'cache_warming_decision', 'context_with_system', 'mcp_servers_change',
|
|
677
|
+
'provider_stream_event', 'session_compact_failed', 'ui_prompt_end',
|
|
678
|
+
'ui_prompt_start', 'user_bash',
|
|
672
679
|
]),
|
|
673
680
|
none: Object.freeze([]),
|
|
674
681
|
});
|
|
@@ -98,7 +98,7 @@ const { getRoadmapPhaseInternal, getMilestoneInfo, stripShippedMilestones, extra
|
|
|
98
98
|
const { pathExistsInternal, generateSlugInternal, toPosixPath } = coreUtils;
|
|
99
99
|
const { comparePhaseNum, normalizePhaseName, stripProjectCodePrefix, PHASE_NUMBER_TOKEN_SOURCE, PHASE_DEP_REF_SOURCE, isForeignPrefixedPhaseQuery, isSentinelPhaseId, extractPhaseToken, scopeToPhase, renderPhaseBranchName, parsePhaseId, renderPhaseId, phaseHeadingPrefixSrcFor, PHASE_HEADING_BASELINE, buildPhaseHeadingScanRegex, } = phaseId;
|
|
100
100
|
const { pruneOrphanedWorktrees } = worktreeSafety;
|
|
101
|
-
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
|
|
101
|
+
const { planningPaths, planningDir, planningRoot, todosDir, listAvailableWorkstreams, peekActiveWorkstream, resolveEnvWorkstream, diagnoseUnresolvedActiveWorkstream, describeUnresolvedWorkstreamReason, findContextMdIn, findPhaseSpecIn, resolvePhaseIdConvention, worktreesOptedOut, } = planningWorkspace;
|
|
102
102
|
const { extractFrontmatter, frontmatterBlock } = frontmatterMod;
|
|
103
103
|
const { isPhaseComplete, resolveVerificationFile, resolveUatFile, VERIFICATION_STATUS, VerificationStatusError } = verificationMod;
|
|
104
104
|
const { evaluateUatPassed } = uatPredicateMod;
|
|
@@ -177,6 +177,28 @@ function resolvePhaseDisplayName(phaseInfo, roadmapPhase) {
|
|
|
177
177
|
|| phaseInfo?.['phase_name']
|
|
178
178
|
|| null;
|
|
179
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* #5629: the phase SPEC as init facts, for every init payload a SPEC-consuming workflow parses
|
|
182
|
+
* (discuss-phase via `phase-op`, discuss-phase-assumptions, plan-phase). `has_spec` is always present;
|
|
183
|
+
* `spec_path` (absolute, posix) only when a plain `NN-SPEC.md` exists. One predicate (`findPhaseSpecIn`, shared
|
|
184
|
+
* with the context-drift gate) decides, so a UI-SPEC or AI-SPEC is never mistaken for the requirements lock and
|
|
185
|
+
* no workflow globs for it. A phase with no directory yet, or one that cannot be read, has no SPEC.
|
|
186
|
+
*/
|
|
187
|
+
function phaseSpecFacts(phaseDirAbs) {
|
|
188
|
+
if (!phaseDirAbs)
|
|
189
|
+
return { has_spec: false };
|
|
190
|
+
let files;
|
|
191
|
+
try {
|
|
192
|
+
files = node_fs_1.default.readdirSync(phaseDirAbs);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return { has_spec: false };
|
|
196
|
+
}
|
|
197
|
+
// Scoped to THIS phase's own artifacts first (#3511), like the sibling artifact lookups: a misfiled
|
|
198
|
+
// `02-SPEC.md` in phase 03's directory must not win (the context-drift gate scopes the same way).
|
|
199
|
+
const spec = findPhaseSpecIn(scopeToPhase(files, node_path_1.default.basename(phaseDirAbs)));
|
|
200
|
+
return spec ? { has_spec: true, spec_path: toPosixPath(node_path_1.default.join(phaseDirAbs, spec)) } : { has_spec: false };
|
|
201
|
+
}
|
|
180
202
|
/**
|
|
181
203
|
* #2994 (review finding, DEFECT.GENERATIVE-FIX): shared archived/not-found
|
|
182
204
|
* fallback applied identically by `cmdInitExecutePhase`, `cmdInitPlanPhase`,
|
|
@@ -600,6 +622,28 @@ function detectFallowConfig(cwd) {
|
|
|
600
622
|
function detectGitCreateTag(cwd) {
|
|
601
623
|
return readConfigJsonValue(cwd, ['git', 'create_tag']) !== false;
|
|
602
624
|
}
|
|
625
|
+
/**
|
|
626
|
+
* `git.repo_tagging` ground truth (#5706, epic #3628): the milestone tagging
|
|
627
|
+
* mode exposed to `complete-milestone.md`. Only the documented `per_repo`
|
|
628
|
+
* opts in; an absent key or any other stored value reads as the default
|
|
629
|
+
* `single` (today's behavior), matching `loadConfig`'s resolution.
|
|
630
|
+
*/
|
|
631
|
+
function detectRepoTagging(cwd) {
|
|
632
|
+
return readConfigJsonValue(cwd, ['git', 'repo_tagging']) === 'per_repo' ? 'per_repo' : 'single';
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* The configured `planning.sub_repos` (#5706): an array of non-empty repo
|
|
636
|
+
* names, possibly empty. A legacy top-level `sub_repos` is honored when the
|
|
637
|
+
* nested key is absent, the same flat-then-nested order `loadConfig` applies.
|
|
638
|
+
* Non-string members are dropped; any degraded read yields `[]`.
|
|
639
|
+
*/
|
|
640
|
+
function detectSubRepos(cwd) {
|
|
641
|
+
const nested = readConfigJsonValue(cwd, ['planning', 'sub_repos']);
|
|
642
|
+
const raw = nested !== undefined ? nested : readConfigJsonValue(cwd, ['sub_repos']);
|
|
643
|
+
if (!Array.isArray(raw))
|
|
644
|
+
return [];
|
|
645
|
+
return raw.filter((name) => typeof name === 'string' && name.trim() !== '');
|
|
646
|
+
}
|
|
603
647
|
/**
|
|
604
648
|
* `state:phase-mvp-mode` ground truth (design doc §Behavior table: ROADMAP.md
|
|
605
649
|
* `**Mode:** mvp` for the CURRENT phase). Bounded, non-throwing — an absent
|
|
@@ -1139,6 +1183,8 @@ function cmdInitPlanPhase(cwd, phase, raw, options = {}) {
|
|
|
1139
1183
|
state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
|
|
1140
1184
|
roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
|
|
1141
1185
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
1186
|
+
// #5629: the phase SPEC (plan-phase lifts its Edge Coverage from it; no workflow globs for it).
|
|
1187
|
+
...phaseSpecFacts(phaseInfo?.['directory'] ? node_path_1.default.join(cwd, phaseInfo['directory']) : null),
|
|
1142
1188
|
patterns_path: null,
|
|
1143
1189
|
};
|
|
1144
1190
|
if (phaseInfo?.['directory']) {
|
|
@@ -1934,6 +1980,8 @@ function cmdInitDiscussPhaseAssumptions(cwd, phase, raw, options = {}) {
|
|
|
1934
1980
|
plan_count: phaseInfo?.['plans']?.length || 0,
|
|
1935
1981
|
roadmap_exists: node_fs_1.default.existsSync(node_path_1.default.join(planningDir(cwd), 'ROADMAP.md')),
|
|
1936
1982
|
planning_exists: node_fs_1.default.existsSync(planningDir(cwd)),
|
|
1983
|
+
// #5629: the phase SPEC, so assumptions mode honours it like the default flow does.
|
|
1984
|
+
...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
|
|
1937
1985
|
};
|
|
1938
1986
|
// #2994 (Phase 6.3): additive, optional field — degrades to null, never throws.
|
|
1939
1987
|
const sectionManifestOptions = {
|
|
@@ -2065,6 +2113,8 @@ function cmdInitPhaseOp(cwd, phase, raw) {
|
|
|
2065
2113
|
state_path: node_fs_1.default.existsSync(statePath) ? toPosixPath(statePath) : null,
|
|
2066
2114
|
roadmap_path: node_fs_1.default.existsSync(roadmapPath) ? toPosixPath(roadmapPath) : null,
|
|
2067
2115
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
2116
|
+
// #5629: the phase SPEC (discuss-phase reads it from here; no workflow globs for it).
|
|
2117
|
+
...phaseSpecFacts(phaseDir ? node_path_1.default.join(cwd, phaseDir) : null),
|
|
2068
2118
|
};
|
|
2069
2119
|
if (phaseInfo?.['directory']) {
|
|
2070
2120
|
const phaseDirFull = node_path_1.default.join(cwd, phaseInfo['directory']);
|
|
@@ -3016,9 +3066,23 @@ function cmdInitCompleteMilestone(cwd, raw, options = {}) {
|
|
|
3016
3066
|
milestones_path: node_fs_1.default.existsSync(milestonesPath) ? toPosixPath(milestonesPath) : null,
|
|
3017
3067
|
project_path: node_fs_1.default.existsSync(projectPath) ? toPosixPath(projectPath) : null,
|
|
3018
3068
|
requirements_path: node_fs_1.default.existsSync(requirementsPath) ? toPosixPath(requirementsPath) : null,
|
|
3069
|
+
// #5706 (epic #3628): the repositories configured for this project and the
|
|
3070
|
+
// milestone tagging mode, so the workflow reads both from one init call.
|
|
3071
|
+
sub_repos: detectSubRepos(cwd),
|
|
3072
|
+
repo_tagging: detectRepoTagging(cwd),
|
|
3019
3073
|
};
|
|
3074
|
+
// #5195: `state:flat-mode` gates the PROJECT.md evolution review. PROJECT.md
|
|
3075
|
+
// is shared across workstreams (the `projectPath` comment above), so a
|
|
3076
|
+
// workstream's milestone close must not rewrite or stage it — the same
|
|
3077
|
+
// decision `cmdInitNewMilestone` applies to its Part A (#2308), resolved from
|
|
3078
|
+
// the same authority (`GSD_WORKSTREAM` env, else the stored pointer) so the
|
|
3079
|
+
// gate cannot disagree with the workstream-scoped paths returned above.
|
|
3080
|
+
// Read-only peek: no self-heal side effect from building a report field (#3579).
|
|
3081
|
+
const workstreamActive = !!(resolveEnvWorkstream() ?? peekActiveWorkstream(cwd));
|
|
3020
3082
|
result['section_manifest'] = buildSectionManifestField(cwd, null, options, 'complete-milestone', {
|
|
3021
3083
|
gitCreateTag,
|
|
3084
|
+
workstreamActive,
|
|
3085
|
+
flatMode: !workstreamActive,
|
|
3022
3086
|
});
|
|
3023
3087
|
output(withProjectRoot(cwd, result), raw);
|
|
3024
3088
|
}
|