@saasontools/strauss-kb 0.1.16 → 0.1.18
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/ARCHITECTURE.md +48 -5
- package/README.md +44 -6
- package/dist/{chunk-H5W53NVU.js → chunk-GSOTMWZZ.js} +1765 -342
- package/dist/chunk-GSOTMWZZ.js.map +1 -0
- package/dist/{chunk-RINBOAQZ.js → chunk-IOIUS26S.js} +2 -2
- package/dist/{chunk-MEZCF646.js → chunk-ROGVYSMV.js} +2 -2
- package/dist/cli-main.cjs +1772 -363
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +1825 -381
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +504 -9
- package/dist/index.d.ts +504 -9
- package/dist/index.js +29 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-main.cjs +1761 -352
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/grammars/README.md +78 -0
- package/grammars/manifest.json +595 -0
- package/grammars/packs.json +127 -0
- package/package.json +7 -2
- package/dist/chunk-H5W53NVU.js.map +0 -1
- /package/dist/{chunk-RINBOAQZ.js.map → chunk-IOIUS26S.js.map} +0 -0
- /package/dist/{chunk-MEZCF646.js.map → chunk-ROGVYSMV.js.map} +0 -0
package/ARCHITECTURE.md
CHANGED
|
@@ -84,11 +84,54 @@ from Zod, and `strauss-kb schema` is the contract.
|
|
|
84
84
|
A fresh stamp is a baseline nobody has checked, so only a run where every
|
|
85
85
|
checkable anchor already matched appends `verified[]`.
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
Symbols resolve through tree-sitter first: a WASM parser per language, each
|
|
88
|
+
grammar's own upstream `queries/tags.scm` over definition sites, and the
|
|
89
|
+
definition node's range as the span. A dotted symbol matches the definition whose enclosing chain
|
|
90
|
+
matches; a bare name matching two is `symbol-ambiguous`. Only declarations are
|
|
91
|
+
captured: a symbol appearing solely in a call is no match.
|
|
92
|
+
|
|
93
|
+
The chain is tree-sitter, then regex, then a whole-file hash. A resolver that
|
|
94
|
+
parsed the file answers for it unless it defines no such symbol at all — tags
|
|
95
|
+
queries capture functions and types, not constants, aliases or fields — so
|
|
96
|
+
`symbol-not-found` continues down the chain and the anchor records whichever
|
|
97
|
+
resolver answered. `symbol-ambiguous` and `resolver-unavailable` stop it:
|
|
98
|
+
picking one of two definitions by text search, or swapping a precise span for a
|
|
99
|
+
heuristic one when a grammar will not load, is how a wrong span comes to hash
|
|
100
|
+
as `match`. A grammar that will not load is a finding, never a throw.
|
|
101
|
+
|
|
102
|
+
Grammars download on first use, sha256-pinned by `grammars/manifest.json` and
|
|
103
|
+
cached under `~/.strauss/grammars`; the reasoning is in the
|
|
104
|
+
[specification](https://saasontools.github.io/strauss-agent-tools/specification#symbol-resolution).
|
|
105
|
+
|
|
106
|
+
Each anchor records the resolver that stamped it. A hash only the previous
|
|
107
|
+
resolver reproduces is `drifted`, reason `resolver-changed`. Trees are cached
|
|
108
|
+
per content hash, grammars load once per process.
|
|
109
|
+
|
|
110
|
+
A tree-sitter stamp hashes the span's token stream rather than its text
|
|
111
|
+
(`hash_kind: "ast"`), so a reformat is not drift; a raw hash keeps comparing
|
|
112
|
+
raw until it is rebaselined.
|
|
113
|
+
|
|
114
|
+
### Drift classification
|
|
115
|
+
|
|
116
|
+
Once the bytes differ, the question is what a machine can settle and what it
|
|
117
|
+
must hand on.
|
|
118
|
+
|
|
119
|
+
| Class | Test | Who settles it |
|
|
120
|
+
| ---------- | ------------------------------------------- | -------------- |
|
|
121
|
+
| `moved` | the stored hash resolves at another address | `kb_reassess` |
|
|
122
|
+
| `cosmetic` | both spans are one token stream | classification |
|
|
123
|
+
| `gone` | the file or symbol no longer exists | a reader |
|
|
124
|
+
| `changed` | everything else | a reader |
|
|
125
|
+
|
|
126
|
+
`moved` and `cosmetic` cost a repository search and a git read, so `load` and
|
|
127
|
+
`query` report only the two a hash comparison already answers and
|
|
128
|
+
`classifyDrift` refines the rest on demand.
|
|
129
|
+
|
|
130
|
+
Classification stops there because the next question — does the record's claim
|
|
131
|
+
still hold — is a reading, and every mechanical proxy for it (similarity
|
|
132
|
+
scores, "small" diffs) answers a different question confidently. So the packet
|
|
133
|
+
carries the evidence a reader needs and names a type-based default, and no
|
|
134
|
+
drift path writes `verified[]` or moves standing.
|
|
92
135
|
|
|
93
136
|
Repository identity is normalised and compared, not parsed: an invented format
|
|
94
137
|
would reject correct values from unseen hosts.
|
package/README.md
CHANGED
|
@@ -206,17 +206,19 @@ Why a lock was rejected: [ARCHITECTURE.md](./ARCHITECTURE.md).
|
|
|
206
206
|
|
|
207
207
|
An anchor names where a record attaches in the code: a `file`, optionally a
|
|
208
208
|
`symbol` — symbolic, because a line number written mid-change is wrong by the
|
|
209
|
-
end of it.
|
|
209
|
+
end of it. Six optional fields extend it:
|
|
210
210
|
|
|
211
211
|
| Field | Meaning |
|
|
212
212
|
| ------------- | ------------------------------------------------------------------------------------- |
|
|
213
213
|
| `hash` | `sha256:<hex>` over the anchored text, algorithm-prefixed. |
|
|
214
|
+
| `hash_kind` | What `hash` covered: `raw` text, or the `ast` token stream. Absent means `raw`. |
|
|
214
215
|
| `lines` | Line count the hash covered. |
|
|
215
216
|
| `resolved_at` | When the anchor last resolved. |
|
|
217
|
+
| `resolver` | Which resolver produced the hash: `tree-sitter` or `regex`. |
|
|
216
218
|
| `repo` | Which repository — remote URL or short name. Absent means this base's own repository. |
|
|
217
219
|
| `ref` | Git rev the evidence was taken at. |
|
|
218
220
|
|
|
219
|
-
`hash`, `lines`, and `
|
|
221
|
+
`hash`, `hash_kind`, `lines`, `resolved_at`, and `resolver` are **measured** — a resolution pass stamps
|
|
220
222
|
them; `repo` and `ref` are **author-owned identity** and a resolution pass
|
|
221
223
|
never writes them.
|
|
222
224
|
|
|
@@ -246,8 +248,40 @@ carries a hash; unstamped anchors and unreachable remotes never fail.
|
|
|
246
248
|
A fully clean run — every anchor checked and `match`, none stamped this run —
|
|
247
249
|
appends a `verified[]` event.
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
`
|
|
251
|
+
Symbols resolve tree-sitter first — the 20 language packs that have both a
|
|
252
|
+
grammar and a definitions query, pinned together by `pnpm grammars pin` from
|
|
253
|
+
`grammars/packs.json` and proved at pin time — then the regex heuristic for
|
|
254
|
+
other extensions and for symbols the tags query does not define (constants,
|
|
255
|
+
type aliases, class fields), then a
|
|
256
|
+
whole-file hash when the anchor names no symbol; an ambiguous match or an
|
|
257
|
+
unloadable grammar returns `unresolved` rather than falling through to a guess. Neither half of a pack is published with the
|
|
258
|
+
package: grammar and query both download on first use, sha256-pinned against
|
|
259
|
+
`grammars/manifest.json`, and are cached under `~/.strauss/grammars`. A hash the old resolver still reproduces and
|
|
260
|
+
the new one does not is `drifted` with reason `resolver-changed` — accept it
|
|
261
|
+
with `--rebaseline`.
|
|
262
|
+
|
|
263
|
+
A tree-sitter stamp hashes the span's normalised token stream
|
|
264
|
+
(`hash_kind: "ast"`), so reformatting the anchored code is not drift. An anchor
|
|
265
|
+
stamped before that keeps comparing raw text until `--rebaseline` restamps it.
|
|
266
|
+
|
|
267
|
+
### Drift classes
|
|
268
|
+
|
|
269
|
+
Once the bytes differ, drift is classified — two classes a machine can close,
|
|
270
|
+
two it hands on:
|
|
271
|
+
|
|
272
|
+
- **moved** — the stored hash turned up elsewhere: same code, new address.
|
|
273
|
+
`kb_reassess` moves the anchor and asks nothing of a reader.
|
|
274
|
+
- **cosmetic** — the old and new spans are one token stream; only formatting
|
|
275
|
+
changed. Needs a grammar, so the regex resolver never reports it.
|
|
276
|
+
- **gone** — the file or the symbol no longer exists. The strongest signal:
|
|
277
|
+
the described code cannot be re-read.
|
|
278
|
+
- **changed** — everything else, and the only class a reader has to judge.
|
|
279
|
+
|
|
280
|
+
`kb_reassess <concept-id>` (`kb_doctor --drifted` base-wide) turns what is left
|
|
281
|
+
into a packet: the record's claim, each anchor's class, the old-vs-new span diff
|
|
282
|
+
(`--with-diff`, recovered from `ref` or from history), and the record's `impact`
|
|
283
|
+
set. Neither verb verifies, supersedes, or changes standing — see the skill's
|
|
284
|
+
protocol.
|
|
251
285
|
|
|
252
286
|
Drift also surfaces on read: `kb_load` and `kb_query` attach a
|
|
253
287
|
`{ kind: "drifted" }` warning — or `{ kind: "unchecked" }` for a foreign anchor
|
|
@@ -275,6 +309,8 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
275
309
|
verify <concept-id> --note <text> Append a verified[] event — who checked, when, and what the check found.
|
|
276
310
|
anchor-resolve <concept-id> [--repo-root <path>] [--rebaseline] [--restamp]
|
|
277
311
|
Resolve anchors against the working tree: stamp, or report drift.
|
|
312
|
+
reassess <concept-id> [--repo-root <path>] [--with-diff]
|
|
313
|
+
One drifted record as something to judge: claim, classes, diff, impact.
|
|
278
314
|
load [type] [--budget N | --all] [--repo-root PATH]
|
|
279
315
|
Hand over the whole base, each record with its standing.
|
|
280
316
|
catalog [type] Every record in one line — id, type, title, standing, stale flag.
|
|
@@ -344,9 +380,11 @@ strauss-kb validate || echo "errors above" # warnings alone still exit 0
|
|
|
344
380
|
```
|
|
345
381
|
|
|
346
382
|
Every CLI verb is a tool: `kb_write`, `kb_write_decision`, `kb_no_decision`,
|
|
347
|
-
`kb_status`, `kb_supersede`, `kb_answer`, `kb_verify`, `kb_anchor_resolve`, `
|
|
383
|
+
`kb_status`, `kb_supersede`, `kb_answer`, `kb_verify`, `kb_anchor_resolve`, `kb_reassess`,
|
|
384
|
+
`kb_load`, `kb_catalog`,
|
|
348
385
|
`kb_pack`,
|
|
349
|
-
`kb_query`, `kb_trace`, `kb_impact`, `kb_backlinks`, `kb_list`, `kb_index`, `kb_log`, `
|
|
386
|
+
`kb_query`, `kb_trace`, `kb_impact`, `kb_backlinks`, `kb_list`, `kb_index`, `kb_log`, `kb_stamp`,
|
|
387
|
+
`kb_validate`,
|
|
350
388
|
`kb_doctor`, `kb_schema`, `kb_types`, `kb_pin`, `kb_unpin`, `kb_pins`,
|
|
351
389
|
`kb_context`. Most take a `bundlePath`. The one CLI verb with no tool is
|
|
352
390
|
`sync-instructions`; the agent capability is `kb_context`.
|