@cassiomc1/forgeloop 1.10.2 → 1.11.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.
Files changed (84) hide show
  1. package/.cursor/rules/project-loop.mdc +2 -2
  2. package/.forgeloop/forgeloop.gitignore +1 -0
  3. package/.github/copilot-instructions.md +2 -2
  4. package/AGENTS.md +1 -0
  5. package/AGENT_COMPATIBILITY.md +7 -0
  6. package/CLAUDE.md +1 -0
  7. package/DOCS_INDEX.md +10 -0
  8. package/LOOP_SYSTEM_DESIGN.md +12 -0
  9. package/ORCHESTRATOR_INTEGRATION.md +9 -0
  10. package/PROTOCOL_INTEGRATION.md +17 -0
  11. package/README.md +12 -10
  12. package/THIRD_PARTY_NOTICES.md +11 -0
  13. package/THREAT_MODEL.md +21 -0
  14. package/benchmarks/repository-index/README.md +73 -0
  15. package/benchmarks/repository-index/queries.json +12 -0
  16. package/benchmarks/repository-index/run-hot-path.mjs +142 -0
  17. package/benchmarks/repository-index/run-persistent-transport.mjs +169 -0
  18. package/completions/_forgeloop +7 -1
  19. package/completions/forgeloop.bash +13 -1
  20. package/completions/forgeloop.fish +40 -1
  21. package/docs/AGENT_PROTOCOL_SUMMARY.md +8 -1
  22. package/docs/CLI_REFERENCE.md +114 -2
  23. package/docs/DOCUMENTATION_GUIDE.md +10 -5
  24. package/docs/GETTING_STARTED.md +17 -0
  25. package/docs/MCP.md +16 -1
  26. package/docs/PACKAGE_CONTENTS.md +7 -1
  27. package/docs/PERSISTENT_SEARCH_TRANSPORT.md +289 -0
  28. package/docs/RECIPES.md +30 -0
  29. package/docs/RELEASE_CHECKLIST.md +34 -0
  30. package/docs/REPOSITORY_INDEX.md +553 -0
  31. package/docs/TROUBLESHOOTING.md +147 -0
  32. package/docs/UNIVERSAL_INTEGRATION.md +30 -0
  33. package/docs/diagrams/README.md +10 -0
  34. package/package.json +11 -2
  35. package/scripts/update-tgrep-manifest.mjs +86 -0
  36. package/scripts/verify-tgrep-manifest.mjs +17 -0
  37. package/src/cli.js +35 -0
  38. package/src/commands/doctor.js +76 -1
  39. package/src/commands/index-rebuild.js +1 -0
  40. package/src/commands/index-setup.js +1 -0
  41. package/src/commands/index-start.js +1 -0
  42. package/src/commands/index-status.js +1 -0
  43. package/src/commands/index-stop.js +1 -0
  44. package/src/commands/init.js +39 -1
  45. package/src/commands/repository-index.js +111 -0
  46. package/src/commands/search.js +1 -0
  47. package/src/commands/update.js +32 -4
  48. package/src/core/cli-command-definitions.js +97 -3
  49. package/src/core/command-executors.js +35 -2
  50. package/src/core/command-input.js +23 -0
  51. package/src/core/error-codes.js +195 -0
  52. package/src/core/filesystem.js +10 -1
  53. package/src/core/integration-invocation-policy.js +27 -0
  54. package/src/core/integration-resources.js +16 -1
  55. package/src/core/protocol-info.js +23 -0
  56. package/src/integration.d.ts +90 -0
  57. package/src/integration.js +21 -0
  58. package/src/persistent-transport/client.js +293 -0
  59. package/src/persistent-transport/constants.js +24 -0
  60. package/src/persistent-transport/errors.js +38 -0
  61. package/src/persistent-transport/framing.js +61 -0
  62. package/src/persistent-transport/lifecycle.js +116 -0
  63. package/src/persistent-transport/ownership.js +184 -0
  64. package/src/persistent-transport/paths.js +31 -0
  65. package/src/persistent-transport/protocol.js +95 -0
  66. package/src/persistent-transport/server.js +256 -0
  67. package/src/persistent-transport/state.js +49 -0
  68. package/src/repository-index/args.js +59 -0
  69. package/src/repository-index/binary-manager.js +413 -0
  70. package/src/repository-index/constants.js +45 -0
  71. package/src/repository-index/errors.js +38 -0
  72. package/src/repository-index/lifecycle.js +17 -0
  73. package/src/repository-index/lock.js +113 -0
  74. package/src/repository-index/manifest.js +132 -0
  75. package/src/repository-index/metrics.js +30 -0
  76. package/src/repository-index/normalize-json.js +187 -0
  77. package/src/repository-index/paths.js +39 -0
  78. package/src/repository-index/platform.js +20 -0
  79. package/src/repository-index/process.js +140 -0
  80. package/src/repository-index/readiness.js +62 -0
  81. package/src/repository-index/search.js +262 -0
  82. package/src/repository-index/server.js +432 -0
  83. package/src/repository-index/status.js +397 -0
  84. package/src/repository-index/tgrep-manifest.json +38 -0
