@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.
- package/.cursor/rules/project-loop.mdc +2 -2
- package/.forgeloop/forgeloop.gitignore +1 -0
- package/.github/copilot-instructions.md +2 -2
- package/AGENTS.md +1 -0
- package/AGENT_COMPATIBILITY.md +7 -0
- package/CLAUDE.md +1 -0
- package/DOCS_INDEX.md +10 -0
- package/LOOP_SYSTEM_DESIGN.md +12 -0
- package/ORCHESTRATOR_INTEGRATION.md +9 -0
- package/PROTOCOL_INTEGRATION.md +17 -0
- package/README.md +12 -10
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/THREAT_MODEL.md +21 -0
- package/benchmarks/repository-index/README.md +73 -0
- package/benchmarks/repository-index/queries.json +12 -0
- package/benchmarks/repository-index/run-hot-path.mjs +142 -0
- package/benchmarks/repository-index/run-persistent-transport.mjs +169 -0
- package/completions/_forgeloop +7 -1
- package/completions/forgeloop.bash +13 -1
- package/completions/forgeloop.fish +40 -1
- package/docs/AGENT_PROTOCOL_SUMMARY.md +8 -1
- package/docs/CLI_REFERENCE.md +114 -2
- package/docs/DOCUMENTATION_GUIDE.md +10 -5
- package/docs/GETTING_STARTED.md +17 -0
- package/docs/MCP.md +16 -1
- package/docs/PACKAGE_CONTENTS.md +7 -1
- package/docs/PERSISTENT_SEARCH_TRANSPORT.md +289 -0
- package/docs/RECIPES.md +30 -0
- package/docs/RELEASE_CHECKLIST.md +34 -0
- package/docs/REPOSITORY_INDEX.md +553 -0
- package/docs/TROUBLESHOOTING.md +147 -0
- package/docs/UNIVERSAL_INTEGRATION.md +30 -0
- package/docs/diagrams/README.md +10 -0
- package/package.json +11 -2
- package/scripts/update-tgrep-manifest.mjs +86 -0
- package/scripts/verify-tgrep-manifest.mjs +17 -0
- package/src/cli.js +35 -0
- package/src/commands/doctor.js +76 -1
- package/src/commands/index-rebuild.js +1 -0
- package/src/commands/index-setup.js +1 -0
- package/src/commands/index-start.js +1 -0
- package/src/commands/index-status.js +1 -0
- package/src/commands/index-stop.js +1 -0
- package/src/commands/init.js +39 -1
- package/src/commands/repository-index.js +111 -0
- package/src/commands/search.js +1 -0
- package/src/commands/update.js +32 -4
- package/src/core/cli-command-definitions.js +97 -3
- package/src/core/command-executors.js +35 -2
- package/src/core/command-input.js +23 -0
- package/src/core/error-codes.js +195 -0
- package/src/core/filesystem.js +10 -1
- package/src/core/integration-invocation-policy.js +27 -0
- package/src/core/integration-resources.js +16 -1
- package/src/core/protocol-info.js +23 -0
- package/src/integration.d.ts +90 -0
- package/src/integration.js +21 -0
- package/src/persistent-transport/client.js +293 -0
- package/src/persistent-transport/constants.js +24 -0
- package/src/persistent-transport/errors.js +38 -0
- package/src/persistent-transport/framing.js +61 -0
- package/src/persistent-transport/lifecycle.js +116 -0
- package/src/persistent-transport/ownership.js +184 -0
- package/src/persistent-transport/paths.js +31 -0
- package/src/persistent-transport/protocol.js +95 -0
- package/src/persistent-transport/server.js +256 -0
- package/src/persistent-transport/state.js +49 -0
- package/src/repository-index/args.js +59 -0
- package/src/repository-index/binary-manager.js +413 -0
- package/src/repository-index/constants.js +45 -0
- package/src/repository-index/errors.js +38 -0
- package/src/repository-index/lifecycle.js +17 -0
- package/src/repository-index/lock.js +113 -0
- package/src/repository-index/manifest.js +132 -0
- package/src/repository-index/metrics.js +30 -0
- package/src/repository-index/normalize-json.js +187 -0
- package/src/repository-index/paths.js +39 -0
- package/src/repository-index/platform.js +20 -0
- package/src/repository-index/process.js +140 -0
- package/src/repository-index/readiness.js +62 -0
- package/src/repository-index/search.js +262 -0
- package/src/repository-index/server.js +432 -0
- package/src/repository-index/status.js +397 -0
- 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.
|