peaks-loop 4.0.32 → 4.0.34

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.
Files changed (111) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README-en.md +3 -4
  3. package/README.md +20 -28
  4. package/dist/cli/commands/_register.js +4 -3
  5. package/dist/cli/commands/audit-commands.js +12 -39
  6. package/dist/cli/commands/capability-commands.d.ts +6 -0
  7. package/dist/cli/commands/capability-commands.js +20 -2
  8. package/dist/cli/commands/code-commands.js +2 -0
  9. package/dist/cli/commands/code-mode-gate-commands.js +3 -3
  10. package/dist/cli/commands/code-mode-status-command.d.ts +17 -0
  11. package/dist/cli/commands/code-mode-status-command.js +51 -0
  12. package/dist/cli/commands/code-run-command.js +8 -1
  13. package/dist/cli/commands/code-runtime-commands.js +13 -5
  14. package/dist/cli/commands/core/skill-command.js +1 -1
  15. package/dist/cli/commands/ecc-commands.js +3 -2
  16. package/dist/cli/commands/project-commands.js +1 -1
  17. package/dist/cli/commands/request-commands.js +3 -7
  18. package/dist/cli/commands/session-24h-mode.js +9 -1
  19. package/dist/cli/commands/shadcn-commands.d.ts +32 -0
  20. package/dist/cli/commands/shadcn-commands.js +120 -0
  21. package/dist/cli/commands/slice-commands.js +1 -4
  22. package/dist/services/24h-mode/auto-engage.d.ts +39 -0
  23. package/dist/services/24h-mode/auto-engage.js +46 -0
  24. package/dist/services/24h-mode/decider.d.ts +11 -5
  25. package/dist/services/24h-mode/decider.js +13 -13
  26. package/dist/services/audit/enforcers/active-skill-resolver.d.ts +3 -1
  27. package/dist/services/audit/enforcers/active-skill-resolver.js +3 -5
  28. package/dist/services/audit/static-service.d.ts +1 -1
  29. package/dist/services/audit/static-service.js +1 -1
  30. package/dist/services/code/auto-compact-lifecycle.d.ts +1 -1
  31. package/dist/services/code/auto-compact-lifecycle.js +1 -1
  32. package/dist/services/code/auto-compact-modes.d.ts +1 -1
  33. package/dist/services/code/auto-compact-modes.js +1 -1
  34. package/dist/services/code/auto-compact-orchestrator.js +18 -22
  35. package/dist/services/code/mode-gate.d.ts +6 -2
  36. package/dist/services/code/mode-gate.js +9 -5
  37. package/dist/services/code/orchestrator-can-do.js +2 -2
  38. package/dist/services/code-review/ecc-bridge.d.ts +94 -15
  39. package/dist/services/code-review/ecc-bridge.js +133 -13
  40. package/dist/services/config/config-service.d.ts +17 -0
  41. package/dist/services/config/config-service.js +34 -0
  42. package/dist/services/context/auto-compact-dispatcher.d.ts +2 -2
  43. package/dist/services/context/auto-compact-dispatcher.js +4 -4
  44. package/dist/services/context/auto-compact-reader.js +8 -1
  45. package/dist/services/context/auto-compact-types.d.ts +13 -1
  46. package/dist/services/context/build-dispatch-system-prompt.js +2 -2
  47. package/dist/services/context/context-schema.d.ts +1 -1
  48. package/dist/services/dashboard/project-dashboard-service.d.ts +0 -7
  49. package/dist/services/dashboard/project-dashboard-service.js +1 -9
  50. package/dist/services/hooks/auto-compact-hook-install.d.ts +2 -2
  51. package/dist/services/hooks/auto-compact-hook-install.js +2 -2
  52. package/dist/services/ide/adapters/claude-code-adapter.d.ts +51 -0
  53. package/dist/services/ide/adapters/claude-code-adapter.js +84 -14
  54. package/dist/services/ide/ide-types.d.ts +10 -1
  55. package/dist/services/mode/mode-enforcement.d.ts +4 -1
  56. package/dist/services/mode/mode-enforcement.js +26 -28
  57. package/dist/services/mode/mode-status-service.d.ts +81 -0
  58. package/dist/services/mode/mode-status-service.js +108 -0
  59. package/dist/services/preferences/preferences-types.d.ts +16 -7
  60. package/dist/services/recommendations/capability-seed-items.js +0 -1
  61. package/dist/services/recommendations/installed-capability-detector.d.ts +33 -0
  62. package/dist/services/recommendations/installed-capability-detector.js +76 -0
  63. package/dist/services/scan/orphan-service.js +1 -1
  64. package/dist/services/skills/presence-lease-service.d.ts +21 -0
  65. package/dist/services/skills/presence-lease-service.js +26 -0
  66. package/dist/services/skills/skill-presence-service.d.ts +10 -1
  67. package/dist/services/skills/skill-presence-service.js +32 -4
  68. package/dist/services/skills/skill-statusline-service.js +6 -3
  69. package/dist/services/slice/multi-pass-orchestrator.js +0 -13
  70. package/dist/services/slice/slice-decompose-import-edges.d.ts +2 -2
  71. package/dist/services/slice/slice-decompose-import-edges.js +1 -29
  72. package/dist/services/slice/slice-decompose-runners.d.ts +2 -4
  73. package/dist/services/slice/slice-decompose-runners.js +1 -23
  74. package/dist/services/slice/slice-decompose-service.d.ts +3 -4
  75. package/dist/services/slice/slice-decompose-service.js +10 -29
  76. package/dist/services/slice/slice-decompose-types.d.ts +6 -47
  77. package/dist/services/slice/slice-decompose-types.js +3 -2
  78. package/dist/services/slice/slice-topology-types.d.ts +2 -3
  79. package/package.json +5 -5
  80. package/schemas/decomposition-v1.json +0 -12
  81. package/schemas/decomposition-v2.json +1 -15
  82. package/skills/bee/peaks-prd/SKILL.md +0 -1
  83. package/skills/bee/peaks-rd/SKILL.md +1 -1
  84. package/skills/bee/peaks-rd/references/external-references.md +1 -3
  85. package/skills/bee/peaks-rd/references/parallel-review-fanout.md +7 -2
  86. package/skills/bee/peaks-rd/references/rd-fanout-contracts.md +22 -8
  87. package/skills/bee/peaks-rd/references/rd-runbook.md +0 -2
  88. package/skills/bee/peaks-txt/SKILL.md +0 -12
  89. package/skills/peaks-code/SKILL.md +9 -9
  90. package/skills/peaks-code/references/mode-selection.md +7 -3
  91. package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
  92. package/skills/peaks-code/references/runbook.md +10 -5
  93. package/skills/peaks-code/references/session-overload-signal-index.md +2 -2
  94. package/skills/peaks-code/references/standards-preflight.md +1 -1
  95. package/skills/peaks-code/references/startup-sequence.md +1 -1
  96. package/skills/peaks-code/references/step-0-8-gate.md +1 -1
  97. package/skills/peaks-code/references/swarm-dispatch-contract.md +2 -2
  98. package/skills/peaks-code/references/workflow-gates-and-types.md +1 -1
  99. package/skills/peaks-doctor/SKILL.md +1 -1
  100. package/skills/peaks-slice-decompose/SKILL.md +0 -1
  101. package/skills/peaks-slice-decompose/references/v2-schema.md +1 -12
  102. package/dist/cli/commands/understand-commands.d.ts +0 -3
  103. package/dist/cli/commands/understand-commands.js +0 -148
  104. package/dist/services/understand/hybrid-types.d.ts +0 -32
  105. package/dist/services/understand/hybrid-types.js +0 -1
  106. package/dist/services/understand/understand-hybrid-service.d.ts +0 -10
  107. package/dist/services/understand/understand-hybrid-service.js +0 -100
  108. package/dist/services/understand/understand-scan-service.d.ts +0 -28
  109. package/dist/services/understand/understand-scan-service.js +0 -170
  110. package/dist/services/understand/understand-types.d.ts +0 -50
  111. package/dist/services/understand/understand-types.js +0 -1
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Read-only "is this capability already satisfied on this machine?"
3
+ * detector for the capability catalog (`peaks capability status` /
4
+ * `peaks capabilities --source ...`).
5
+ *
6
+ * Slice B1 of 2026-09-09-ecc-dynamic-and-cleanup: the previous
7
+ * `getInstalledCapabilityIds()` returned `[]` unconditionally, so the
8
+ * catalog could never report anything as installed. This module answers
9
+ * the question from evidence that already exists on disk — no install
10
+ * side effect, no network, no subprocess:
11
+ *
12
+ * - `everything-claude-code.*` — satisfied when the ECC cache is
13
+ * populated (`~/.peaks/cache/ecc-installed.json` + at least one
14
+ * cached/materialized agent).
15
+ * - a source that maps to an npm package — satisfied when that package
16
+ * (or its `.bin` shim) is present in the project's `node_modules`.
17
+ *
18
+ * Every probe is fail-soft: a throw degrades to "not installed" so the
19
+ * catalog never breaks because a probe failed.
20
+ */
21
+ export type InstalledCapabilityProbe = {
22
+ /** Project whose `node_modules` is probed. */
23
+ readonly projectRoot: string;
24
+ /** Override for tests; defaults to `<projectRoot>/node_modules`. */
25
+ readonly nodeModulesDir?: string;
26
+ /** Override for tests; defaults to a live ECC cache probe. */
27
+ readonly eccCacheAvailable?: boolean;
28
+ };
29
+ /**
30
+ * Return the capabilityIds whose acquisition is already satisfied.
31
+ * Sorted + de-duplicated so the JSON envelope is stable across runs.
32
+ */
33
+ export declare function detectInstalledCapabilityIds(probe: InstalledCapabilityProbe): string[];
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Read-only "is this capability already satisfied on this machine?"
3
+ * detector for the capability catalog (`peaks capability status` /
4
+ * `peaks capabilities --source ...`).
5
+ *
6
+ * Slice B1 of 2026-09-09-ecc-dynamic-and-cleanup: the previous
7
+ * `getInstalledCapabilityIds()` returned `[]` unconditionally, so the
8
+ * catalog could never report anything as installed. This module answers
9
+ * the question from evidence that already exists on disk — no install
10
+ * side effect, no network, no subprocess:
11
+ *
12
+ * - `everything-claude-code.*` — satisfied when the ECC cache is
13
+ * populated (`~/.peaks/cache/ecc-installed.json` + at least one
14
+ * cached/materialized agent).
15
+ * - a source that maps to an npm package — satisfied when that package
16
+ * (or its `.bin` shim) is present in the project's `node_modules`.
17
+ *
18
+ * Every probe is fail-soft: a throw degrades to "not installed" so the
19
+ * catalog never breaks because a probe failed.
20
+ */
21
+ import { existsSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ import { hasMaterializedEccAgents, listCachedAgents } from 'peaks-loop-mut';
24
+ import { seedCapabilityItems } from './capability-seed-items.js';
25
+ const ECC_SOURCE_ID = 'everything-claude-code';
26
+ /**
27
+ * `sourceId` → npm package whose presence in `node_modules` satisfies the
28
+ * item's acquisition. Deliberately explicit: the catalog mixes repos,
29
+ * skills packages, MCP servers, and docs, and only a small subset is
30
+ * actually an npm dependency we can probe. Adding an entry here is the
31
+ * only change needed to make that source's items detectable.
32
+ */
33
+ const NPM_PACKAGE_BY_SOURCE = {
34
+ codegraph: 'codegraph'
35
+ };
36
+ function packagePresent(nodeModulesDir, packageName) {
37
+ try {
38
+ return (existsSync(join(nodeModulesDir, packageName)) ||
39
+ existsSync(join(nodeModulesDir, '.bin', packageName)));
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ function eccCacheAvailable() {
46
+ try {
47
+ // Cached agents imply the manifest + sha dir exist; the materialized
48
+ // plugin-free copy is checked independently so a hand-populated
49
+ // `~/.peaks/agents/ecc/` still counts as satisfied.
50
+ return listCachedAgents().length > 0 || hasMaterializedEccAgents();
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ /**
57
+ * Return the capabilityIds whose acquisition is already satisfied.
58
+ * Sorted + de-duplicated so the JSON envelope is stable across runs.
59
+ */
60
+ export function detectInstalledCapabilityIds(probe) {
61
+ const nodeModulesDir = probe.nodeModulesDir ?? join(probe.projectRoot, 'node_modules');
62
+ const eccAvailable = probe.eccCacheAvailable ?? eccCacheAvailable();
63
+ const installed = new Set();
64
+ for (const item of seedCapabilityItems) {
65
+ if (item.sourceId === ECC_SOURCE_ID) {
66
+ if (eccAvailable)
67
+ installed.add(item.capabilityId);
68
+ continue;
69
+ }
70
+ const packageName = NPM_PACKAGE_BY_SOURCE[item.sourceId];
71
+ if (packageName !== undefined && packagePresent(nodeModulesDir, packageName)) {
72
+ installed.add(item.capabilityId);
73
+ }
74
+ }
75
+ return [...installed].sort();
76
+ }
@@ -26,7 +26,7 @@ const PARENT_COMMANDS = new Set([
26
26
  'qa', 'sc', 'txt', 'code-review', 'rd', 'sh', 'config', 'audit', 'codegraph',
27
27
  'context', 'agent', 'capability', 'classify', 'gstack', 'gate',
28
28
  'hook', 'hooks', 'log', 'loop', 'memory', 'perf', 'playwright', 'preferences',
29
- 'project', 'retrospective', 'slice', 'statusline', 'understand', 'workflow',
29
+ 'project', 'retrospective', 'slice', 'statusline', 'workflow',
30
30
  'migrate', 'mcp', 'doctor', 'help'
31
31
  ]);
32
32
  const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', 'coverage']);
@@ -66,6 +66,27 @@ export interface GcPresenceLeasesInput {
66
66
  readonly trigger?: 'manual' | 'workspace-init' | 'presence-set';
67
67
  }
68
68
  export declare function setPresenceLease(input: SetPresenceLeaseInput): SetPresenceLeaseResult;
69
+ /**
70
+ * Slice 2026-09-09-mode-consolidation (Slice B): stamp `mode` onto every
71
+ * in-flight lease of the bound session, in place.
72
+ *
73
+ * Used by the 24h auto-engage path (T3/T4, `peaks code run --24h`,
74
+ * `peaks session 24h-mode transition --state 24H_ACTIVE`) to record the
75
+ * autonomy level without re-creating the lease (a fresh `setPresenceLease`
76
+ * would reset `startedAt` / `status`). `lastHeartbeat` is intentionally
77
+ * NOT touched — stamping a mode is not a liveness signal.
78
+ *
79
+ * Returns the number of leases updated; 0 when there is nothing in flight.
80
+ * Callers are responsible for the "only `24h` may be auto-set" guard.
81
+ */
82
+ export declare function stampPresenceLeaseMode(input: {
83
+ readonly projectRoot: string;
84
+ readonly sessionId: string;
85
+ readonly mode: string;
86
+ }): {
87
+ updated: number;
88
+ leasePaths: string[];
89
+ };
69
90
  export declare function readPresenceLease(input: ReadPresenceLeaseInput): PresenceProjection;
70
91
  export declare function markPresenceLost(input: MarkPresenceLostInput): SkillPresenceLease;
71
92
  export declare function gcStalePresenceLeases(input: GcPresenceLeasesInput): GcResult;
@@ -175,6 +175,32 @@ export function setPresenceLease(input) {
175
175
  gc,
176
176
  };
177
177
  }
178
+ /**
179
+ * Slice 2026-09-09-mode-consolidation (Slice B): stamp `mode` onto every
180
+ * in-flight lease of the bound session, in place.
181
+ *
182
+ * Used by the 24h auto-engage path (T3/T4, `peaks code run --24h`,
183
+ * `peaks session 24h-mode transition --state 24H_ACTIVE`) to record the
184
+ * autonomy level without re-creating the lease (a fresh `setPresenceLease`
185
+ * would reset `startedAt` / `status`). `lastHeartbeat` is intentionally
186
+ * NOT touched — stamping a mode is not a liveness signal.
187
+ *
188
+ * Returns the number of leases updated; 0 when there is nothing in flight.
189
+ * Callers are responsible for the "only `24h` may be auto-set" guard.
190
+ */
191
+ export function stampPresenceLeaseMode(input) {
192
+ const sessionId = validateSessionId(input.sessionId);
193
+ const leasePaths = [];
194
+ for (const lease of listPresenceLeases(input.projectRoot, sessionId)) {
195
+ if (lease.status !== 'preparing' && lease.status !== 'running')
196
+ continue;
197
+ const path = leaseFilePath(input.projectRoot, sessionId, lease.callerId, lease.workflowId);
198
+ const next = { ...lease, mode: input.mode };
199
+ writeAtomic(path, JSON.stringify(next, null, 2));
200
+ leasePaths.push(path);
201
+ }
202
+ return { updated: leasePaths.length, leasePaths };
203
+ }
178
204
  export function readPresenceLease(input) {
179
205
  const sessionId = validateSessionId(input.sessionId ?? null);
180
206
  const callerId = validateCallerId(input.callerId);
@@ -1,6 +1,15 @@
1
- export type SkillPresenceMode = 'full-auto' | 'assisted' | 'swarm' | 'strict';
1
+ export type SkillPresenceMode = 'full-auto' | 'assisted' | 'strict' | '24h';
2
2
  export declare const VALID_SKILL_PRESENCE_MODES: ReadonlyArray<SkillPresenceMode>;
3
+ export declare const LEGACY_SKILL_PRESENCE_MODE_ALIASES: Readonly<Record<string, SkillPresenceMode>>;
3
4
  export declare function isSkillPresenceMode(value: string): value is SkillPresenceMode;
5
+ /**
6
+ * Normalize a raw on-disk / CLI mode token to a current
7
+ * `SkillPresenceMode`. Current values pass through; the legacy
8
+ * `'swarm'` alias maps to `'full-auto'`; anything else returns
9
+ * `undefined` so the caller can decide (drop the field, not the
10
+ * presence). Never throws.
11
+ */
12
+ export declare function normalizeSkillPresenceMode(value: string | undefined | null): SkillPresenceMode | undefined;
4
13
  export type SkillPresence = {
5
14
  skill: string;
6
15
  mode?: SkillPresenceMode;
@@ -20,12 +20,33 @@ void null;
20
20
  export const VALID_SKILL_PRESENCE_MODES = [
21
21
  'full-auto',
22
22
  'assisted',
23
- 'swarm',
24
- 'strict'
23
+ 'strict',
24
+ '24h'
25
25
  ];
26
+ // Migration note (slice 2026-09-09-mode-consolidation): `swarm` was REMOVED
27
+ // as a mode — parallel fan-out is now the default execution strategy in
28
+ // every mode. A legacy on-disk `mode: 'swarm'` is normalized on read to
29
+ // `'full-auto'` (never crash, never drop the presence).
30
+ export const LEGACY_SKILL_PRESENCE_MODE_ALIASES = {
31
+ swarm: 'full-auto'
32
+ };
26
33
  export function isSkillPresenceMode(value) {
27
34
  return VALID_SKILL_PRESENCE_MODES.includes(value);
28
35
  }
36
+ /**
37
+ * Normalize a raw on-disk / CLI mode token to a current
38
+ * `SkillPresenceMode`. Current values pass through; the legacy
39
+ * `'swarm'` alias maps to `'full-auto'`; anything else returns
40
+ * `undefined` so the caller can decide (drop the field, not the
41
+ * presence). Never throws.
42
+ */
43
+ export function normalizeSkillPresenceMode(value) {
44
+ if (typeof value !== 'string' || value.length === 0)
45
+ return undefined;
46
+ if (isSkillPresenceMode(value))
47
+ return value;
48
+ return LEGACY_SKILL_PRESENCE_MODE_ALIASES[value];
49
+ }
29
50
  /**
30
51
  * The current outer session id, exposed to Bash tool calls via the
31
52
  * `PEAKS_OUTER_SESSION_ID` environment variable. Stamping it onto the
@@ -118,8 +139,15 @@ function readSkillPresenceFromLease(projectRootOverride) {
118
139
  // The lease carries `callerId` (the adapter / harness session id),
119
140
  // not the legacy `outerSessionId` field. Project it for back-compat
120
141
  // with `clearStalePresenceOnRotation`'s outer-mismatch check.
142
+ //
143
+ // Slice 2026-09-09-mode-consolidation: `mode` is projected too (it was
144
+ // silently dropped before, which made `getSkillPresence().mode` always
145
+ // undefined and left every `presence.mode` consumer dead). Normalize on
146
+ // read so a legacy `'swarm'` lease surfaces as `'full-auto'`.
147
+ const leaseMode = normalizeSkillPresenceMode(lease.mode);
121
148
  return {
122
149
  skill: lease.skill,
150
+ ...(leaseMode !== undefined ? { mode: leaseMode } : {}),
123
151
  sessionId,
124
152
  outerSessionId: lease.callerId,
125
153
  setAt: lease.startedAt,
@@ -208,7 +236,7 @@ function getPreviousOuterSessionId(projectRootOverride) {
208
236
  * `peakSessionId`, OR via `ensureSession` for the first-time case).
209
237
  */
210
238
  export function setSkillPresenceForCaller(projectRootOverride, callerId, peakSessionId, skill, mode, gate) {
211
- const validatedMode = mode && isSkillPresenceMode(mode) ? mode : undefined;
239
+ const validatedMode = normalizeSkillPresenceMode(mode);
212
240
  const now = new Date().toISOString();
213
241
  const presence = {
214
242
  skill,
@@ -257,7 +285,7 @@ export function setSkillPresence(skill, mode, gate, projectRootOverride) {
257
285
  // the old shape don't break) but we surface a warning to the
258
286
  // CLI boundary via the `outerSessionMismatch` field.
259
287
  // 3. delegates the canonical write to `setPresenceLease`.
260
- const validatedMode = mode && isSkillPresenceMode(mode) ? mode : undefined;
288
+ const validatedMode = normalizeSkillPresenceMode(mode);
261
289
  const sessionId = getCurrentSessionId(projectRootOverride);
262
290
  const outerSessionId = getCurrentOuterSessionId();
263
291
  const previousOuterSessionId = getPreviousOuterSessionId(projectRootOverride);
@@ -30,6 +30,7 @@ import { readActiveDispatchIndex } from '../dispatch/dispatch-record-writer.js';
30
30
  * picks the most recent in-flight lease across all callers; this is the
31
31
  * documented back-compat path.
32
32
  */
33
+ import { normalizeSkillPresenceMode } from './skill-presence-service.js';
33
34
  const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000;
34
35
  /**
35
36
  * Slice rid-statusline-24h-overlay (2026-08-10): name-distinct from
@@ -245,12 +246,14 @@ function readPresenceReadOnly(projectRoot, callerId) {
245
246
  }
246
247
  // Leases on disk may carry an optional `mode` field (the lease constructor
247
248
  // spreads `input.mode` when present); the typed `SkillPresenceLease` does
248
- // not declare it, so widen the read shape here.
249
- const latestMode = latest.mode;
249
+ // not declare it, so widen the read shape here. Normalized on read: a
250
+ // legacy `'swarm'` lease renders as `'full-auto'` (slice
251
+ // 2026-09-09-mode-consolidation).
252
+ const latestMode = normalizeSkillPresenceMode(latest.mode);
250
253
  return {
251
254
  presence: {
252
255
  skill: latest.skill,
253
- ...(typeof latestMode === 'string' && latestMode.length > 0 ? { mode: latestMode } : {}),
256
+ ...(latestMode !== undefined ? { mode: latestMode } : {}),
254
257
  setAt: latest.startedAt,
255
258
  },
256
259
  invalid: false,
@@ -65,7 +65,6 @@ export async function decompose(rid, prdMarkdown, projectRoot, opts = {}) {
65
65
  const wantFile = granularity === 'file' || granularity === 'both' || granularity === 'auto';
66
66
  const passes = [];
67
67
  let codegraph = zeroCodegraph();
68
- let understandAnything = zeroUnderstand();
69
68
  let pass1WorkUnits = [];
70
69
  if (wantService) {
71
70
  const result1 = await decomposeSlices(rid, prdMarkdown, projectRoot, opts);
@@ -77,7 +76,6 @@ export async function decompose(rid, prdMarkdown, projectRoot, opts = {}) {
77
76
  internalEdges: v1EdgesToV2(result1.dependencyDAG.edges)
78
77
  });
79
78
  codegraph = result1.codegraph;
80
- understandAnything = result1.understandAnything;
81
79
  }
82
80
  if (wantFile) {
83
81
  if (pass1WorkUnits.length > 0) {
@@ -115,7 +113,6 @@ export async function decompose(rid, prdMarkdown, projectRoot, opts = {}) {
115
113
  internalEdges: v1EdgesToV2(result.dependencyDAG.edges)
116
114
  });
117
115
  codegraph = result.codegraph;
118
- understandAnything = result.understandAnything;
119
116
  }
120
117
  }
121
118
  let crossPassEdges = [];
@@ -136,7 +133,6 @@ export async function decompose(rid, prdMarkdown, projectRoot, opts = {}) {
136
133
  crossPassEdges,
137
134
  llmArbitrations,
138
135
  codegraph,
139
- understandAnything,
140
136
  partial: false
141
137
  };
142
138
  }
@@ -214,12 +210,3 @@ function zeroCodegraph() {
214
210
  note: 'no decomposition run'
215
211
  };
216
212
  }
217
- function zeroUnderstand() {
218
- return {
219
- kgNodes: 0,
220
- kgEdges: 0,
221
- available: false,
222
- fallback: 'structural-only',
223
- note: 'no decomposition run'
224
- };
225
- }
@@ -4,5 +4,5 @@
4
4
  * the 800 LOC cap (mechanical verbatim move). `buildDependencyEdges` is
5
5
  * the only exported entry point; the rest are internal helpers.
6
6
  */
7
- import type { DependencyEdge, ImportEdge, KnowledgeGraph, WorkUnit } from './slice-decompose-types.js';
8
- export declare function buildDependencyEdges(wus: readonly WorkUnit[], importEdges: readonly ImportEdge[], kg: KnowledgeGraph | null, projectRoot: string): DependencyEdge[];
7
+ import type { DependencyEdge, ImportEdge, WorkUnit } from './slice-decompose-types.js';
8
+ export declare function buildDependencyEdges(wus: readonly WorkUnit[], importEdges: readonly ImportEdge[], projectRoot: string): DependencyEdge[];
@@ -55,38 +55,10 @@ function collectImportEdges(importEdges, fileToWu, projectRoot, collector) {
55
55
  pushIfNew(collector, edge);
56
56
  }
57
57
  }
58
- function collectSemanticEdges(kg, fileToWu, collector) {
59
- for (const e of kg.edges) {
60
- if (e.type !== 'contains_flow' && e.type !== 'flow_step')
61
- continue;
62
- const fromNode = kg.nodes.find((n) => n.id === e.source);
63
- const toNode = kg.nodes.find((n) => n.id === e.target);
64
- if (!fromNode?.filePath || !toNode?.filePath)
65
- continue;
66
- const fromWu = fileToWu.get(fromNode.filePath);
67
- const toWu = fileToWu.get(toNode.filePath);
68
- if (!fromWu || !toWu || fromWu === toWu)
69
- continue;
70
- const weight = e.type === 'flow_step' ? 0.05 : 0.1;
71
- const edge = {
72
- from: fromWu,
73
- to: toWu,
74
- kind: e.type,
75
- weight,
76
- evidence: `understand-anything: ${e.type} ${e.source}->${e.target}`,
77
- isSemantic: true,
78
- confidence: 'semantic'
79
- };
80
- pushIfNew(collector, edge);
81
- }
82
- }
83
- export function buildDependencyEdges(wus, importEdges, kg, projectRoot) {
58
+ export function buildDependencyEdges(wus, importEdges, projectRoot) {
84
59
  const fileToWu = indexFilesToWorkUnits(wus);
85
60
  const collector = { edges: [], seen: new Set() };
86
61
  collectImportEdges(importEdges, fileToWu, projectRoot, collector);
87
- if (kg !== null) {
88
- collectSemanticEdges(kg, fileToWu, collector);
89
- }
90
62
  return collector.edges;
91
63
  }
92
64
  function resolveRelativeImport(projectRoot, sourceFile, evidence) {
@@ -7,17 +7,15 @@
7
7
  * does not inject fakes via `DecomposeOptions`. The 6-stage pure
8
8
  * algorithm itself lives in `slice-decompose-service.ts`.
9
9
  *
10
- * Public surface (3 exported factories):
10
+ * Public surface (2 exported factories):
11
11
  *
12
12
  * defaultCodegraphRunner() -- spawns `npx codegraph <cmd>`
13
- * defaultUnderstandRunner() -- reads .understand-anything/knowledge-graph.json
14
13
  * defaultImportEdgeRunner() -- reads source files for import statements
15
14
  *
16
15
  * v2.18.3 file-split: this module is the extracted sub-tree of the
17
16
  * pre-split `slice-decompose-service.ts`. Function signatures are
18
17
  * unchanged (verbatim move).
19
18
  */
20
- import type { CodegraphRunner, ImportEdgeRunner, UnderstandRunner } from './slice-decompose-types.js';
19
+ import type { CodegraphRunner, ImportEdgeRunner } from './slice-decompose-types.js';
21
20
  export declare function defaultCodegraphRunner(): CodegraphRunner;
22
- export declare function defaultUnderstandRunner(): UnderstandRunner;
23
21
  export declare function defaultImportEdgeRunner(): ImportEdgeRunner;
@@ -7,10 +7,9 @@
7
7
  * does not inject fakes via `DecomposeOptions`. The 6-stage pure
8
8
  * algorithm itself lives in `slice-decompose-service.ts`.
9
9
  *
10
- * Public surface (3 exported factories):
10
+ * Public surface (2 exported factories):
11
11
  *
12
12
  * defaultCodegraphRunner() -- spawns `npx codegraph <cmd>`
13
- * defaultUnderstandRunner() -- reads .understand-anything/knowledge-graph.json
14
13
  * defaultImportEdgeRunner() -- reads source files for import statements
15
14
  *
16
15
  * v2.18.3 file-split: this module is the extracted sub-tree of the
@@ -121,27 +120,6 @@ function runCodegraph(args, projectRoot) {
121
120
  throw error;
122
121
  }
123
122
  }
124
- export function defaultUnderstandRunner() {
125
- return {
126
- async read(projectRoot) {
127
- const kgPath = join(projectRoot, '.understand-anything', 'knowledge-graph.json');
128
- if (!existsSync(kgPath))
129
- return null;
130
- try {
131
- const raw = readFileSync(kgPath, 'utf8');
132
- const parsed = JSON.parse(raw);
133
- return {
134
- nodes: parsed.nodes ?? [],
135
- edges: parsed.edges ?? [],
136
- layers: parsed.layers ?? []
137
- };
138
- }
139
- catch { // TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
140
- return null;
141
- }
142
- }
143
- };
144
- }
145
123
  export function defaultImportEdgeRunner() {
146
124
  return {
147
125
  async importsOf(projectRoot, files) {
@@ -12,13 +12,12 @@
12
12
  * Default runners (CLI-mode, real shell-outs):
13
13
  *
14
14
  * defaultCodegraphRunner() -- spawns `npx codegraph <cmd>`
15
- * defaultUnderstandRunner() -- reads .understand-anything/knowledge-graph.json
16
15
  * defaultImportEdgeRunner() -- reads source files for import statements
17
16
  *
18
- * Tests inject fakes via the `codegraphRunner`, `understandRunner`, and
19
- * `importEdgeRunner` fields of `DecomposeOptions`.
17
+ * Tests inject fakes via the `codegraphRunner` and `importEdgeRunner`
18
+ * fields of `DecomposeOptions`.
20
19
  */
21
20
  import type { DecomposeOptions, DecompositionResult } from './slice-decompose-types.js';
22
21
  export type { DecomposeOptions };
23
22
  export declare function decomposeSlices(rid: string, prdMarkdown: string, projectRoot: string, options?: DecomposeOptions): Promise<DecompositionResult>;
24
- export { defaultCodegraphRunner, defaultUnderstandRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';
23
+ export { defaultCodegraphRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';
@@ -12,11 +12,10 @@
12
12
  * Default runners (CLI-mode, real shell-outs):
13
13
  *
14
14
  * defaultCodegraphRunner() -- spawns `npx codegraph <cmd>`
15
- * defaultUnderstandRunner() -- reads .understand-anything/knowledge-graph.json
16
15
  * defaultImportEdgeRunner() -- reads source files for import statements
17
16
  *
18
- * Tests inject fakes via the `codegraphRunner`, `understandRunner`, and
19
- * `importEdgeRunner` fields of `DecomposeOptions`.
17
+ * Tests inject fakes via the `codegraphRunner` and `importEdgeRunner`
18
+ * fields of `DecomposeOptions`.
20
19
  */
21
20
  import { basename } from 'node:path';
22
21
  import { calibrate } from './calibration-store.js';
@@ -48,8 +47,6 @@ function createInitialState(rid, prdMarkdown, projectRoot, runners) {
48
47
  cgStatus: null,
49
48
  workUnits: [],
50
49
  depEdges: [],
51
- kg: null,
52
- understandAvailable: false,
53
50
  codegraphAffectedCrossFile: false,
54
51
  scc: null,
55
52
  criticalPath: null,
@@ -84,7 +81,6 @@ async function runStage(state, stage) {
84
81
  function resolveRunners(options) {
85
82
  return {
86
83
  cg: options.codegraphRunner ?? defaultCodegraphRunner(),
87
- ur: options.understandRunner ?? defaultUnderstandRunner(),
88
84
  ier: options.importEdgeRunner ?? defaultImportEdgeRunner()
89
85
  };
90
86
  }
@@ -172,15 +168,13 @@ function matchAcToHit(ac, hits) {
172
168
  // Stage 2: dependency DAG
173
169
  // =====================================================================
174
170
  async function buildDepDagStage(state) {
175
- const kg = await state.runners.ur.read(state.projectRoot);
176
- const understandAvailable = kg !== null;
177
171
  const fileSet = await collectFileSet(state.workUnits, state.runners.ier, state.projectRoot);
178
172
  const allFiles = Array.from(fileSet);
179
173
  const codegraphAffectedCrossFile = await probeCrossFileAffected(allFiles, state.runners.cg, state.projectRoot);
180
174
  const workUnits = applyImplicitWuFallback(state.workUnits, allFiles);
181
175
  const importEdges = await state.runners.ier.importsOf(state.projectRoot, allFiles);
182
- const depEdges = buildDependencyEdges(workUnits, importEdges, kg, state.projectRoot);
183
- return { ...state, kg, understandAvailable, codegraphAffectedCrossFile, workUnits, depEdges };
176
+ const depEdges = buildDependencyEdges(workUnits, importEdges, state.projectRoot);
177
+ return { ...state, codegraphAffectedCrossFile, workUnits, depEdges };
184
178
  }
185
179
  async function collectFileSet(workUnits, ier, projectRoot) {
186
180
  const explicitFiles = workUnits.flatMap((w) => w.files);
@@ -362,10 +356,10 @@ function backtrackPath(endNode, prev) {
362
356
  function minCutStage(state) {
363
357
  if (state.criticalPath === null)
364
358
  return state;
365
- const minCut = findMinCut(state.workUnits, state.depEdges, state.criticalPath, state.kg);
359
+ const minCut = findMinCut(state.workUnits, state.depEdges, state.criticalPath);
366
360
  return { ...state, minCut };
367
361
  }
368
- function findMinCut(_wus, edges, criticalPath, _kg) {
362
+ function findMinCut(_wus, edges, criticalPath) {
369
363
  const cpSet = new Set(criticalPath.nodes);
370
364
  const nonCpEdges = edges.filter((e) => !cpSet.has(e.from) || !cpSet.has(e.to));
371
365
  const sorted = [...nonCpEdges].sort((a, b) => a.weight - b.weight);
@@ -405,7 +399,7 @@ function partitionEstimateEmitStage(state) {
405
399
  ...b,
406
400
  slices: b.slices.map((s) => ({
407
401
  ...s,
408
- estimate: estimateSlice(s, state.kg)
402
+ estimate: estimateSlice(s)
409
403
  }))
410
404
  }));
411
405
  const result = buildDecompositionResult(state, batchesWithEstimates);
@@ -416,12 +410,10 @@ function buildDecompositionResult(state, batchesWithEstimates) {
416
410
  const totalSlices = batchesWithEstimates.reduce((sum, b) => sum + b.slices.length, 0);
417
411
  const pickHint = buildPickHint(totalSlices);
418
412
  const codegraphEnvelope = buildCodegraphEnvelope(state);
419
- const understandEnvelope = buildUnderstandEnvelope(state);
420
413
  return {
421
414
  rid: state.rid,
422
415
  generatedAt: new Date().toISOString(),
423
416
  codegraph: codegraphEnvelope,
424
- understandAnything: understandEnvelope,
425
417
  workUnits: state.workUnits,
426
418
  dependencyDAG: { edges: state.depEdges },
427
419
  sccAnalysis: state.scc,
@@ -460,18 +452,7 @@ function buildCodegraphEnvelope(state) {
460
452
  : 'codegraph.affected returned 0 cross-file dependents (v0.7.10 limitation); used real import edges'
461
453
  };
462
454
  }
463
- function buildUnderstandEnvelope(state) {
464
- return {
465
- kgNodes: state.kg?.nodes.length ?? 0,
466
- kgEdges: state.kg?.edges.length ?? 0,
467
- available: state.understandAvailable,
468
- fallback: state.understandAvailable ? 'semantic' : 'structural-only',
469
- note: state.understandAvailable
470
- ? 'read from .understand-anything/knowledge-graph.json'
471
- : '.understand-anything/knowledge-graph.json not found; algorithm falls back to structural cuts'
472
- };
473
- }
474
- function estimateSlice(slice, _kg) {
455
+ function estimateSlice(slice) {
475
456
  const sampleSize = 0;
476
457
  const complexitySum = 0;
477
458
  return calibrate(complexitySum, slice.estimate.testCount, slice.estimate.locSum, sampleSize);
@@ -569,5 +550,5 @@ function wuToSlice(wu) {
569
550
  // `slice-decompose-runners.ts` module — see v2.18.3 file-split for
570
551
  // the rationale. Function signatures and behaviour are unchanged
571
552
  // (verbatim move).
572
- import { defaultCodegraphRunner, defaultUnderstandRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';
573
- export { defaultCodegraphRunner, defaultUnderstandRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';
553
+ import { defaultCodegraphRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';
554
+ export { defaultCodegraphRunner, defaultImportEdgeRunner } from './slice-decompose-runners.js';