peaks-loop 4.0.51 → 4.0.52

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 (61) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README-en.md +1 -1
  3. package/README.md +1 -1
  4. package/dist/cli/commands/baseline-commands.js +11 -1
  5. package/dist/cli/commands/codegraph-command-runtime.d.ts +28 -0
  6. package/dist/cli/commands/codegraph-command-runtime.js +72 -0
  7. package/dist/cli/commands/codegraph-commands.d.ts +2 -11
  8. package/dist/cli/commands/codegraph-commands.js +173 -228
  9. package/dist/cli/commands/codegraph-status-command.d.ts +22 -0
  10. package/dist/cli/commands/codegraph-status-command.js +299 -0
  11. package/dist/cli/commands/core/memory-command.js +6 -2
  12. package/dist/cli/commands/job-commands.js +121 -30
  13. package/dist/cli/commands/project-commands.js +13 -3
  14. package/dist/cli/commands/request-commands.js +19 -8
  15. package/dist/cli/commands/slice-commands.js +2 -2
  16. package/dist/services/artifacts/artifact-prerequisites.js +23 -1
  17. package/dist/services/codegraph/codegraph-autorefresh.d.ts +16 -0
  18. package/dist/services/codegraph/codegraph-autorefresh.js +51 -5
  19. package/dist/services/codegraph/codegraph-config-repair-writer.d.ts +88 -0
  20. package/dist/services/codegraph/codegraph-config-repair-writer.js +322 -0
  21. package/dist/services/codegraph/codegraph-exclude-integrity.d.ts +20 -2
  22. package/dist/services/codegraph/codegraph-exclude-integrity.js +24 -3
  23. package/dist/services/codegraph/codegraph-exclude-reconciler.d.ts +23 -2
  24. package/dist/services/codegraph/codegraph-exclude-reconciler.js +123 -12
  25. package/dist/services/codegraph/codegraph-exclude-repair.d.ts +109 -55
  26. package/dist/services/codegraph/codegraph-exclude-repair.js +249 -195
  27. package/dist/services/codegraph/codegraph-include-reconciler.d.ts +10 -0
  28. package/dist/services/codegraph/codegraph-include-reconciler.js +160 -0
  29. package/dist/services/codegraph/codegraph-index-integrity.d.ts +268 -0
  30. package/dist/services/codegraph/codegraph-index-integrity.js +471 -0
  31. package/dist/services/codegraph/codegraph-service.d.ts +54 -0
  32. package/dist/services/codegraph/codegraph-service.js +84 -1
  33. package/dist/services/doctor/doctor-service/checks/codegraph-exclude-integrity.js +19 -4
  34. package/dist/services/doctor/doctor-service/checks/codegraph-index-integrity.d.ts +54 -0
  35. package/dist/services/doctor/doctor-service/checks/codegraph-index-integrity.js +151 -0
  36. package/dist/services/doctor/doctor-service/checks/l3-orphan-sessions.js +10 -10
  37. package/dist/services/doctor/doctor-service/plugin-registry.js +2 -0
  38. package/dist/services/doctor/doctor-service/types.d.ts +25 -0
  39. package/dist/services/memory/project-memory-service/index/kind-dispatch.js +48 -13
  40. package/dist/services/memory/project-memory-service/index.d.ts +5 -3
  41. package/dist/services/memory/project-memory-service/index.js +2 -2
  42. package/dist/services/memory/project-memory-service/parsers/frontmatter.d.ts +15 -1
  43. package/dist/services/memory/project-memory-service/parsers/frontmatter.js +34 -6
  44. package/dist/services/memory/project-memory-service/parsers/markdown-pure.d.ts +27 -1
  45. package/dist/services/memory/project-memory-service/parsers/markdown-pure.js +92 -7
  46. package/dist/services/memory/project-memory-service/types.d.ts +86 -0
  47. package/dist/services/slice/slice-check-types.d.ts +1 -1
  48. package/dist/services/workspace/runtime-layout.d.ts +91 -0
  49. package/dist/services/workspace/runtime-layout.js +148 -0
  50. package/dist/services/workspace/workspace-claude-settings-materializer.js +14 -0
  51. package/package.json +6 -6
  52. package/scripts/clean-dist.mjs +15 -3
  53. package/scripts/sync-version.mjs +26 -4
  54. package/skills/bee/peaks-prd/SKILL.md +1 -1
  55. package/skills/bee/peaks-qa/references/qa-skill-presence.md +1 -1
  56. package/skills/bee/peaks-rd/references/skill-presence-and-title.md +1 -1
  57. package/skills/bee/peaks-sc/SKILL.md +1 -1
  58. package/skills/bee/peaks-txt/SKILL.md +3 -3
  59. package/skills/peaks-code/SKILL.md +1 -1
  60. package/skills/peaks-code/references/project-memory-loading.md +19 -1
  61. package/skills/peaks-code/references/step-11-memory-sediment.md +1 -1
