@saasontools/strauss-kb 0.1.13 → 0.1.14
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 +39 -50
- package/README.md +139 -424
- package/dist/{chunk-XALWG3EZ.js → chunk-43KALLFU.js} +21 -36
- package/dist/chunk-43KALLFU.js.map +1 -0
- package/dist/{chunk-ZICKDZGY.js → chunk-MBXNCZ4V.js} +2 -2
- package/dist/{chunk-WZODZNR6.js → chunk-PYA5E7FL.js} +2 -2
- package/dist/cli-main.cjs +20 -35
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +20 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/mcp-main.cjs +20 -35
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-XALWG3EZ.js.map +0 -1
- /package/dist/{chunk-ZICKDZGY.js.map → chunk-MBXNCZ4V.js.map} +0 -0
- /package/dist/{chunk-WZODZNR6.js.map → chunk-PYA5E7FL.js.map} +0 -0
package/ARCHITECTURE.md
CHANGED
|
@@ -1,43 +1,42 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
The README
|
|
4
|
-
shaped that way, and which alternatives were tried and dropped — the decisions
|
|
5
|
-
a later reader would otherwise reopen.
|
|
3
|
+
The README is the entry point. This is why the format is shaped as it is.
|
|
6
4
|
|
|
7
5
|
## One record per file
|
|
8
6
|
|
|
9
|
-
The filename is the identity, so two writers never merge
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
last-write-wins.
|
|
7
|
+
The filename is the identity, so two writers never merge — they choose distinct
|
|
8
|
+
names. Publication uses `link`, so a collision surfaces as a 409 rather than a
|
|
9
|
+
silent last-write-wins.
|
|
13
10
|
|
|
14
11
|
Read-modify-write (`setStatus`, `answer`) checks a content digest immediately
|
|
15
|
-
before publishing
|
|
16
|
-
rather than closing it. A lock would close it and add a
|
|
17
|
-
than the residue: a crashed holder blocks every later writer, where a lost
|
|
18
|
-
update costs one retry.
|
|
12
|
+
before publishing, narrowing the lost-update window to two adjacent syscalls
|
|
13
|
+
rather than closing it. A lock would close it and add a worse failure: a crashed holder blocks every later writer, where a lost update costs one retry.
|
|
19
14
|
|
|
20
15
|
## Read for a question, not for a session
|
|
21
16
|
|
|
22
|
-
A base loaded at the start of a long conversation is summarised away by the end
|
|
23
|
-
|
|
17
|
+
A base loaded at the start of a long conversation is summarised away by the end,
|
|
18
|
+
so no consumer loads it that way:
|
|
24
19
|
|
|
25
|
-
| Consumer | How it reads
|
|
26
|
-
| ------------------------------- |
|
|
27
|
-
| Diff annotation | `matchToDiff` — deterministic, no context
|
|
28
|
-
| "Has this been decided?" | a fresh short-lived reader, given
|
|
29
|
-
| An implementor writing a record | a point query at the moment of writing
|
|
20
|
+
| Consumer | How it reads |
|
|
21
|
+
| ------------------------------- | --------------------------------------------------- |
|
|
22
|
+
| Diff annotation | `matchToDiff` — deterministic, no context |
|
|
23
|
+
| "Has this been decided?" | a fresh short-lived reader, given base and question |
|
|
24
|
+
| An implementor writing a record | a point query at the moment of writing |
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
Reloading costs about three thousand tokens for twenty records.
|
|
27
|
+
|
|
28
|
+
## Load beats retrieval while the base fits
|
|
29
|
+
|
|
30
|
+
On nine questions whose wording appears in no record, a reader holding the whole
|
|
31
|
+
base answered eight; embedding search over the same records answered four. Two
|
|
32
|
+
differences are structural: a reader can say no record answers, where vector
|
|
33
|
+
search returns its nearest neighbour whatever the distance; and it picks the
|
|
34
|
+
record that answers rather than the one nearest the topic.
|
|
35
35
|
|
|
36
36
|
## What happens when a base outgrows a context
|
|
37
37
|
|
|
38
|
-
Loading stops working
|
|
39
|
-
|
|
40
|
-
candidates instead of everything:
|
|
38
|
+
Loading stops working above a few hundred records; what replaces it is the same
|
|
39
|
+
reader given candidates, not everything:
|
|
41
40
|
|
|
42
41
|
```
|
|
43
42
|
vector recall → top ~20 candidates, with their scores
|
|
@@ -45,24 +44,18 @@ vector recall → top ~20 candidates, with their scores
|
|
|
45
44
|
reader judges → picks what answers, or says nothing does
|
|
46
45
|
```
|
|
47
46
|
|
|
48
|
-
The reader stays the judge
|
|
49
|
-
structural wins the README reports: it can say no record answers the question,
|
|
50
|
-
and it picks the record that answers rather than the one nearest the topic.
|
|
51
|
-
Neither survives if a ranker's top hit is taken as the answer.
|
|
47
|
+
The reader stays the judge, preserving the two structural wins above.
|
|
52
48
|
|
|
53
49
|
**A score threshold is not the growth path.** The wrong `audit trail` hit scored
|
|
54
50
|
0.318 against the correct `race condition` hit at 0.295; any cut that drops the
|
|
55
51
|
first drops the second. A threshold excludes the absurd — an unrelated query
|
|
56
52
|
scored 0.091 — and nothing else.
|
|
57
53
|
|
|
58
|
-
**Tags are not the growth path either.** The field exists, is written, and
|
|
59
|
-
|
|
60
|
-
`
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
`strauss_anchors` names a file and a symbol, which either match the repository
|
|
64
|
-
or do not, where a tag can be wrong forever. If narrowing ever matters, measure
|
|
65
|
-
tag narrowing against vector recall on a real base rather than adding both.
|
|
54
|
+
**Tags are not the growth path either.** The field exists, is written, and read by
|
|
55
|
+
nothing but an index line. Free-text tags drift the way `auth` /
|
|
56
|
+
`authentication` / `authn` drift; enforcing a vocabulary would make them a
|
|
57
|
+
closed enum, which `type` already is. `strauss_anchors` names a file and symbol,
|
|
58
|
+
which either match the repository or not.
|
|
66
59
|
|
|
67
60
|
## Typed links
|
|
68
61
|
|
|
@@ -81,11 +74,10 @@ record's declared dependencies are not obligations anyone still owes.
|
|
|
81
74
|
|
|
82
75
|
## Rejected: a format that needs a parser
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`strauss-kb schema` is the contract rather than a description of one.
|
|
77
|
+
A hand-rolled frontmatter reader could not express nested maps, misreading every
|
|
78
|
+
OKF `generated`, `sources[]`, and `verified[]`; its replacement's first log
|
|
79
|
+
format was `·`-delimited. Both are gone: the log is JSONL, the schema is emitted
|
|
80
|
+
from Zod, and `strauss-kb schema` is the contract.
|
|
89
81
|
|
|
90
82
|
## Anchor resolution
|
|
91
83
|
|
|
@@ -195,12 +187,9 @@ local git client actually performs.
|
|
|
195
187
|
|
|
196
188
|
## Rejected for now: a base registry
|
|
197
189
|
|
|
198
|
-
Cross-base questions are unaskable
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
disposable.
|
|
190
|
+
Cross-base questions are unaskable: supersession, traces, and search stop at the
|
|
191
|
+
directory boundary. That is the price of a base that can be copied or handed
|
|
192
|
+
over whole, and it keeps the search index disposable.
|
|
202
193
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
only for display. It is deliberately unbuilt. Adding it early would drag back
|
|
206
|
-
the cross-scope machinery this model exists to avoid.
|
|
194
|
+
The cheap escape, if that becomes the common case, is a registry: paths a caller
|
|
195
|
+
names explicitly, queried one at a time and merged only for display.
|