@@ -0,0 +1,553 @@
1
+ # ForgeLoop Repository Index
2
+
3
+ ## Overview
4
+
5
+ ForgeLoop includes a mandatory, local Repository Index for repeatable
6
+ repository-wide textual discovery. The public contract is provider-neutral:
7
+ the CLI, Integration API, and MCP adapter all use the same normalized search
8
+ service. The initial implementation is a ForgeLoop-managed Microsoft `tgrep`
9
+ 1.0.3 engine.
10
+
11
+ Repository Search is an engineering aid. It locates source text quickly and
12
+ keeps up with working-tree changes, but it is not a task ledger, a dependency
13
+ graph, verification evidence, completion authority, or historical source of
14
+ truth.
15
+
16
+ The CLI-only persistent local transport is documented separately in
17
+ [`PERSISTENT_SEARCH_TRANSPORT.md`](./PERSISTENT_SEARCH_TRANSPORT.md). It is a
18
+ startup/reuse optimization over this service; the Integration API and MCP
19
+ adapter remain direct consumers.
20
+
21
+ ## Why Repository Index exists
22
+
23
+ Repeated full-tree scans are noisy and can be expensive on larger projects.
24
+ The index keeps a derived local cache and a live watcher so harnesses and
25
+ developers can search through one stable ForgeLoop boundary. Consumers do not
26
+ need to install or discover a host `grep`, `rg`, or `tgrep` executable.
27
+
28
+ ForgeLoop does not promise a universal speedup. Correctness, current-working-
29
+ tree visibility, bounded resource use, and deterministic failure are the
30
+ acceptance criteria. Benchmark results are workload- and platform-specific.
31
+
32
+ ## Mandatory status
33
+
34
+ For an actual Git repository, `init`, `doctor`, and `update` treat the
35
+ Repository Index as required operational readiness. A missing or unhealthy
36
+ engine is reported as unhealthy; it is never silently replaced by `rg`,
37
+ `grep`, or an unpinned `tgrep` on `PATH`.
38
+
39
+ The first setup may download a pinned release asset. Air-gapped environments
40
+ can preload the exact release archive with `--asset`; the archive is still
41
+ checked against the manifest SHA-256 value. A non-Git target can be used for
42
+ protocol fixtures and reports an explicit `DEFERRED` result from lifecycle
43
+ commands because there is no repository to index.
44
+
45
+ Index health does not alter task ownership, historical completion, contracts,
46
+ receipts, evidence, guides, or verification scope. A task that was previously
47
+ validated `COMPLETE` remains historically complete even if the current index
48
+ server is down.
49
+
50
+ ## Architecture
51
+
52
+ ```text
53
+ CLI `search` only
54
+ |
55
+ v
56
+ CLI persistent local IPC host
57
+ |
58
+ +-----------------------------+
59
+ v
60
+ Integration API / MCP ----> provider-neutral search service
61
+ |
62
+ v
63
+ managed tgrep executable and server
64
+ | |
65
+ v v
66
+ opaque project cache working-tree watcher
67
+ .forgeloop/.../tgrep current file mutations
68
+ ```
69
+
70
+ The user-level binary cache and project-level index are separate:
71
+
72
+ ```text
73
+ ~/.forgeloop/engines/tgrep/1.0.3/<platform>/tgrep
74
+ <repo>/.forgeloop/repository-index/tgrep/
75
+ <repo>/.forgeloop/repository-index/engine-state.json
76
+ ```
77
+
78
+ The native index files are opaque derived cache data. ForgeLoop communicates
79
+ with `tgrep` through its CLI and server behavior; it does not read or depend
80
+ on `index.bin`, `lookup.bin`, `files.bin`, or other native file formats.
81
+
82
+ ## Managed engine
83
+
84
+ The checked-in
85
+ [`tgrep-manifest.json`](../src/repository-index/tgrep-manifest.json) is the
86
+ distribution source of truth. It pins the upstream repository, semantic
87
+ version, release asset name, archive type, binary name, archive SHA-256
88
+ checksum, and extracted executable SHA-256 checksum. Managed installation
89
+ verifies the executable digest before it ever runs `tgrep --version`; a digest
90
+ mismatch is reported and explicit setup/repair safely replaces the quarantined
91
+ binary. The development override remains version-checked but is deliberately
92
+ non-canonical and is not covered by the release binary digest.
93
+ The manifest currently contains verified assets for:
94
+
95
+ | ForgeLoop key | Native platform | Archive |
96
+ | --- | --- | --- |
97
+ | `darwin-arm64` | macOS Apple Silicon | `tar.gz` |
98
+ | `darwin-x64` | macOS Intel | `tar.gz` |
99
+ | `linux-x64` | Linux Intel/AMD64 | `tar.gz` |
100
+ | `windows-x64` | Windows Intel/AMD64 | `zip` |
101
+
102
+ Unsupported platform/architecture combinations fail with
103
+ `E_REPOSITORY_INDEX_PLATFORM_UNSUPPORTED`; they never fall through to another
104
+ binary. Verify the manifest locally with:
105
+
106
+ ```bash
107
+ npm run repository-index:manifest
108
+ ```
109
+
110
+ The normal runtime never asks GitHub for `latest` and never searches `PATH`.
111
+ `FORGELOOP_TGREP_BINARY` is an explicit development/test override. It must be
112
+ an absolute path and still reports the pinned `tgrep 1.0.3` version. An
113
+ override is marked `managed: false` and is not a production provisioning
114
+ mechanism.
115
+
116
+ ## Initial setup
117
+
118
+ Inside a supported Git repository:
119
+
120
+ ```bash
121
+ forgeloop init
122
+ forgeloop doctor
123
+ forgeloop index-status --json
124
+ ```
125
+
126
+ `init` performs the existing ForgeLoop kit and policy initialization, then
127
+ provisions the managed engine when needed, explicitly builds the index, starts
128
+ the ForgeLoop-owned watcher, and verifies readiness. A valid binary and index
129
+ are reused on a second `init`; no duplicate server is started.
130
+
131
+ For explicit repair or a preloaded archive:
132
+
133
+ ```bash
134
+ forgeloop index-setup
135
+ forgeloop index-setup --asset /absolute/path/tgrep-v1.0.3-release.tar.gz
136
+ ```
137
+
138
+ The archive filename may differ from the manifest asset name, but its bytes
139
+ must match the archive and executable checksums for the current platform. Setup
140
+ downloads or reads into a temporary directory, validates the archive, rejects
141
+ unsafe entries, verifies the extracted executable digest before version
142
+ execution, and installs atomically.
143
+
144
+ ## Search CLI
145
+
146
+ The standard discovery command is:
147
+
148
+ ```bash
149
+ forgeloop search "ExecutionReceipt"
150
+ forgeloop search "validateCompletion" --glob "*.js"
151
+ forgeloop search "receipt" --type js --context 3
152
+ forgeloop search "E_RECEIPT_PATH_MISMATCH" --files-with-matches
153
+ ```
154
+
155
+ Supported first-release options are `--fixed-strings`, `--ignore-case`,
156
+ `--smart-case`, `--word`/`--word-regexp`, repeatable `--glob` and `--type`,
157
+ `--context`, `--before-context`, `--after-context`, `--max-count`,
158
+ `--files-with-matches`, `--stats`, and `--json`. Native flags are not exposed
159
+ through a generic pass-through option, and the normal API does not expose
160
+ `--no-index` or `--no-ignore`.
161
+
162
+ Default output is generated from normalized results:
163
+
164
+ ```text
165
+ src/core/completion.js:42:7: return validateCompletion(result);
166
+ ```
167
+
168
+ JSON output is provider-neutral and uses project-relative paths:
169
+
170
+ ```bash
171
+ forgeloop search "ExecutionReceipt" --json
172
+ ```
173
+
174
+ ```json
175
+ {
176
+ "schemaVersion": 1,
177
+ "query": {
178
+ "pattern": "ExecutionReceipt",
179
+ "globs": [],
180
+ "types": [],
181
+ "fixedStrings": false,
182
+ "ignoreCase": false,
183
+ "smartCase": false,
184
+ "wordRegexp": false,
185
+ "filesWithMatches": false,
186
+ "stats": false
187
+ },
188
+ "repositoryIndex": {
189
+ "engine": "tgrep",
190
+ "engineVersion": "1.0.3",
191
+ "indexed": true,
192
+ "server": true
193
+ },
194
+ "matches": [
195
+ {
196
+ "path": "src/core/completion.js",
197
+ "line": 42,
198
+ "column": 7,
199
+ "text": "return validateCompletion(result);",
200
+ "submatches": []
201
+ }
202
+ ],
203
+ "metrics": {
204
+ "queryDurationMs": 12,
205
+ "nativeDurationMs": 4,
206
+ "matchCount": 1,
207
+ "matchedFileCount": 1,
208
+ "engine": "tgrep",
209
+ "engineVersion": "1.0.3",
210
+ "serverUsed": true,
211
+ "exitCode": 0
212
+ }
213
+ }
214
+ ```
215
+
216
+ ForgeLoop returns CLI exit code `0` for a completed query, including zero
217
+ matches, and `2` for a ForgeLoop/search error. The `metrics.exitCode` field
218
+ preserves the observed native result (`0` for matches or `1` for no matches)
219
+ for diagnostics. A native exit code `2` is always a structured search error.
220
+
221
+ Structured search output intentionally omits `repositoryRoot`, `indexPath`,
222
+ `statePath`, `binaryPath`, and other machine-local paths. Match and file paths
223
+ are repository-relative. The same sanitized projection is used by the CLI,
224
+ Integration API, and MCP adapter; `doctor` remains the explicit diagnostic
225
+ surface for local troubleshooting details.
226
+
227
+ The first search in a process performs strong setup and readiness checks.
228
+ Subsequent searches use a per-repository process-local readiness record and a
229
+ cheap PID liveness check, without repeating native version/status commands or
230
+ process command-line inspection. A healthy cache is invalidated when the
231
+ manifest version, selected binary, index boundary, or server liveness no
232
+ longer matches. If a query observes a server/index execution failure, ForgeLoop
233
+ performs one bounded setup-and-retry cycle. Native exit code `1` remains a
234
+ successful zero-match result and is never treated as a recovery failure.
235
+
236
+ ### Persistent CLI search host
237
+
238
+ The CLI search path uses a user-scoped persistent ForgeLoop host so separate
239
+ `forgeloop search` processes can reuse one local Node runtime and the existing
240
+ per-repository readiness cache. The host can serve multiple repositories. It is
241
+ an optimization layer only: it calls the canonical `searchRepository()` service
242
+ directly and never spawns `forgeloop`, `rg`, or a second search implementation.
243
+
244
+ The Integration API and MCP adapter continue to call the canonical service
245
+ directly. They do not cross the CLI transport or inherit its process lifecycle.
246
+ The CLI syntax and normalized result contract are unchanged.
247
+
248
+ The host uses a versioned length-prefixed JSON protocol over a local Unix-domain
249
+ socket on POSIX systems and a user-scoped Windows named pipe on Windows. The
250
+ authoritative operational state is kept under `~/.forgeloop/persistent-search/`;
251
+ it contains only protocol/version, PID, scope, nonce, endpoint, entrypoint, and
252
+ timestamps. It contains no repository roots, search history, matches, or
253
+ evidence. Requests and responses have bounded frame sizes, bounded
254
+ connection/startup timeouts, and stable transport error codes. A host idles out
255
+ after ten minutes by default without stopping repository tgrep watchers or
256
+ deleting their derived indexes.
257
+
258
+ Startup is serialized by a user-scoped lock. Every reuse, recovery, and stop
259
+ operation correlates the state record with a live PID, the exact host entrypoint,
260
+ the persistent-server marker, scope identity, and a nonce-bearing handshake.
261
+ Stale state is removed only after that boundary is proven; an unrelated process
262
+ is never terminated by name, broad pattern, or PID alone. The client performs
263
+ at most one bounded recovery attempt and never falls back to `rg`.
264
+
265
+ The transport protocol and ownership tests run without a native engine. Native
266
+ CI additionally runs real transport searches on Ubuntu, macOS, and Windows,
267
+ including cold/warm reuse, multiple repositories, 50-client startup
268
+ contention, recovery, and result differential checks. The observational
269
+ benchmark runner is [`run-persistent-transport.mjs`](../benchmarks/repository-index/run-persistent-transport.mjs);
270
+ it reports cold and warm API, persistent-host CLI, raw tgrep, and optional `rg`
271
+ timings separately, including a Node process-startup measurement. Results are
272
+ workload-specific and are not a correctness or universal speed claim.
273
+
274
+ Search patterns, paths, and filters are passed as direct argument-array values
275
+ with `shell: false`. Shell syntax is not evaluated. Request limits are:
276
+
277
+ For the transport protocol, host lifecycle, ownership proof, privacy boundary,
278
+ and recovery behavior, see the dedicated
279
+ [`Persistent Search Transport`](./PERSISTENT_SEARCH_TRANSPORT.md) reference.
280
+
281
+ | Input | Limit |
282
+ | --- | --- |
283
+ | Pattern | 1 to 4096 characters |
284
+ | Glob/type filters | At most 32 values of at most 256 characters each |
285
+ | Context values | Safe non-negative integers |
286
+ | `max-count` | A positive integer when supplied |
287
+
288
+ ## Status and lifecycle commands
289
+
290
+ All lifecycle commands support `--json`.
291
+
292
+ ### `index-status`
293
+
294
+ ```bash
295
+ forgeloop index-status
296
+ forgeloop index-status --json
297
+ ```
298
+
299
+ This command is read-only. It does not repair a stale server or download an
300
+ engine. The normalized status includes `health`, pinned engine information,
301
+ effective resource policy, index metadata, and owned-server state. Structured
302
+ status omits machine-local repository, index, state, and binary paths;
303
+ diagnostics may expose local paths only through the explicit `doctor`
304
+ diagnostic surface. Health is one of `READY`, `INDEXING`,
305
+ `NOT_INITIALIZED`, `ENGINE_MISSING`, `ENGINE_INVALID`, `SERVER_DOWN`,
306
+ `SERVER_UNHEALTHY`, or `ERROR`. Only `READY` satisfies mandatory readiness.
307
+
308
+ ### `index-start`
309
+
310
+ ```bash
311
+ forgeloop index-start --json
312
+ ```
313
+
314
+ Starts a server only after a complete index exists. A matching healthy server
315
+ is reused. ForgeLoop writes `engine-state.json` and validates the server's
316
+ repository root, index path, binary, server metadata, process liveness, and
317
+ command line.
318
+
319
+ ### `index-stop`
320
+
321
+ ```bash
322
+ forgeloop index-stop --json
323
+ ```
324
+
325
+ Stops only a server whose ownership is proven for the current repository. PID
326
+ presence is not ownership. ForgeLoop never uses `pkill`, `killall`, or an
327
+ executable-name-wide termination.
328
+
329
+ ### `index-rebuild`
330
+
331
+ ```bash
332
+ forgeloop index-rebuild --json
333
+ ```
334
+
335
+ This is an explicit derived-cache operation. It stops the ForgeLoop-owned
336
+ server, removes only `.forgeloop/repository-index/tgrep/`, rebuilds with the
337
+ canonical flags, restarts the watcher, and verifies readiness. Task state,
338
+ contracts, receipts, evidence, profiles, guides, and other `.forgeloop`
339
+ artifacts are outside its deletion boundary.
340
+
341
+ ## Integration API
342
+
343
+ The stable entrypoint is
344
+ `@cassiomc1/forgeloop/integration`. The named operation `repository/search`
345
+ uses the same `searchRepository()` service as the CLI:
346
+
347
+ ```js
348
+ import { repositorySearch, repositoryIndexStatus } from "@cassiomc1/forgeloop/integration";
349
+
350
+ const result = await repositorySearch({
351
+ projectPath: "/absolute/project",
352
+ pattern: "ExecutionReceipt",
353
+ globs: ["*.js"],
354
+ context: 2,
355
+ });
356
+
357
+ const status = await repositoryIndexStatus({ projectPath: "/absolute/project" });
358
+ ```
359
+
360
+ The public types are `RepositorySearchRequest`, `RepositorySearchMatch`,
361
+ `RepositorySearchResult`, and `RepositoryIndexStatus`. They do not expose
362
+ child-process objects, native JSON-RPC packets, or binary index internals.
363
+ Integrations must not supply arbitrary native command arguments.
364
+
365
+ The generic command envelope also supports `executeForgeLoopCommand({ command:
366
+ "search", projectPath, input: { pattern } })`; it has the same validation,
367
+ error, and provenance semantics as the CLI executor.
368
+
369
+ ## MCP usage
370
+
371
+ The optional MCP adapter derives the `forgeloop_search` tool from the canonical
372
+ command registry, so it calls ForgeLoop's search service rather than spawning
373
+ its own process. It exposes normalized structured output and preserves
374
+ ForgeLoop error codes. The read-only status resource is:
375
+
376
+ ```text
377
+ forgeloop://repository/index-status
378
+ ```
379
+
380
+ MCP clients must not create a second index configuration or pass raw tgrep
381
+ arguments. In safe/default mode, repository search is read-only and available;
382
+ maintenance commands such as setup, start, stop, and rebuild remain launch-
383
+ capability gated. See [`docs/MCP.md`](./MCP.md) for transport and capability
384
+ policy.
385
+
386
+ ## Resource controls
387
+
388
+ The initial canonical policy is intentionally small and explicit:
389
+
390
+ | Setting | Default |
391
+ | --- | --- |
392
+ | Maximum indexed/searchable file size | `64M` |
393
+ | Initial indexing CPU budget | `50%` of logical cores |
394
+ | Watcher queue capacity | `16384` events |
395
+ | Automatic mutation-save threshold | `5000` mutations |
396
+
397
+ The index command and server share the file-size and traversal boundary. The
398
+ server's own bounded memory behavior is retained for its initial build; the
399
+ ForgeLoop wrapper does not add a second scheduler. Effective values are
400
+ reported in `index-status`.
401
+
402
+ ## Ignored files
403
+
404
+ Normal indexing respects repository ignore rules and follows the pinned
405
+ engine's default hidden-file behavior. ForgeLoop also explicitly excludes
406
+ `.forgeloop/repository-index` so the cache cannot index its own writes. Tracked
407
+ source files and normal unignored files remain searchable; ignored generated
408
+ files are not part of the default result set.
409
+
410
+ Search is not a complete dependency analysis. A search result must not be used
411
+ to narrow Differential Verification Scope or to claim that unreturned files
412
+ are unaffected. Direct file reading remains authoritative when a verification
413
+ requirement concerns a large or ignored file.
414
+
415
+ ## File-size policy
416
+
417
+ The pinned engine's default maximum searchable file size is made explicit as
418
+ `64M`. Files over that limit may be absent from both the index and search
419
+ results. ForgeLoop does not claim that Repository Search covers every byte of
420
+ the repository. A known large-file verification must use an existing direct
421
+ verification mechanism rather than treating a no-match result as proof of
422
+ absence.
423
+
424
+ ## Offline installation
425
+
426
+ An already provisioned, version-verified managed binary works offline. A
427
+ missing binary requires either network access to the pinned GitHub release
428
+ asset or an explicit local archive:
429
+
430
+ ```bash
431
+ forgeloop index-setup --asset /absolute/path/tgrep-v1.0.3-x86_64-unknown-linux-musl.tar.gz
432
+ ```
433
+
434
+ The preloaded archive path must be absolute and regular. ForgeLoop validates
435
+ the exact platform archive and executable checksums, rejects archive path
436
+ traversal and symbolic-link entries, extracts only to a temporary directory,
437
+ verifies the executable digest before `tgrep --version`, and performs an
438
+ atomic install. A failed or partial download is removed and does not become a
439
+ trusted engine.
440
+
441
+ ## Troubleshooting
442
+
443
+ Start with read-only status:
444
+
445
+ ```bash
446
+ forgeloop index-status --json
447
+ forgeloop doctor --json
448
+ ```
449
+
450
+ Then use the narrowest repair:
451
+
452
+ ```bash
453
+ forgeloop index-start --json
454
+ forgeloop index-setup --asset /absolute/path/to/pinned-asset.tar.gz --json
455
+ forgeloop index-rebuild --json
456
+ ```
457
+
458
+ Stable Repository Index errors include:
459
+
460
+ | Code | Meaning | First response |
461
+ | --- | --- | --- |
462
+ | `E_REPOSITORY_INDEX_PLATFORM_UNSUPPORTED` | No pinned asset exists for the host pair | Use a supported platform or an explicitly supported release build |
463
+ | `E_REPOSITORY_INDEX_ENGINE_MISSING` | Managed/override binary is absent or not a regular executable | Run `index-setup` or provide `FORGELOOP_TGREP_BINARY` for development |
464
+ | `E_REPOSITORY_INDEX_ENGINE_DOWNLOAD_FAILED` | Pinned asset could not be safely downloaded/read | Check network or use `--asset` |
465
+ | `E_REPOSITORY_INDEX_ENGINE_CHECKSUM_MISMATCH` | Archive bytes differ from the manifest | Obtain the exact release asset; do not bypass verification |
466
+ | `E_REPOSITORY_INDEX_ENGINE_BINARY_CHECKSUM_MISMATCH` | Managed or extracted executable bytes differ from the manifest | Run `index-setup` or `index-rebuild` to repair the managed binary; do not run a mismatched executable |
467
+ | `E_REPOSITORY_INDEX_ENGINE_EXTRACTION_FAILED` | Archive is invalid or unsafe | Replace the archive with the exact pinned asset |
468
+ | `E_REPOSITORY_INDEX_ENGINE_VERSION_MISMATCH` | Binary does not report the pinned version | Use `tgrep 1.0.3` |
469
+ | `E_REPOSITORY_INDEX_ENGINE_EXECUTION_FAILED` | Managed executable could not be launched/verified | Inspect permissions and host compatibility |
470
+ | `E_REPOSITORY_INDEX_NOT_INITIALIZED` | No complete project index exists | Run `index-setup` |
471
+ | `E_REPOSITORY_INDEX_INDEXING` | Initial index metadata is incomplete | Wait briefly and inspect status again |
472
+ | `E_REPOSITORY_INDEX_SERVER_START_FAILED` | Owned watcher did not become ready | Inspect status, then run `index-rebuild` |
473
+ | `E_REPOSITORY_INDEX_SERVER_STOP_FAILED` | Ownership could not be proven or stop timed out | Do not kill by name; inspect metadata/process identity |
474
+ | `E_REPOSITORY_INDEX_SERVER_UNHEALTHY` | Server/index identity or health check failed | Run `index-status`, then rebuild if needed |
475
+ | `E_REPOSITORY_INDEX_SEARCH_FAILED` | Native search exited with an error | Inspect the preserved bounded diagnostic and status |
476
+ | `E_REPOSITORY_INDEX_OUTPUT_INVALID` | Known JSON output was malformed | Rebuild and report a pinned-engine regression if repeated |
477
+ | `E_REPOSITORY_INDEX_REBUILD_FAILED` | Rebuild did not produce complete metadata | Preserve other ForgeLoop state and retry after diagnosis |
478
+ | `E_REPOSITORY_INDEX_REQUEST_INVALID` | Search request exceeded the contract | Correct the pattern, filter, or numeric bound |
479
+
480
+ ## Security
481
+
482
+ The Repository Index is a local derived-cache boundary:
483
+
484
+ - version, asset, archive SHA-256, and executable SHA-256 are pinned in source control;
485
+ - release URLs are restricted to the expected HTTPS GitHub hosts;
486
+ - downloads and extraction are bounded and atomic; managed binaries are hashed
487
+ before any execution and tampered binaries are repaired only through the
488
+ canonical setup path;
489
+ - archive absolute paths, `..` traversal, and symbolic links are rejected;
490
+ - native processes receive direct argument arrays with `shell: false`;
491
+ - server stop requires repository-root, index-path, metadata, binary, and
492
+ command-line identity, not just a PID;
493
+ - search patterns, match text, and machine-local repository paths are not sent
494
+ to telemetry or returned in normal structured search/status output by default;
495
+ - native index files are never interpreted as protocol truth;
496
+ - search metrics remain operational observations, not evidence or completion
497
+ proof.
498
+
499
+ See [`THREAT_MODEL.md`](../THREAT_MODEL.md) and [`SECURITY.md`](../SECURITY.md)
500
+ for the broader ForgeLoop trust model.
501
+
502
+ ## Rebuilding
503
+
504
+ Use `index-rebuild` after corruption, a pinned-engine upgrade, or a confirmed
505
+ stale cache. The operation is deliberately scoped to derived Repository Index
506
+ data. It does not run task recovery, rewrite completion, alter claims, remove
507
+ receipts, or change guide/profile authority.
508
+
509
+ If an owned server unexpectedly exits, the next normal search invalidates its
510
+ local readiness record and performs one recovery setup/retry under a short
511
+ project-scoped startup lock. Concurrent searches share one verified server; the
512
+ lock is not held for the duration of a search query.
513
+
514
+ ## Upgrade behavior
515
+
516
+ The runtime uses one pinned version from the manifest and never auto-tracks
517
+ `latest`. When a future ForgeLoop release changes that version, `update`
518
+ provisions the new engine and rebuilds the derived index by default. An engine
519
+ upgrade must refresh asset names and hashes, third-party notices, differential
520
+ and live-watcher tests, benchmarks, and package validation before release.
521
+
522
+ Existing ForgeLoop projects do not need their entire `.forgeloop` directory
523
+ deleted. `update` creates missing Repository Index state while preserving
524
+ project profile, task state, evidence, receipts, and policy artifacts.
525
+
526
+ ## Performance benchmarking
527
+
528
+ The reproducible benchmark input is
529
+ [`benchmarks/repository-index/queries.json`](../benchmarks/repository-index/queries.json)
530
+ and its protocol is described in
531
+ [`benchmarks/repository-index/README.md`](../benchmarks/repository-index/README.md).
532
+ Measure cold index build, first-use setup, warm selective queries, post-mutation
533
+ queries, and high-match queries. Record actual duration, match counts, commit,
534
+ platform, architecture, Node version, and engine version. Do not convert these
535
+ measurements into token savings, cost savings, or universal speed claims.
536
+
537
+ ## Relationship to guides, context, and evidence
538
+
539
+ ForgeLoop keeps the boundaries distinct:
540
+
541
+ ```text
542
+ Guides / routing -> how the work should be performed
543
+ Repository Search -> where matching repository content exists
544
+ Task contract -> what outcome is required
545
+ Verification / evidence -> what was actually proven
546
+ Completion validation -> whether protocol completion is valid
547
+ ```
548
+
549
+ Repository Search can support discovery, planning, execution, debugging, and
550
+ review preparation. It is not a lifecycle transition, does not select or
551
+ shrink verification scope, and does not become a receipt or evidence source.
552
+ Optional Ripwire advisory context and structural-quality providers remain
553
+ independent capabilities; neither is a Repository Index backend.