@@ -0,0 +1,160 @@
1
+ // src/services/codegraph/codegraph-include-reconciler.ts
2
+ //
3
+ // Slice-002 of `2026-09-16-codegraph-index-integrity` — the INCLUDE axis
4
+ // of the config repair. It answers one question:
5
+ //
6
+ // "Which extensions does upstream's extractor support but upstream's own
7
+ // default `include` template never names, and which of those does THIS
8
+ // project's `include` still not admit?"
9
+ //
10
+ // Why this exists (the real defect, measured): upstream
11
+ // `@colbymchenry/codegraph` decides what to parse from its own
12
+ // `EXTENSION_MAP` (37 extensions in 0.7.10), but `init` writes a 32-entry
13
+ // `DEFAULT_CONFIG.include` template that names only 32 of them. Five
14
+ // supported extensions are therefore absent from every fresh config:
15
+ // `.mjs`, `.cjs`, `.pyw`, `.hxx`, `.rake`. Upstream's `mergeConfig` has no
16
+ // separate override channel — `config.json`'s `include` replaces the
17
+ // defaults wholesale — so a fresh clone indexes none of them while
18
+ // `peaks codegraph status` still prints `[OK] Index is up to date`. On this
19
+ // repo that was 31 tracked files (30 `.mjs` + 1 `.cjs`) absent from a
20
+ // 1220-row index. It is the same class of defect as upstream's default
21
+ // `exclude` template colliding with real source directories, which slice S2
22
+ // of `2026-09-12-codegraph-exclude-integrity` already self-heals at the
23
+ // `init` seam; the include axis was simply never reconciled.
24
+ //
25
+ // Genericity (binding — mirrors the exclude reconciler): no hardcoded
26
+ // extension list, no hardcoded rule names, no project-specific paths. The
27
+ // candidate set is COMPUTED from upstream's own two tables (`EXTENSION_MAP`
28
+ // in `dist/extraction/grammars.js`, `DEFAULT_CONFIG` in `dist/types.js`),
29
+ // and every candidate is confirmed against upstream's own decision pair
30
+ // (`isLanguageSupported(detectLanguage(...))` — the same two functions
31
+ // `extraction/index.js` calls). Upstream can add an extension tomorrow and
32
+ // this module picks it up with no edit here; the "five" above is a
33
+ // measurement, not a constant in the code.
34
+ //
35
+ // Additive, never clobbering: a project's `include` is append-only from
36
+ // here. No user entry is removed, reordered or rewritten, and an extension
37
+ // any existing entry already admits is left alone. Append-only is the same
38
+ // posture `codegraph-exclude-repair.ts` takes toward a third-party config
39
+ // file it edits.
40
+ //
41
+ // Scope: PURE (`normalizeCodegraphInclude`) plus ONE read-only adapter
42
+ // (`upstreamIncludeCandidateExtensions`, which reads the installed upstream
43
+ // package). Nothing in this module writes a file.
44
+ //
45
+ // NOTE FOR FUTURE EDITORS: glob literals contain the two-character
46
+ // sequence that ends a block comment, so every comment in this file uses
47
+ // `//` lines — INCLUDING the exported API documentation, which is why this
48
+ // file has no `/** ... */` blocks. Do not convert them.
49
+ import { createRequire } from 'node:module';
50
+ import { dirname, extname, join } from 'node:path';
51
+ import { compileCodegraphGlobs } from './codegraph-exclude-reconciler.js';
52
+ // ─────────────────────────────────────────────────────────────────────
53
+ // Which extensions does this project's `include` already admit?
54
+ // ─────────────────────────────────────────────────────────────────────
55
+ // The pattern upstream's own template uses for a bare extension: all 32
56
+ // entries of `DEFAULT_CONFIG.include` have exactly this shape, and they are
57
+ // matched with `picomatch(..., { dot: true })` — the same engine, and the
58
+ // same options, that `matchesCodegraphGlob` delegates to. So an appended
59
+ // pattern is indistinguishable in form from an upstream-authored one.
60
+ function includePatternForExtension(extension) {
61
+ return `**/*${extension}`;
62
+ }
63
+ // A synthetic path used ONLY to ask "does any existing rule admit a file
64
+ // with this extension". A root-level probe answers that question exactly
65
+ // for every pattern shape upstream itself writes, because `picomatch`'s
66
+ // trailing-slash-star-star prefix matches zero path segments (measured:
67
+ // the `.mjs` pattern matches both `probe.mjs` and `a/b/probe.mjs`).
68
+ //
69
+ // KNOWN PROXY LIMIT, stated rather than hidden: a path-narrowed rule such as
70
+ // a `src`-prefixed brace list of js/mjs does NOT match the root-level probe,
71
+ // so an extension admitted only under a subdirectory is treated as
72
+ // uncovered and the bare extension pattern is appended. That errs ADDITIVE —
73
+ // the index admits more tracked files, never fewer — and it is pinned by a
74
+ // test rather than left to be discovered. A false "already covered" cannot
75
+ // occur for any pattern upstream's template can produce, and if it did its
76
+ // only effect would be to leave the gap the inspector already reports.
77
+ function extensionProbePath(extension) {
78
+ return `codegraph-include-probe${extension}`;
79
+ }
80
+ // Compiled ONCE per rule, never per (candidate x rule) pair — see
81
+ // `compileCodegraphGlobs`. The `matchers` list is the include list the
82
+ // candidate is tested against: the caller's entries first, then the
83
+ // patterns this same pass has already decided to append, so a duplicate
84
+ // candidate cannot append twice without re-parsing the list each time
85
+ // (perf audit S10: the re-parse was 0.25 / 2.15 / 23.4 / 234.4 ms at
86
+ // 32 / 320 / 3,200 / 32,000 rules, plus a spread array per candidate).
87
+ function isExtensionAdmitted(extension, matchers) {
88
+ const probe = extensionProbePath(extension);
89
+ return matchers.some((matcher) => matcher.matchesAny(probe));
90
+ }
91
+ // Pure: given the current `include` list and the extensions upstream
92
+ // supports but its own template omits, return the list with the uncovered
93
+ // ones appended. No fs, no clock, no serialization.
94
+ //
95
+ // The result is always a SUPERSET of the input, in the input's order, so a
96
+ // caller can never remove or reorder a user entry. Appending an extension
97
+ // the list already admits is a no-op, which is what makes the whole
98
+ // normalization idempotent: feeding the repaired list back in yields
99
+ // `changed: false`.
100
+ //
101
+ // Candidates are de-duplicated by their EFFECT, not by string equality:
102
+ // each candidate is tested against the input list PLUS the patterns this
103
+ // call has already appended, so a duplicate candidate cannot append twice.
104
+ export function normalizeCodegraphInclude(input) {
105
+ const addedPatterns = [];
106
+ // The include list as this pass sees it, compiled once. Appending a
107
+ // pattern extends the list by ONE compiled rule instead of re-parsing
108
+ // every entry on the next candidate (see `isExtensionAdmitted`).
109
+ const matchers = [compileCodegraphGlobs(input.include)];
110
+ for (const candidate of input.candidateExtensions) {
111
+ const extension = candidate.startsWith('.') ? candidate : `.${candidate}`;
112
+ if (isExtensionAdmitted(extension, matchers)) {
113
+ continue;
114
+ }
115
+ const pattern = includePatternForExtension(extension);
116
+ addedPatterns.push(pattern);
117
+ matchers.push(compileCodegraphGlobs([pattern]));
118
+ }
119
+ if (addedPatterns.length === 0) {
120
+ return { changed: false, include: input.include, addedPatterns: [] };
121
+ }
122
+ return {
123
+ changed: true,
124
+ include: [...input.include, ...addedPatterns],
125
+ addedPatterns
126
+ };
127
+ }
128
+ let cachedCandidateExtensions = null;
129
+ // The extensions upstream's extractor supports but its own default
130
+ // `include` template never names, as dotted extensions — measured against
131
+ // the installed `@colbymchenry/codegraph` 0.7.10 as `.mjs`, `.cjs`,
132
+ // `.pyw`, `.hxx`, `.rake`, in that order.
133
+ //
134
+ // Derived entirely from upstream's own data:
135
+ //
136
+ // 1. `EXTENSION_MAP` keys are the extension universe the extractor knows.
137
+ // 2. The extensions upstream's template already names are read off
138
+ // `DEFAULT_CONFIG.include` — the entry's own extension, so the
139
+ // comparison is extension-to-extension and cannot be confused by a
140
+ // template that switches glob syntax.
141
+ // 3. A candidate is kept only when upstream's own support decision
142
+ // accepts it, so a table entry with no grammar behind it is never
143
+ // repaired into the config.
144
+ //
145
+ // Returns the same array on every call (module-level cache); the two
146
+ // modules only define tables and functions, so the load is cheap and
147
+ // Node's `require` cache makes later calls free.
148
+ export function upstreamUnnamedIncludeExtensions() {
149
+ if (cachedCandidateExtensions === null) {
150
+ const require = createRequire(import.meta.url);
151
+ const packageJsonPath = require.resolve('@colbymchenry/codegraph/package.json');
152
+ const distDir = join(dirname(packageJsonPath), 'dist');
153
+ const types = require(join(distDir, 'types.js'));
154
+ const grammars = require(join(distDir, 'extraction', 'grammars.js'));
155
+ const namedByTemplate = new Set(types.DEFAULT_CONFIG.include.map((entry) => extname(entry).toLowerCase()));
156
+ cachedCandidateExtensions = Object.keys(grammars.EXTENSION_MAP).filter((extension) => !namedByTemplate.has(extension.toLowerCase()) &&
157
+ grammars.isLanguageSupported(grammars.detectLanguage(`probe${extension}`)));
158
+ }
159
+ return cachedCandidateExtensions;
160
+ }
@@ -0,0 +1,268 @@
1
+ import { type ReadCodegraphExcludeConfig, type ReadTrackedFiles } from './codegraph-exclude-reconciler.js';
2
+ /**
3
+ * Exit code `peaks codegraph status` uses when the index itself is
4
+ * incomplete or stale — distinct from `CODEGRAPH_INTEGRITY_EXIT_CODE` (74,
5
+ * the exclude-rule gate) and from `CODEGRAPH_INIT_CONFLICT_EXIT_CODE` (73).
6
+ *
7
+ * Why distinct rather than reusing 74: the two gates have different
8
+ * REMEDIATIONS. 74 means "these `exclude` rules must be dropped", and a CI
9
+ * job keyed on 74 already knows to run `repair-exclude`. 75 means "the
10
+ * index content does not match the repository — a supported tracked file
11
+ * is missing from it, or it holds rows for files that are gone". Folding
12
+ * that into 74 would silently re-point an existing consumer at a different
13
+ * fix. When BOTH gates fire, 74 wins (the exclude gap is the upstream
14
+ * cause; repairing it and rebuilding also clears staleness).
15
+ *
16
+ * NOTE (2026-09-16 policy change): 75 is only reachable in STRICT mode.
17
+ * See `isCodegraphIndexStrictMode`.
18
+ */
19
+ export declare const CODEGRAPH_INDEX_INTEGRITY_EXIT_CODE = 75;
20
+ /**
21
+ * Exit code for "the index axis could not be measured at all" — the db is
22
+ * present but unreadable, or its schema no longer has the `files` table
23
+ * (an upstream bump), or `git ls-files` / the config read failed.
24
+ *
25
+ * Distinct from BOTH 0 and 75 on purpose, and it applies in every mode
26
+ * including the advisory default:
27
+ *
28
+ * - 0 would say "I checked and it is fine". It does not.
29
+ * - 75 would say "I checked and the index does not cover the
30
+ * repository", which asserts a measurement that never happened.
31
+ *
32
+ * Why it is not merely advisory (the user's option C covers `gap`, not
33
+ * this): option C exists so that upgrading peaks-loop cannot turn a
34
+ * *healthy* project red — the three downstream triggers it names (a
35
+ * tracked `.mjs`, an un-purged dead row, a deliberately narrowed
36
+ * `include`) are all `gap`-class. "Could not read my own input" is never a
37
+ * healthy-project condition: it requires `.codegraph/codegraph.db` to be
38
+ * present but unreadable, and `.codegraph/` is gitignored, so a downstream
39
+ * CI checkout normally has no index at all and reports `not-applicable`
40
+ * (exit 0, no output). This is the exact failure class
41
+ * `codegraph-exclude-reconciler.ts:76-82` documents as the reason that
42
+ * module exists.
43
+ */
44
+ export declare const CODEGRAPH_INDEX_UNEVALUABLE_EXIT_CODE = 76;
45
+ /**
46
+ * The one command that repairs what this axis detects (slice-002). Exported
47
+ * as a constant rather than spelled out at each site so the human line, the
48
+ * doctor message and the JSON `nextActions` cannot name three different
49
+ * things: the renderer below, the doctor check and the CLI envelope all
50
+ * interpolate this value.
51
+ *
52
+ * It repairs BOTH axes in one run — `include` normalization, `exclude` rule
53
+ * drops against the normalized include, then a FORCED index rebuild (the
54
+ * only upstream path that drops rows for files deleted in an earlier
55
+ * commit; see `CodegraphExcludeRepairOptions.reindex`).
56
+ */
57
+ export declare const CODEGRAPH_REPAIR_INDEX_COMMAND = "peaks codegraph repair-index --project <root>";
58
+ /**
59
+ * Opt-in switch for the user's option C decision (advisory by default,
60
+ * blocking on request). Set `PEAKS_CODEGRAPH_INDEX_STRICT=1` (or `true`)
61
+ * to make a detected index gap block: `status` exits 75 and the doctor
62
+ * check loses its `severity: 'warning'` tag and flips the doctor exit code.
63
+ *
64
+ * Why an environment variable rather than a config key or a CLI flag:
65
+ *
66
+ * - ONE mechanism covers both consumers. `peaks codegraph status` and
67
+ * `peaks doctor` are separate command surfaces; a CLI flag would have
68
+ * to be threaded through the doctor's option plumbing as well, and the
69
+ * default doctor probe takes no arguments.
70
+ * - CI is where the need lives, and CI sets environment variables.
71
+ * - A config key would have to live in the gitignored
72
+ * `.codegraph/config.json` (upstream's file, which this slice must
73
+ * never write) — so it would not survive a clone and could not
74
+ * configure a CI job at all.
75
+ * - It writes no state, so it does not weaken the read-only contract.
76
+ *
77
+ * Discoverability: the advisory warning text names this variable
78
+ * verbatim, so an operator who wants blocking is told how to get it at
79
+ * the moment they see the finding.
80
+ */
81
+ export declare const CODEGRAPH_INDEX_STRICT_ENV_VAR = "PEAKS_CODEGRAPH_INDEX_STRICT";
82
+ /** True when the project opted in to blocking index-gap verdicts. */
83
+ export declare function isCodegraphIndexStrictMode(env?: Readonly<Record<string, string | undefined>>): boolean;
84
+ /**
85
+ * The four outcomes of the index axis, kept apart so that no consumer
86
+ * that CAN carry four outcomes collapses two:
87
+ *
88
+ * - `clean` — measured, nothing wrong.
89
+ * - `gap` — measured, the index does not cover the repository.
90
+ * - `not-evaluated` — the axis was attempted and FAILED (unreadable db,
91
+ * schema drift, no git work tree, malformed/missing
92
+ * config). The index is NOT known to be fine.
93
+ * - `not-applicable`— there is no index here at all (no `codegraph.db`):
94
+ * the pre-init / dangling state, which is not a defect.
95
+ *
96
+ * `not-evaluated` and `not-applicable` both used to be `null` in the
97
+ * machine envelope, which is how "I could not check" came to be reported
98
+ * identically to "there is nothing to check".
99
+ *
100
+ * SCOPE OF THE CLAIM (narrowed under R12-2 — the earlier wording, "no
101
+ * consumer can collapse two of them", was overbroad). This module keeps
102
+ * all four apart, and so do `peaks codegraph status`'s two channels (the
103
+ * `[FAIL]`/`[WARN]` tags and `indexIntegrityVerdict` + the exit codes 0 /
104
+ * 75 / 76). The DOCTOR does not: its check shape is `{ok, severity?}`
105
+ * (legacy `DoctorCheck`, kept back-compatible on purpose), so
106
+ * `not-evaluated` and an advisory `gap` are BOTH `ok:false,
107
+ * severity:'warning'` and are told apart by message text alone — see
108
+ * `doctor-service/checks/codegraph-index-integrity.ts`. That collapse is
109
+ * recorded, not fixed: neither state reads as `ok:true`, so the invariant
110
+ * this axis exists for ("could not evaluate" must never pass as "verified
111
+ * clean") still holds there, and in the advisory default neither state
112
+ * moves the doctor exit code — so no exit-code consumer is misled by it.
113
+ * Under `PEAKS_CODEGRAPH_INDEX_STRICT=1` the two ARE separated in the
114
+ * machine fields (`severity` survives on `not-evaluated`, is dropped from
115
+ * `gap`), which is pinned by a test.
116
+ */
117
+ export type CodegraphIndexIntegrityVerdict = 'clean' | 'gap' | 'not-evaluated' | 'not-applicable';
118
+ /**
119
+ * Fold the inspected report (null when there is no index to inspect) and
120
+ * the caught failure (null when nothing threw) into one verdict. This is
121
+ * the single place the four outcomes are distinguished, so a caller
122
+ * cannot re-derive them differently.
123
+ */
124
+ export declare function resolveCodegraphIndexIntegrityVerdict(report: CodegraphIndexIntegrityReport | null, warning: string | null): CodegraphIndexIntegrityVerdict;
125
+ /**
126
+ * The exit code the index axis contributes, or `null` when it
127
+ * contributes none (clean / not-applicable → the caller's exit code is
128
+ * left alone).
129
+ */
130
+ export declare function codegraphIndexIntegrityExitCode(verdict: CodegraphIndexIntegrityVerdict, strict: boolean): number | null;
131
+ export type CodegraphIndexIntegrityReport = {
132
+ /** Absolute path of the inspected `.codegraph/config.json`. */
133
+ readonly configPath: string;
134
+ /** Absolute path of the inspected index database. */
135
+ readonly databasePath: string;
136
+ /** True when either axis is non-empty. `[OK]` must not be printed then. */
137
+ readonly gap: boolean;
138
+ /** Git-tracked files upstream's extractor would ingest (any extension). */
139
+ readonly trackedSourceCount: number;
140
+ /** Of those, the ones the config's `include` globs admit. */
141
+ readonly admittedTrackedCount: number;
142
+ /** Class ① — supported tracked files `include` does not admit. */
143
+ readonly includeGap: readonly string[];
144
+ /** Rows in the index's `files` table. */
145
+ readonly indexedFileCount: number;
146
+ /** Class ② — index rows whose path no longer exists on disk. */
147
+ readonly deadRows: readonly string[];
148
+ };
149
+ /**
150
+ * Everything `inspectCodegraphIndexIntegrityFrom` needs, already resolved.
151
+ * Pure input: no fs, no spawn, no clock — the adapters below supply it.
152
+ */
153
+ export type CodegraphIndexIntegrityInput = {
154
+ readonly configPath: string;
155
+ readonly databasePath: string;
156
+ readonly trackedFiles: readonly string[];
157
+ readonly include: readonly string[];
158
+ /** Project-relative paths carried by the index's `files` table. */
159
+ readonly indexedPaths: readonly string[];
160
+ /** True when upstream's extractor supports `filePath`'s language. */
161
+ readonly supportsPath: (filePath: string) => boolean;
162
+ /** True when a project-relative index path still exists on disk. */
163
+ readonly pathExists: (projectRelativePath: string) => boolean;
164
+ };
165
+ /**
166
+ * Pure fold over already-resolved data. Both axes are set differences, so
167
+ * neither can be satisfied by a self-consistency assertion: axis ① compares
168
+ * git's tracked set against the `include` matcher, axis ② compares the
169
+ * index's own rows against the filesystem.
170
+ */
171
+ export declare function inspectCodegraphIndexIntegrityFrom(input: CodegraphIndexIntegrityInput): CodegraphIndexIntegrityReport;
172
+ /** The upstream decision, verbatim: detect the language, then ask if it has a grammar. */
173
+ export declare function upstreamSupportsPath(filePath: string): boolean;
174
+ /**
175
+ * Per-call, bounded replacement for the per-row `existsSync` above.
176
+ *
177
+ * WHY: the fold calls `pathExists` once per index row (`inspectCodegraph
178
+ * IndexIntegrityFrom`), so the gate is O(rows) full-path stats at ~13.5 µs
179
+ * each — 35 ms at 1.2k rows, 1,923 ms at 100x. It is unbounded in the size
180
+ * of the index. What is replaced is the COST, not the authority: a row is
181
+ * confirmed PRESENT by looking its basename up in one cached listing of its
182
+ * parent directory, so the number of filesystem calls is bounded by the
183
+ * number of DISTINCT DIRECTORIES the index names — which is bounded by the
184
+ * repository, not by the index.
185
+ *
186
+ * A listing may only answer `true`, and only for an entry whose dirent is
187
+ * positively a plain file or a plain directory. For exactly those entries,
188
+ * "the name is in `readdir`" and "`existsSync` on the joined path is true"
189
+ * cannot disagree. Everything else falls through to
190
+ * `codegraphIndexPathExists` — the old implementation, verbatim — so the
191
+ * classes this cache cannot decide are decided exactly as they always were:
192
+ *
193
+ * - a symlink or junction entry (`isSymbolicLink()`, Windows included:
194
+ * a junction reports `isDirectory() === false`), because a BROKEN link
195
+ * is listed by `readdir` and is absent from disk;
196
+ * - a case-differing path on a case-insensitive filesystem — the listing
197
+ * carries the on-disk spelling, so `SRC/OK.TS` misses and the stat
198
+ * decides (true on Windows, false on Linux, exactly as before);
199
+ * - a path naming a directory, or any non-file special entry;
200
+ * - a parent that is missing, unreadable, or not a directory at all
201
+ * (`readdir` throws → `null`, memoized so the failure costs one call);
202
+ * - a trailing-slash or empty row, and a project root that does not exist.
203
+ *
204
+ * The cache lives for ONE `inspectCodegraphIndexIntegrity` call, so a
205
+ * second command re-reads the tree and cannot be served a stale listing.
206
+ * Within a call, a listing taken before a concurrent delete is the only
207
+ * divergence from the old code — both implementations race the filesystem,
208
+ * and neither holds a snapshot.
209
+ */
210
+ export declare function createCodegraphIndexPathExists(): (projectRoot: string, projectRelativePath: string) => boolean;
211
+ /**
212
+ * Injection seam for `inspectCodegraphIndexIntegrity`.
213
+ *
214
+ * `trackedFiles` / `config` are the ALREADY-READ shared inputs (perf audit
215
+ * F1) — the CLI reads them once and hands the same values to both codegraph
216
+ * axes, so the `git ls-files` spawn, the config read and the `include`
217
+ * glob compilation happen once per command instead of twice. They are
218
+ * values, not reader functions, because that is what the caller has: the
219
+ * read has already happened by the time either axis runs.
220
+ *
221
+ * Both are READ-MARKED (code review R4-1): only a value returned by the
222
+ * readers is admissible. An explicit `[]` — which the seam used to accept
223
+ * and which silently meant "nothing is tracked", erasing every include-gap
224
+ * — is now a compile error and a run-time throw. `undefined`/omitted still
225
+ * means "read it yourself", exactly as before.
226
+ *
227
+ * The three remaining fields are genuine per-call adapters, used by tests
228
+ * to drive the fold without touching a real db or the real oracle.
229
+ */
230
+ export type CodegraphIndexIntegrityDeps = {
231
+ readonly trackedFiles?: ReadTrackedFiles | undefined;
232
+ readonly config?: ReadCodegraphExcludeConfig | undefined;
233
+ readonly readIndexedPaths?: (projectRoot: string) => readonly string[];
234
+ readonly supportsPath?: (filePath: string) => boolean;
235
+ readonly pathExists?: (projectRoot: string, projectRelativePath: string) => boolean;
236
+ };
237
+ /**
238
+ * Read-only entry point: resolve git's tracked files, the config's
239
+ * `include` globs and the index's own rows from disk, then fold them into
240
+ * one report. Throws (never silently degrades) when the project is not a
241
+ * git work tree, the config is missing/malformed, or the index is absent —
242
+ * callers that must stay alive (`status`, doctor) catch and surface it.
243
+ */
244
+ export declare function inspectCodegraphIndexIntegrity(projectRoot: string, deps?: CodegraphIndexIntegrityDeps): CodegraphIndexIntegrityReport;
245
+ /**
246
+ * Human-readable detail lines for a gapped report, grouped by axis so an
247
+ * operator can tell which defect they have (and whether they have both).
248
+ *
249
+ * Returns an empty array for a clean report — the caller decides whether
250
+ * "clean" is worth printing at all.
251
+ *
252
+ * `blocking` is the user's option C switch, and it changes the TAG, not
253
+ * the finding: advisory (the default) prints `[WARN]` and the command
254
+ * exits 0; strict prints `[FAIL]` and the command exits 75. The verdict
255
+ * word is chosen here rather than by the caller so the two channels
256
+ * cannot disagree about the same report.
257
+ *
258
+ * The remediation sentence NAMES the real command (`peaks codegraph
259
+ * repair-index`). Slice-001 deliberately named none, because naming a
260
+ * command that does not exist yet reproduces the exact failure this gate
261
+ * exists to prevent (an operator following a hint into "command not
262
+ * found"). Slice-002 shipped that command, so the obligation recorded in
263
+ * slice-001's design decision 4 is discharged here — and the name is
264
+ * exported as a constant so the renderer, the doctor message and the
265
+ * error envelope cannot drift from the command that is actually
266
+ * registered.
267
+ */
268
+ export declare function renderCodegraphIndexIntegrityLines(report: CodegraphIndexIntegrityReport, blocking: boolean): readonly string[];