@opengsd/gsd-core 1.7.0-rc.5 → 1.7.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-executor.md +2 -1
- package/agents/gsd-security-auditor.md +13 -15
- package/agents/gsd-ui-checker.md +2 -0
- package/agents/gsd-ui-researcher.md +1 -0
- package/bin/install.js +975 -196
- package/commands/gsd/mempalace-capture.md +27 -1
- package/commands/gsd/surface.md +6 -6
- package/gsd-core/bin/gsd-tools.cjs +63 -2
- package/gsd-core/bin/lib/api-coverage.cjs +3 -4
- package/gsd-core/bin/lib/audit.cjs +7 -6
- package/gsd-core/bin/lib/capability-registry.cjs +503 -87
- package/gsd-core/bin/lib/capability-validator.cjs +56 -18
- package/gsd-core/bin/lib/check-command-router.cjs +1 -1
- package/gsd-core/bin/lib/clock.cjs +19 -0
- package/gsd-core/bin/lib/commands.cjs +48 -9
- package/gsd-core/bin/lib/config-loader.cjs +6 -2
- package/gsd-core/bin/lib/config.cjs +12 -0
- package/gsd-core/bin/lib/core-utils.cjs +8 -2
- package/gsd-core/bin/lib/drift.cjs +4 -4
- package/gsd-core/bin/lib/frontmatter.cjs +22 -0
- package/gsd-core/bin/lib/gsd2-import.cjs +2 -1
- package/gsd-core/bin/lib/host-integration.cjs +33 -8
- package/gsd-core/bin/lib/init.cjs +60 -53
- package/gsd-core/bin/lib/install-engine.cjs +93 -22
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +2 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +3 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +1 -1
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +342 -0
- package/gsd-core/bin/lib/markdown-table.cjs +698 -0
- package/gsd-core/bin/lib/mcp-server.cjs +18 -7
- package/gsd-core/bin/lib/milestone.cjs +217 -31
- package/gsd-core/bin/lib/phase-command-router.cjs +50 -2
- package/gsd-core/bin/lib/phase-lifecycle.cjs +62 -36
- package/gsd-core/bin/lib/phase-locator.cjs +23 -2
- package/gsd-core/bin/lib/phase.cjs +436 -61
- package/gsd-core/bin/lib/plan-scan.cjs +3 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +24 -7
- package/gsd-core/bin/lib/roadmap-parser.cjs +218 -13
- package/gsd-core/bin/lib/roadmap.cjs +100 -49
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +242 -44
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +3 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +24 -14
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +19 -5
- package/gsd-core/bin/lib/runtime-homes.cjs +22 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +526 -29
- package/gsd-core/bin/lib/runtime-name-policy.cjs +63 -5
- package/gsd-core/bin/lib/schema-detect.cjs +2 -1
- package/gsd-core/bin/lib/security.cjs +7 -37
- package/gsd-core/bin/lib/shell-command-projection.cjs +176 -27
- package/gsd-core/bin/lib/smart-entry.cjs +4 -3
- package/gsd-core/bin/lib/stale-bake-guard.cjs +30 -10
- package/gsd-core/bin/lib/state-transition.cjs +100 -45
- package/gsd-core/bin/lib/state.cjs +391 -126
- package/gsd-core/bin/lib/surface.cjs +12 -8
- package/gsd-core/bin/lib/template.cjs +2 -1
- package/gsd-core/bin/lib/uat.cjs +54 -8
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +249 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +23 -1
- package/gsd-core/bin/lib/verify.cjs +4 -3
- package/gsd-core/bin/lib/workstream.cjs +3 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +1 -1
- package/gsd-core/bin/lib/write-set.cjs +38 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -3
- package/gsd-core/references/checkpoints.md +12 -0
- package/gsd-core/references/ui-consideration-probe.md +73 -0
- package/gsd-core/templates/UI-SPEC.md +25 -0
- package/gsd-core/templates/VALIDATION.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/audit-milestone.md +7 -4
- package/gsd-core/workflows/debug.md +2 -0
- package/gsd-core/workflows/execute-phase.md +5 -3
- package/gsd-core/workflows/fast.md +8 -22
- package/gsd-core/workflows/plan-phase.md +6 -0
- package/gsd-core/workflows/progress.md +2 -2
- package/gsd-core/workflows/quick.md +2 -0
- package/gsd-core/workflows/review.md +42 -3
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/settings-advanced.md +7 -4
- package/gsd-core/workflows/ship.md +8 -2
- package/gsd-core/workflows/spec-phase.md +1 -1
- package/gsd-core/workflows/transition.md +1 -1
- package/gsd-core/workflows/ui-phase.md +146 -1
- package/gsd-core/workflows/validate-phase.md +2 -2
- package/hooks/dist/gsd-statusline.js +164 -14
- package/hooks/dist/gsd-windsurf-pre-command.js +275 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +132 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-statusline.js +164 -14
- package/hooks/gsd-windsurf-pre-command.js +275 -0
- package/hooks/gsd-windsurf-pre-write.js +132 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +10 -4
- package/pi/gsd.cjs +354 -0
- package/scripts/build-hooks.js +3 -0
- package/scripts/ci-test-scope.cjs +39 -1
- package/scripts/gen-golden-install-parity-zcode.cjs +35 -35
- package/scripts/gen-install-tree-fixtures.cjs +75 -0
- package/scripts/gen-registry.cjs +128 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -1
- package/scripts/lint-table-schema-drift.cjs +157 -0
- package/scripts/lint-test-file-count.allowlist.json +2 -1
- package/scripts/registry-schema.cjs +565 -0
- package/scripts/validate-registry.cjs +117 -0
- package/skills/gsd-mempalace-capture/SKILL.md +27 -1
- package/skills/gsd-surface/SKILL.md +6 -6
- package/vscode/browser.js +197 -0
- package/vscode/extension.js +383 -0
- package/vscode/host-binding.js +113 -0
- package/vscode/package.json +96 -0
|
@@ -55,7 +55,33 @@ This step is `onError: skip` at `discuss:post` / `plan:post` / `verify:post` --
|
|
|
55
55
|
On any error or timeout, stop and let the phase continue -- capture is best-effort.
|
|
56
56
|
|
|
57
57
|
1. **Dedup first.** Interactive: `mempalace_check_duplicate` on the artifact's deterministic drawer id. Headless: rely on `mempalace mine`'s content-hash idempotency.
|
|
58
|
-
2. **Add the drawer (verbatim).** File the exact artifact text into `room: <room>` of `wing: <wing>` with provenance (`source_file`, phase id). Interactive: `mempalace_add_drawer`. Headless:
|
|
58
|
+
2. **Add the drawer (verbatim).** File the exact artifact text into `room: <room>` of `wing: <wing>` with provenance (`source_file`, phase id). Interactive: `mempalace_add_drawer`. Headless: see below.
|
|
59
|
+
|
|
60
|
+
**`mempalace mine` has no `--room` flag** — only `search` accepts `--room` ([CLI reference: https://mempalaceofficial.com/reference/cli.html](https://mempalaceofficial.com/reference/cli.html)). Room assignment is driven by `detect_room()` matching folder-path segments against the `rooms:` list in `mempalace.yaml` ([mining guide: https://mempalaceofficial.com/guide/mining.html](https://mempalaceofficial.com/guide/mining.html) — "Rooms are auto-detected from your folder structure"; [config reference: https://mempalaceofficial.com/guide/configuration.html](https://mempalaceofficial.com/guide/configuration.html)). Stage the artifact under a room-named folder so `detect_room()` assigns it correctly:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
STAGE=".planning/.mempalace-stage"
|
|
64
|
+
# One-time: declare the GSD room taxonomy so detect_room() recognizes these folders
|
|
65
|
+
mkdir -p "$STAGE"
|
|
66
|
+
[ -f "$STAGE/mempalace.yaml" ] || cat > "$STAGE/mempalace.yaml" <<'YAML'
|
|
67
|
+
rooms:
|
|
68
|
+
- decisions
|
|
69
|
+
- planning
|
|
70
|
+
- milestones
|
|
71
|
+
- problems
|
|
72
|
+
- general
|
|
73
|
+
YAML
|
|
74
|
+
# Suppress MemPalace cache artifacts written into the scanned tree
|
|
75
|
+
[ -f "$STAGE/.gitignore" ] || echo "mempalace_embedder.json" > "$STAGE/.gitignore"
|
|
76
|
+
# Stage under <room>/<phase-id>/<basename> — stable path so mine's content-hash
|
|
77
|
+
# idempotency (file_already_mined keys on absolute source_file + mtime) deduplicates
|
|
78
|
+
# instead of creating duplicate drawers on re-runs.
|
|
79
|
+
ROOM_DIR="$STAGE/<room>/<phase-id>"
|
|
80
|
+
mkdir -p "$ROOM_DIR"
|
|
81
|
+
cp "<artifact-path>" "$ROOM_DIR/<basename>"
|
|
82
|
+
# Mine with --wing only — no --room flag; detect_room() assigns from the folder path
|
|
83
|
+
mempalace mine "$STAGE" --wing <wing>
|
|
84
|
+
```
|
|
59
85
|
3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(<project>, decided, <decision>)` from CONTEXT; `(<phase>, delivered, <capability>)` from SUMMARY). Under `augment` these are an *additive* mirror of GSD's native `.planning/graphs/`. Under `kg_backend`/`replace` the palace KG is the *authoritative* fact store — GSD still produces `.planning/graphs/` through its normal graphify, so an unreachable palace never loses a fact.
|
|
60
86
|
4. Re-running a phase MUST NOT create duplicate drawers (deterministic ids + `check_duplicate`).
|
|
61
87
|
|
package/commands/gsd/surface.md
CHANGED
|
@@ -37,9 +37,9 @@ Parse the first token of $ARGUMENTS:
|
|
|
37
37
|
## list / status
|
|
38
38
|
|
|
39
39
|
Load the capability registry and call `listSurface(runtimeConfigDir, manifest, CLUSTERS, registry)` from
|
|
40
|
-
|
|
40
|
+
the engine module at `${runtimeConfigDir}/gsd-core/bin/lib/surface.cjs`. The registry is loaded via:
|
|
41
41
|
```js
|
|
42
|
-
const registry = require('gsd-core/bin/lib/capability-registry.cjs');
|
|
42
|
+
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
43
43
|
```
|
|
44
44
|
Display:
|
|
45
45
|
|
|
@@ -71,7 +71,7 @@ Install profile: standard (from .gsd-profile)
|
|
|
71
71
|
3. `writeSurface(runtimeConfigDir, surfaceState)`.
|
|
72
72
|
4. Resolve and re-apply:
|
|
73
73
|
```js
|
|
74
|
-
const registry = require('gsd-core/bin/lib/capability-registry.cjs');
|
|
74
|
+
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
75
75
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
76
76
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
77
77
|
```
|
|
@@ -89,7 +89,7 @@ Valid cluster names: `core_loop`, `audit_review`, `milestone`, `research_ideate`
|
|
|
89
89
|
3. Add cluster to `surfaceState.disabledClusters` (deduplicate).
|
|
90
90
|
4. `writeSurface` → resolve layout → `applySurface`:
|
|
91
91
|
```js
|
|
92
|
-
const registry = require('gsd-core/bin/lib/capability-registry.cjs');
|
|
92
|
+
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
93
93
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
94
94
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
95
95
|
```
|
|
@@ -103,7 +103,7 @@ Valid cluster names: `core_loop`, `audit_review`, `milestone`, `research_ideate`
|
|
|
103
103
|
2. Remove cluster from `surfaceState.disabledClusters`.
|
|
104
104
|
3. `writeSurface` → resolve layout → `applySurface`:
|
|
105
105
|
```js
|
|
106
|
-
const registry = require('gsd-core/bin/lib/capability-registry.cjs');
|
|
106
|
+
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
107
107
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
108
108
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
109
109
|
```
|
|
@@ -151,7 +151,7 @@ All paths can be overridden by reading the `CLAUDE_CONFIG_DIR` env var if set.
|
|
|
151
151
|
|
|
152
152
|
- Unknown cluster name → list valid cluster names, exit without writing.
|
|
153
153
|
- Unknown profile name → list known profiles (`core`, `standard`, `full`), exit.
|
|
154
|
-
- Missing `surface.cjs` → prompt: "Run `npm i -g gsd-core` to reinstall GSD."
|
|
154
|
+
- Missing `surface.cjs` → prompt: "Run `npm i -g @opengsd/gsd-core` to reinstall GSD."
|
|
155
155
|
|
|
156
156
|
<execution_context>
|
|
157
157
|
Surface state file: `~/.claude/.gsd-surface.json`
|
|
@@ -27,6 +27,12 @@
|
|
|
27
27
|
* list-todos [area] Count and enumerate pending todos
|
|
28
28
|
* list-seeds [status] List captured seeds (optional status filter)
|
|
29
29
|
* verify-path-exists <path> Check file/directory existence
|
|
30
|
+
* quick-tasks-append --task <text> Append a row to STATE.md's "Quick Tasks
|
|
31
|
+
* Completed" table (schema-backed via
|
|
32
|
+
* markdown-table.cjs; #2133/ADR-2143).
|
|
33
|
+
* Fails loud (non-zero exit) on a missing
|
|
34
|
+
* or unrecognized table instead of the old
|
|
35
|
+
* awk NF-2 silent-skip guess.
|
|
30
36
|
* config-ensure-section Initialize .planning/config.json
|
|
31
37
|
* history-digest Aggregate all SUMMARY.md data
|
|
32
38
|
* summary-extract <path> [--fields] Extract structured data from SUMMARY.md
|
|
@@ -693,7 +699,7 @@ async function main() {
|
|
|
693
699
|
'from-gsd2, frontmatter, gap-analysis, generate-claude-md, generate-claude-profile, ' +
|
|
694
700
|
'generate-dev-preferences, generate-slug, graphify, history-digest, init, intel, ' +
|
|
695
701
|
'capability, classify-confidence, git, learnings, list-seeds, list-todos, loop, milestone, package-legitimacy, phase, phase-plan-index, phases, profile-questionnaire, ' +
|
|
696
|
-
'profile-sample, progress, project-instruction-file, prompt-budget, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, smart-entry, state, ' +
|
|
702
|
+
'profile-sample, progress, project-instruction-file, prompt-budget, quick-tasks-append, requirements, research-plan, research-store, resolve-granularity, resolve-model, roadmap, scaffold, smart-entry, state, ' +
|
|
697
703
|
'task, template, user-story, validate, verify, verify-path-exists, verify-summary, eval, workstream, worktree\n\n' +
|
|
698
704
|
'Global flags:\n' +
|
|
699
705
|
' --raw Emit raw output without post-processing\n' +
|
|
@@ -1213,6 +1219,59 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1213
1219
|
break;
|
|
1214
1220
|
}
|
|
1215
1221
|
|
|
1222
|
+
case 'quick-tasks-append': {
|
|
1223
|
+
// #2133 / ADR-2143 §3,§7: schema-backed replacement for fast.md's inline
|
|
1224
|
+
// `awk NF-2` Quick Tasks column arithmetic. Row construction is delegated
|
|
1225
|
+
// to the pure appendQuickTaskRow (markdown-table.cjs); this case only
|
|
1226
|
+
// handles the I/O (read STATE.md, resolve date/commit, write STATE.md).
|
|
1227
|
+
const qtaArgs = args.slice(1);
|
|
1228
|
+
const qtaTask = parseNamedArgs(qtaArgs, ['task']).task || args[1];
|
|
1229
|
+
if (!qtaTask) {
|
|
1230
|
+
error('quick-tasks-append requires --task <description> (or a positional description)', ERROR_REASON.USAGE);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
const statePath = path.join(cwd, '.planning', 'STATE.md');
|
|
1234
|
+
if (!fs.existsSync(statePath)) {
|
|
1235
|
+
error(`quick-tasks-append: STATE.md not found at ${statePath}`, ERROR_REASON.USAGE);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
1239
|
+
const { execGit } = require('./lib/shell-command-projection.cjs');
|
|
1240
|
+
const hashResult = execGit(['rev-parse', '--short', 'HEAD'], { cwd });
|
|
1241
|
+
const commit = hashResult.exitCode === 0 && hashResult.stdout ? hashResult.stdout : '—';
|
|
1242
|
+
|
|
1243
|
+
const { appendQuickTaskRow } = require('./lib/markdown-table.cjs');
|
|
1244
|
+
|
|
1245
|
+
// #2242 review fix: route the read -> mutate -> write cycle through
|
|
1246
|
+
// state.readModifyWriteStateMd (lib/state.cjs) instead of a raw
|
|
1247
|
+
// fs.readFileSync + fs.writeFileSync pair, so the whole read-modify-write
|
|
1248
|
+
// is atomic under STATE.md's lockfile — closing the lost-update race a
|
|
1249
|
+
// raw read/write pair left open (cf. #500/#905/#1230). This mirrors the
|
|
1250
|
+
// pattern every other STATE.md-mutating case in state.cts uses (e.g.
|
|
1251
|
+
// cmdStateAddBlocker, cmdStateAddDecision): a mutable outer variable
|
|
1252
|
+
// captures the pure helper's side output, and a fail-loud reason throws
|
|
1253
|
+
// ExitError from INSIDE the transform (readModifyWriteStateMd's finally
|
|
1254
|
+
// still releases the lock before the throw propagates; the transform
|
|
1255
|
+
// throws before returning new content, so nothing is ever written).
|
|
1256
|
+
let mutation;
|
|
1257
|
+
state.readModifyWriteStateMd(statePath, (content) => {
|
|
1258
|
+
const result = appendQuickTaskRow(content, { description: qtaTask, date, commit });
|
|
1259
|
+
if (!result.ok) {
|
|
1260
|
+
// Mirrors fast.md's old "skip with a brief log" behaviour (#2133): this
|
|
1261
|
+
// is an expected, recoverable condition (no table / unrecognized
|
|
1262
|
+
// schema), not a hard crash. ExitError sets a non-zero exit code (so
|
|
1263
|
+
// fast.md's `|| echo ...` fallback fires) without calling
|
|
1264
|
+
// process.exit() directly — stdout stays flushed and untouched.
|
|
1265
|
+
throw new ExitError(1, `⚠ quick-tasks-append: ${result.reason}`);
|
|
1266
|
+
}
|
|
1267
|
+
mutation = result.value;
|
|
1268
|
+
return result.value.content;
|
|
1269
|
+
}, cwd);
|
|
1270
|
+
|
|
1271
|
+
output({ ok: true, row: mutation.row, variant: mutation.variant }, raw, mutation.row);
|
|
1272
|
+
break;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1216
1275
|
case 'config-ensure-section': {
|
|
1217
1276
|
// Phase 6 (#3575): dispatch via SDK executeForCjs. The catalog rebinds
|
|
1218
1277
|
// 'config-ensure-section' to configNewProject in
|
|
@@ -1500,7 +1559,9 @@ async function runCommand(command, args, cwd, raw, defaultValue, originalCommand
|
|
|
1500
1559
|
// new-milestone never inherits un-archived dirs. --no-archive-phases opts out.
|
|
1501
1560
|
const archivePhases = !args.includes('--no-archive-phases');
|
|
1502
1561
|
const force = args.includes('--force');
|
|
1503
|
-
|
|
1562
|
+
// #2118: --dry-run prints a preview plan without mutating.
|
|
1563
|
+
const dryRun = args.includes('--dry-run');
|
|
1564
|
+
milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases, force, dryRun }, raw);
|
|
1504
1565
|
} else {
|
|
1505
1566
|
error('Unknown milestone subcommand. Available: complete', ERROR_REASON.SDK_UNKNOWN_COMMAND);
|
|
1506
1567
|
}
|
|
@@ -264,13 +264,12 @@ function parseCoverageMatrix(text) {
|
|
|
264
264
|
const src = text.replace(/\r\n/g, '\n');
|
|
265
265
|
// (1) fenced ```coverage JSON block takes precedence if present.
|
|
266
266
|
// Case-insensitive info string (```coverage and ```Coverage are both legal CommonMark).
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (fenceMatch && fenceMatch[1]) {
|
|
267
|
+
const fenceBody = (0, markdown_sectionizer_cjs_1.extractFencedBlock)(src, 'coverage');
|
|
268
|
+
if (fenceBody) {
|
|
270
269
|
out.format = 'json';
|
|
271
270
|
let parsed;
|
|
272
271
|
try {
|
|
273
|
-
parsed = JSON.parse(
|
|
272
|
+
parsed = JSON.parse(fenceBody);
|
|
274
273
|
}
|
|
275
274
|
catch {
|
|
276
275
|
out.errors.push('fenced ```coverage block is not valid JSON');
|
|
@@ -17,6 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
18
18
|
const node_path_1 = __importDefault(require("node:path"));
|
|
19
19
|
const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
|
|
20
|
+
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
20
21
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
21
22
|
const planningWorkspace = require("./planning-workspace.cjs");
|
|
22
23
|
const { planningDir } = planningWorkspace;
|
|
@@ -71,9 +72,9 @@ function scanDebugSessions(planDir) {
|
|
|
71
72
|
continue;
|
|
72
73
|
// Extract hypothesis from "Current Focus" block if parseable
|
|
73
74
|
let hypothesis = '';
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
const focusText =
|
|
75
|
+
const focusSection = (0, markdown_sectionizer_cjs_1.collectSection)(content, (h) => h.level === 2 && h.text.trim().toLowerCase().startsWith('current focus'), { levelBounded: true });
|
|
76
|
+
if (focusSection) {
|
|
77
|
+
const focusText = focusSection.body.trim().split('\n')[0].trim();
|
|
77
78
|
hypothesis = (0, security_cjs_1.sanitizeForDisplay)(focusText.slice(0, 100));
|
|
78
79
|
}
|
|
79
80
|
const slug = node_path_1.default.basename(entry.name, '.md');
|
|
@@ -509,9 +510,9 @@ function scanContextQuestions(planDir) {
|
|
|
509
510
|
}
|
|
510
511
|
// Also check for ## Open Questions section in body
|
|
511
512
|
if (questions.length === 0) {
|
|
512
|
-
const
|
|
513
|
-
if (
|
|
514
|
-
const oqBody =
|
|
513
|
+
const oqSection = (0, markdown_sectionizer_cjs_1.collectSection)(content, (h) => h.level === 2 && h.text.trim().toLowerCase().startsWith('open questions'), { levelBounded: true });
|
|
514
|
+
if (oqSection) {
|
|
515
|
+
const oqBody = oqSection.body.trim();
|
|
515
516
|
if (oqBody && oqBody.length > 0 && !/^\s*none\s*$/i.test(oqBody)) {
|
|
516
517
|
const items = oqBody.split('\n')
|
|
517
518
|
.map((l) => l.trim())
|