* test(4): reproduce non-idempotent phase complete + unclamped percent in CJS CLI RED regression tests for issue #4: - T1: double invocation of cmdPhaseComplete double-increments **Completed Phases:** in STATE.md body (blind parseInt+1 instead of deriving from ROADMAP) - T2: progress percent can exceed 100% when Completed Phases > Total Phases The CJS path (bin/lib/phase.cjs:cmdPhaseComplete) has the bug; the SDK path (phase-lifecycle.ts:phaseComplete, fixed in ~PR#3520) already derives completed_phases from ROADMAP Complete-row count, making it idempotent. References: - Issue #4 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - /tmp/adr-3524-review-findings.md (architectural justification) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): add sdk/scripts/gen-phase-lifecycle-policy.mjs generator + freshness check placeholder Generates phase-lifecycle-policy.generated.cjs from sdk/src/query/phase-lifecycle-policy.ts. All functions in phase-lifecycle-policy.ts are pure transforms (no I/O), directly serializable via Function.prototype.toString(). The GSDError dependency is replaced with a lightweight stub that throws plain Error objects — CJS callers that need process.exit(1) behavior catch these and delegate to error(). This is the "I/O adapter pattern" from ADR-3524 Section 4 applied to pure helpers. References: - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - /tmp/adr-3524-review-findings.md (architectural justification) - Issue #4 (open-gsd/get-shit-done-redux) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): add sdk/scripts/gen-phase.mjs generator Generates phase.generated.cjs from sdk/src/query/phase.ts. Only pure helpers (isCanonicalPlanFile, describeNonCanonicalPlans) are generated; async query handlers (findPhase, phasePlanIndex) are I/O-bound and remain per-side per ADR-3524 Section 4. References: - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - /tmp/adr-3524-review-findings.md (architectural justification) - Issue #4 (open-gsd/get-shit-done-redux) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): add sdk/scripts/gen-phase-lifecycle.mjs + core idempotency fix logic Generates phase-lifecycle.generated.cjs providing two pure functions that are the root-cause fix for issue #4: 1. deriveProgressFromRoadmap(roadmapContent): counts Complete rows in ROADMAP progress table — makes completed_phases idempotent (derived from ground truth instead of blind +1). Direct transcription of the SDK's "Root cause 1 fix" block in phase-lifecycle.ts (~line 1644). 2. clampPercent(completed, total): percent capped at 100 — prevents >100% progress when Completed Phases exceeds Total Phases. Design note: the full phase lifecycle mutations (add, insert, remove, complete) are inherently async and I/O-bound. Per ADR-3524 Section 4 ("I/O stays per-side"), those are NOT generated. Only the pure-computation kernel is extracted, following the I/O adapter pattern: pure logic shared; each side (CJS sync, SDK async) supplies its own I/O adapter. The pure functions are defined in the generator as real JS functions and serialized via Function.prototype.toString() — same technique as gen-project-root.mjs — rather than embedded in template literals (which would require double-escaping all regex backslashes). References: - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - /tmp/adr-3524-review-findings.md (architectural justification) - Issue #4 (open-gsd/get-shit-done-redux) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): emit phase.generated.cjs, phase-lifecycle.generated.cjs, phase-lifecycle-policy.generated.cjs Three generated CJS artifacts from their respective generator scripts: - phase.generated.cjs (1.7K): isCanonicalPlanFile + describeNonCanonicalPlans from sdk/src/query/phase.ts - phase-lifecycle.generated.cjs (3.6K): deriveProgressFromRoadmap + clampPercent — the idempotency+clamp fix for issue #4 - phase-lifecycle-policy.generated.cjs (7.0K): 14 pure phase naming/directory helpers from sdk/src/query/phase-lifecycle-policy.ts Run to regenerate: node sdk/scripts/gen-phase.mjs node sdk/scripts/gen-phase-lifecycle.mjs node sdk/scripts/gen-phase-lifecycle-policy.mjs References: - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - Issue #4 (open-gsd/get-shit-done-redux) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(4): migrate bin/lib/phase.cjs cmdPhaseComplete to use generated helpers Replace the blind-increment + unclamped percent bug in cmdPhaseComplete with the idempotent ROADMAP-derived approach: read freshly-updated ROADMAP, call deriveProgressFromRoadmap() from phase-lifecycle.generated.cjs, fall back to existing value when ROADMAP is unavailable. clampPercent() prevents >100%. Root cause fix for issue #4: the original parseInt(completedRaw) + 1 on every call made phase complete non-idempotent; the missing Math.min(100, ...) clamp allowed Progress to exceed 100%. I/O adapter pattern (ADR-3524 §4): pure computation in generated module; CJS supplies sync readFileSync; SDK supplies async readFile. Same logic, two adapters. Closes: Tests in 4-phase-complete-cjs-regression.test.cjs go GREEN. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): add freshness checks + npm scripts for phase generated artifacts (D4/D6) Add check-phase-fresh.mjs, check-phase-lifecycle-fresh.mjs, and check-phase-lifecycle-policy-fresh.mjs (same pattern as check-project-root-fresh.mjs: import buildXCjs() from the generator, regenerate in-memory, byte-compare to committed file, exit 1 if stale). Add gen:phase, check:phase-fresh, gen:phase-lifecycle, check:phase-lifecycle-fresh, gen:phase-lifecycle-policy, check:phase-lifecycle-policy-fresh to sdk/package.json. Note: gen:phase-lifecycle / check:phase-lifecycle-fresh do not require 'npm run build' because the generator defines pure functions directly rather than importing dist. Update shared-module-handsync-allowlist.json: reclassify phase.cjs justification to reflect that it now consumes phase-lifecycle.generated.cjs for cmdPhaseComplete. The *.generated.cjs files are excluded by the lint scanner (excludes *.generated.cjs) so no new allowlist entries are required for the generated artifacts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci(4): add freshness-check CI steps for phase, phase-lifecycle, phase-lifecycle-policy Add three drift-check steps to .github/workflows/test.yml following the same pattern as the existing freshness checks (ubuntu-latest + node 24 only): - SDK generated phase artifact drift check - SDK generated phase-lifecycle artifact drift check - SDK generated phase-lifecycle-policy artifact drift check These guard against editors modifying the generated *.cjs files directly. They run check-phase-fresh.mjs, check-phase-lifecycle-fresh.mjs, and check-phase-lifecycle-policy-fresh.mjs respectively (added in D4). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(4): amend ADR-3524 — phase * I/O adapter pattern for issue #4 (D8) Append a 2026-05-23 amendment to docs/adr/3524-cjs-sdk-hard-seam.md documenting the Phase * cooperating-sibling retirement: three new generator scripts extract pure-computation helpers from phase.ts / phase-lifecycle.ts / phase-lifecycle-policy.ts, cmdPhaseComplete migrates to deriveProgressFromRoadmap + clampPercent for idempotency, freshness checks + CI steps added. Clarifies what is NOT generated (async I/O-bound mutation handlers stay per-side per Section 4) and notes open drift bugs #6 and #26 for traceability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(4): add changeset fragment for cmdPhaseComplete fix Refs #4 * fix(154): use canonical /gsd:plan-phase form in phase-lifecycle-policy.ts Replaces the retired /gsd-plan-phase slash command reference with the canonical colon-namespaced /gsd:plan-phase in the TS source template string that feeds the generated CJS roadmap entry helper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(154): regenerate phase-lifecycle-policy.generated.cjs after slash-namespace fix Regenerated via node sdk/scripts/gen-phase-lifecycle-policy.mjs after fixing /gsd-plan-phase → /gsd:plan-phase in the TS source. Generated file now contains the canonical colon form. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(154): cross-platform frontmatter regex anchor in 4-phase-complete-cjs-regression.test.cjs Replaces /^---\n/ with /^---\r?\n/ so the frontmatter extraction helper in the regression test tolerates Windows CRLF line endings (autocrlf=true checkout leaves \r before \n, causing /^---\n/ to never match). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(154): add new generated CJS modules to INVENTORY.md and regenerate manifest Adds three missing rows to the CLI Modules table: - phase-lifecycle-policy.generated.cjs - phase-lifecycle.generated.cjs - phase.generated.cjs Bumps the headline count from 74 to 77 to match the filesystem. Also regenerates docs/INVENTORY-MANIFEST.json via node scripts/gen-inventory-manifest.cjs --write. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(154): regenerate phase-lifecycle-policy.generated.cjs with hyphen form Root cause: commit 6cd701f4 regenerated the CJS artifact but at that point sdk/dist/query/phase-lifecycle-policy.js already had the correct /gsd-plan-phase (hyphen) form while sdk/src/query/phase-lifecycle-policy.ts still had /gsd:plan-phase (colon). The generator uses Function.prototype.toString() on the compiled dist, so the CJS picked up the wrong string from the stale TS source that was compiled into dist at some earlier point. Fix: correct the TS source to /gsd-plan-phase and re-run gen-phase-lifecycle-policy.mjs so that buildPhaseRoadmapEntry in the CJS emits the hyphen form, satisfying the bug-3584-runtime-slash-emitters.test.cjs assertion at line 179. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(154): restore /gsd:plan-phase canonical form in phase-lifecycle-policy Commit 0c3a9c75 incorrectly reverted the slash-namespace fix by misreading sdk/dist/ (a build artifact in hyphen form for non-Claude runtimes) as the authoritative source. The canonical form for Claude-facing source is /gsd:plan-phase (colon-namespaced). Fix: revert TS source back to /gsd:plan-phase, rebuild dist, regenerate phase-lifecycle-policy.generated.cjs. Fixes bug-2543-gsd-slash-namespace test failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(154): update INVENTORY.md CLI Modules count to 79 after rebase onto main Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(154): use hyphen form /gsd-plan-phase in persisted phase section template - sdk/src/query/phase-lifecycle-policy.ts: use /gsd-plan-phase (routable hyphen form) in the phase scaffold template that gets persisted to ROADMAP.md; bug-3584 requires persisted artifacts use the hyphen form - docs/INVENTORY.md: add missing runtime-name-policy.cjs row in CLI Modules table - tests/4-phase-complete-cjs-regression.test.cjs: add maxRetries/retryDelay to rmSync calls to satisfy Windows parity ratchet (baseline was 95) - Regenerate phase-lifecycle-policy.generated.cjs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86 lines
3.7 KiB
JSON
86 lines
3.7 KiB
JSON
{
|
|
"name": "@opengsd/gsd-sdk",
|
|
"version": "1.0.0",
|
|
"description": "GSD SDK — programmatic interface for running GSD plans via the Agent SDK",
|
|
"type": "module",
|
|
"main": "dist/index.js",
|
|
"types": "dist/index.d.ts",
|
|
"exports": {
|
|
".": {
|
|
"import": "./dist/index.js",
|
|
"types": "./dist/index.d.ts"
|
|
}
|
|
},
|
|
"bin": {
|
|
"gsd-sdk": "./dist/cli.js"
|
|
},
|
|
"files": [
|
|
"dist",
|
|
"shared",
|
|
"prompts"
|
|
],
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/open-gsd/get-shit-done-redux.git",
|
|
"directory": "sdk"
|
|
},
|
|
"homepage": "https://github.com/open-gsd/get-shit-done-redux/tree/main/sdk",
|
|
"bugs": {
|
|
"url": "https://github.com/open-gsd/get-shit-done-redux/issues"
|
|
},
|
|
"author": "TÂCHES",
|
|
"license": "MIT",
|
|
"publishConfig": {
|
|
"access": "public"
|
|
},
|
|
"engines": {
|
|
"node": ">=22.0.0"
|
|
},
|
|
"scripts": {
|
|
"build": "tsc",
|
|
"check:alias-drift": "npm run build && node scripts/check-command-aliases-fresh.mjs",
|
|
"gen:state-document": "npm run build && npx tsx scripts/gen-state-document.ts",
|
|
"check:state-document-fresh": "npm run build && node scripts/check-state-document-fresh.mjs",
|
|
"gen:configuration": "npm run build && node scripts/gen-configuration.mjs",
|
|
"check:configuration-fresh": "npm run build && node scripts/check-configuration-fresh.mjs",
|
|
"gen:workstream-inventory-builder": "npm run build && node scripts/gen-workstream-inventory-builder.mjs",
|
|
"check:workstream-inventory-builder-fresh": "npm run build && node scripts/check-workstream-inventory-builder-fresh.mjs",
|
|
"gen:project-root": "npm run build && node scripts/gen-project-root.mjs",
|
|
"check:project-root-fresh": "npm run build && node scripts/check-project-root-fresh.mjs",
|
|
"gen:plan-scan": "npm run build && node scripts/gen-plan-scan.mjs",
|
|
"check:plan-scan-fresh": "npm run build && node scripts/check-plan-scan-fresh.mjs",
|
|
"gen:secrets": "npm run build && node scripts/gen-secrets.mjs",
|
|
"check:secrets-fresh": "npm run build && node scripts/check-secrets-fresh.mjs",
|
|
"gen:schema-detect": "npm run build && node scripts/gen-schema-detect.mjs",
|
|
"check:schema-detect-fresh": "npm run build && node scripts/check-schema-detect-fresh.mjs",
|
|
"gen:decisions": "npm run build && node scripts/gen-decisions.mjs",
|
|
"check:decisions-fresh": "npm run build && node scripts/check-decisions-fresh.mjs",
|
|
"gen:workstream-name-policy": "npm run build && node scripts/gen-workstream-name-policy.mjs",
|
|
"check:workstream-name-policy-fresh": "npm run build && node scripts/check-workstream-name-policy-fresh.mjs",
|
|
"gen:validate": "npm run build && node scripts/gen-validate.mjs",
|
|
"check:validate-fresh": "npm run build && node scripts/check-validate-fresh.mjs",
|
|
"gen:phase": "npm run build && node scripts/gen-phase.mjs",
|
|
"check:phase-fresh": "npm run build && node scripts/check-phase-fresh.mjs",
|
|
"gen:phase-lifecycle": "node scripts/gen-phase-lifecycle.mjs",
|
|
"check:phase-lifecycle-fresh": "node scripts/check-phase-lifecycle-fresh.mjs",
|
|
"gen:phase-lifecycle-policy": "npm run build && node scripts/gen-phase-lifecycle-policy.mjs",
|
|
"check:phase-lifecycle-policy-fresh": "npm run build && node scripts/check-phase-lifecycle-policy-fresh.mjs",
|
|
"prepublishOnly": "rm -rf dist && tsc && chmod +x dist/cli.js",
|
|
"test": "vitest run",
|
|
"test:unit": "vitest run --project unit",
|
|
"test:integration": "vitest run --project integration"
|
|
},
|
|
"dependencies": {
|
|
"@anthropic-ai/claude-agent-sdk": "^0.2.84",
|
|
"synckit": "^0.11.12",
|
|
"ws": "8.20.1"
|
|
},
|
|
"devDependencies": {
|
|
"@types/node": "^22.0.0",
|
|
"@types/ws": "^8.18.1",
|
|
"tsx": "^4.22.0",
|
|
"typescript": "^5.7.0",
|
|
"vitest": "^3.1.1"
|
|
}
|
|
}
|