unknown-knowledge 2.1.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/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +167 -0
- package/cli/.gitkeep +0 -0
- package/cli/commands/init-copy.js +90 -0
- package/cli/commands/init.js +386 -0
- package/cli/init-copy.js +24 -0
- package/cli/init.js +24 -0
- package/cli/kit.manifest.yaml +256 -0
- package/cli/lib/copy-payload.js +334 -0
- package/cli/lib/generate-wrappers.js +162 -0
- package/package.json +36 -0
- package/payload/adapter-fixtures/README.md +53 -0
- package/payload/adapter-fixtures/html/EXPECTED.yaml +50 -0
- package/payload/adapter-fixtures/html/sample.html +38 -0
- package/payload/adapter-fixtures/md/EXPECTED.yaml +65 -0
- package/payload/adapter-fixtures/md/sample.md +32 -0
- package/payload/adapter-fixtures/pdf/EXPECTED.yaml +45 -0
- package/payload/adapter-fixtures/pdf/sample.pdf +0 -0
- package/payload/adapter-fixtures/txt/EXPECTED.yaml +31 -0
- package/payload/adapter-fixtures/txt/sample.txt +18 -0
- package/payload/docs/README.md +102 -0
- package/payload/docs/boundaries.md +60 -0
- package/payload/docs/ci-wiring.md +109 -0
- package/payload/docs/steward-guide.md +238 -0
- package/payload/engine/audit.js +34 -0
- package/payload/engine/commands/audit.js +289 -0
- package/payload/engine/commands/derive.js +334 -0
- package/payload/engine/commands/ingest.js +124 -0
- package/payload/engine/commands/log-entry.js +85 -0
- package/payload/engine/commands/phoenix.js +206 -0
- package/payload/engine/commands/preflight.js +530 -0
- package/payload/engine/commands/resolve.js +1678 -0
- package/payload/engine/commands/survey-map.js +351 -0
- package/payload/engine/commands/validate-values.js +315 -0
- package/payload/engine/commands/validate.js +1426 -0
- package/payload/engine/derive.js +34 -0
- package/payload/engine/ingest.js +34 -0
- package/payload/engine/lib/anchor-signatures.js +126 -0
- package/payload/engine/lib/boot.js +39 -0
- package/payload/engine/lib/call-numbers.js +133 -0
- package/payload/engine/lib/cli.js +147 -0
- package/payload/engine/lib/coverage.js +849 -0
- package/payload/engine/lib/decomposition.js +225 -0
- package/payload/engine/lib/derived.js +494 -0
- package/payload/engine/lib/engine-refusal.js +40 -0
- package/payload/engine/lib/exit-codes.js +14 -0
- package/payload/engine/lib/extractor-kinds.js +955 -0
- package/payload/engine/lib/format-adapters.js +802 -0
- package/payload/engine/lib/id-grammars.js +178 -0
- package/payload/engine/lib/iso-date.js +55 -0
- package/payload/engine/lib/kit-root.js +101 -0
- package/payload/engine/lib/load-stores.js +1624 -0
- package/payload/engine/lib/log-entry.js +196 -0
- package/payload/engine/lib/phoenix.js +628 -0
- package/payload/engine/lib/scoring.js +150 -0
- package/payload/engine/lib/suppressions.js +172 -0
- package/payload/engine/lib/time-verdicts.js +282 -0
- package/payload/engine/lib/usage-error.js +14 -0
- package/payload/engine/lib/validate-record.js +504 -0
- package/payload/engine/log-entry.js +34 -0
- package/payload/engine/phoenix.js +39 -0
- package/payload/engine/preflight.js +34 -0
- package/payload/engine/resolve.js +34 -0
- package/payload/engine/survey-map.js +34 -0
- package/payload/engine/validate-values.js +34 -0
- package/payload/engine/validate.js +34 -0
- package/payload/extractor-fixtures/.gitkeep +0 -0
- package/payload/extractor-fixtures/README.md +29 -0
- package/payload/extractor-fixtures/swift/strings-keys/EXPECTED.yaml +8 -0
- package/payload/extractor-fixtures/swift/strings-keys/sample.strings +15 -0
- package/payload/extractor-fixtures/swift/swift-const-array/EXPECTED.yaml +7 -0
- package/payload/extractor-fixtures/swift/swift-const-array/sample.swift +21 -0
- package/payload/extractor-fixtures/swift/swift-enum/EXPECTED.yaml +8 -0
- package/payload/extractor-fixtures/swift/swift-enum/sample.swift +30 -0
- package/payload/extractor-fixtures/swift/yaml-keys/EXPECTED.yaml +6 -0
- package/payload/extractor-fixtures/swift/yaml-keys/sample.yaml +23 -0
- package/payload/extractor-fixtures/swift/yaml-map-keys/EXPECTED.yaml +7 -0
- package/payload/extractor-fixtures/swift/yaml-map-keys/sample.yaml +15 -0
- package/payload/extractor-fixtures/ts/dir-modules/EXPECTED.yaml +12 -0
- package/payload/extractor-fixtures/ts/dir-modules/sample-modules/alpha.widget.ts +1 -0
- package/payload/extractor-fixtures/ts/dir-modules/sample-modules/beta.widget.ts +1 -0
- package/payload/extractor-fixtures/ts/dir-modules/sample-modules/gamma.widget.ts +1 -0
- package/payload/extractor-fixtures/ts/dir-modules/sample-modules/helpers/format.ts +3 -0
- package/payload/extractor-fixtures/ts/dir-modules/sample-modules/widgets.test.ts +2 -0
- package/payload/extractor-fixtures/ts/json-keys/EXPECTED.yaml +7 -0
- package/payload/extractor-fixtures/ts/json-keys/sample.json +5 -0
- package/payload/extractor-fixtures/ts/json-map-keys/EXPECTED.yaml +7 -0
- package/payload/extractor-fixtures/ts/json-map-keys/sample.json +13 -0
- package/payload/extractor-fixtures/ts/ts-const-array/EXPECTED.yaml +6 -0
- package/payload/extractor-fixtures/ts/ts-const-array/sample.ts +13 -0
- package/payload/extractor-fixtures/ts/ts-enum/EXPECTED.yaml +7 -0
- package/payload/extractor-fixtures/ts/ts-enum/sample.ts +11 -0
- package/payload/extractor-fixtures/ts/ts-object-keys/EXPECTED.yaml +6 -0
- package/payload/extractor-fixtures/ts/ts-object-keys/sample.tsx +23 -0
- package/payload/extractor-fixtures/ts/ts-union/EXPECTED.yaml +5 -0
- package/payload/extractor-fixtures/ts/ts-union/sample.ts +9 -0
- package/payload/hooks/pre-commit +37 -0
- package/payload/hooks/reverse-lookup +66 -0
- package/payload/package.json +3 -0
- package/payload/protocol/.gitkeep +0 -0
- package/payload/protocol/AGENTS.md +239 -0
- package/payload/protocol/derived-layer.md +174 -0
- package/payload/protocol/new-kind-pipeline.md +179 -0
- package/payload/protocol/registry-warrant.md +162 -0
- package/payload/protocol/skills/kb-build.md +303 -0
- package/payload/protocol/skills/knowledge-audit.md +183 -0
- package/payload/protocol/skills/knowledge-bootstrap.md +229 -0
- package/payload/protocol/skills/knowledge-reflect.md +397 -0
- package/payload/schemas/catalog.schema.json +32 -0
- package/payload/schemas/decision-entry.schema.json +122 -0
- package/payload/schemas/finding.schema.json +77 -0
- package/payload/schemas/gap.schema.json +52 -0
- package/payload/schemas/graduation-categories.schema.json +64 -0
- package/payload/schemas/knowledge-leaf.schema.json +194 -0
- package/payload/schemas/miss.schema.json +45 -0
- package/payload/schemas/ontology-concept.schema.json +115 -0
- package/payload/schemas/phoenix-event.schema.json +76 -0
- package/payload/schemas/registry.schema.json +57 -0
- package/payload/schemas/rules.schema.json +14 -0
- package/payload/schemas/survey-scope.schema.json +23 -0
- package/payload/templates/decisions/_catalog.yaml +7 -0
- package/payload/templates/decisions/_registries/graduation-categories.yaml +42 -0
- package/payload/templates/decisions/phoenix-event.yaml +74 -0
- package/payload/templates/decisions/reflect-mint-proposal.yaml +100 -0
- package/payload/templates/decisions/registry-minting.yaml +58 -0
- package/payload/templates/decisions/trust-graduation.yaml +120 -0
- package/payload/templates/decisions/trust-revocation.yaml +106 -0
- package/payload/templates/knowledge/_catalog.yaml +9 -0
- package/payload/templates/knowledge/_registries/anchor.yaml +42 -0
- package/payload/templates/knowledge/_registries/authority-tiers.yaml +32 -0
- package/payload/templates/knowledge/_registries/domains.yaml +43 -0
- package/payload/templates/knowledge/_registries/form.yaml +38 -0
- package/payload/templates/knowledge/_registries/jurisdictions.yaml +20 -0
- package/payload/templates/knowledge/_registries/operations.yaml +18 -0
- package/payload/templates/knowledge/_registries/stage.yaml +53 -0
- package/payload/templates/knowledge/_rules.yaml +6 -0
- package/payload/templates/new-kind/README.md +107 -0
- package/payload/templates/new-kind/descriptor.example.yaml +18 -0
- package/payload/templates/new-kind/fixture/EXPECTED.yaml +6 -0
- package/payload/templates/new-kind/fixture/demo-anchor.list +2 -0
- package/payload/templates/new-kind/fixture/sample.list +7 -0
- package/payload/templates/new-kind/parser.example.js +98 -0
- package/payload/templates/ontology/_catalog.yaml +6 -0
- package/payload/templates/ontology/_rules.yaml +6 -0
- package/payload/wrappers/cursor.mdc +15 -0
- package/payload/wrappers/pointer.md +10 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# /knowledge-bootstrap — phase-2 store population (PRD §6, D-019)
|
|
2
|
+
|
|
3
|
+
> Paths in this document are client-relative — relative to the vendored kit
|
|
4
|
+
> root after init (`ontology/…`, `engine/…`, `protocol/…`). In the kit repo
|
|
5
|
+
> itself these live under `payload/`. Commands are written to run from the
|
|
6
|
+
> **repo root** with the kit dir at its default name `unknown-knowledge/`;
|
|
7
|
+
> substitute your chosen kit dir name if it differs.
|
|
8
|
+
|
|
9
|
+
Init's phase 1 (the CLI) scaffolded empty stores; this skill is phase 2 — the
|
|
10
|
+
judgment half, run by whatever agent the client already uses. It populates
|
|
11
|
+
the stores: a confirmed traversal scope, a per-project class taxonomy, the
|
|
12
|
+
first ontology concepts (each born with its checkability rung), the miss-log
|
|
13
|
+
backlog, and the knowledge-store skeleton. Per-platform wrapper files are
|
|
14
|
+
thin pointers here; this is the platform-agnostic skill body. You operate
|
|
15
|
+
under `protocol/AGENTS.md` throughout — every gate rule there binds here.
|
|
16
|
+
|
|
17
|
+
Two `--root` conventions, stated once (same as AGENTS.md):
|
|
18
|
+
|
|
19
|
+
- Every store-reading CLI (`survey-map.js`, `resolve.js`, `validate.js`,
|
|
20
|
+
`validate-values.js`) takes `--root` as the **repo root** (default: cwd);
|
|
21
|
+
the stores are auto-located at `<root>/unknown-knowledge/`.
|
|
22
|
+
- `log-entry.js` takes `--root` as the **kit dir** (the directory containing
|
|
23
|
+
`logs/`), e.g. `--root unknown-knowledge`.
|
|
24
|
+
|
|
25
|
+
## Resumable by construction
|
|
26
|
+
|
|
27
|
+
A dead session costs the remaining steps, never a restart. **On entry,
|
|
28
|
+
detect existing artifacts and resume from the first incomplete step** —
|
|
29
|
+
each step below also carries its own "On resume" rule:
|
|
30
|
+
|
|
31
|
+
| Artifact found on entry | What it means |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `survey-scope.yaml` at the repo root AND class rules in `ontology/_rules.yaml` | the scope+taxonomy gate was confirmed — it is **never re-litigated on resume**; skip to EMIT (survey-map now honors the scope automatically). Scope file WITHOUT class rules means the session stopped mid-gate: complete the taxonomy half (the confirmed scope itself is not re-asked) before moving on |
|
|
34
|
+
| `ontology/_rules.yaml` with class rules | the taxonomy half of the gate is done; do not re-propose it |
|
|
35
|
+
| Concepts in `ontology/classes/` | emission already started — it is **idempotent by anchor identity**: probe each anchor with the reverse lookup before emitting; never a duplicate concept for the same anchor |
|
|
36
|
+
| An **open** `logs/misses/` entry for a path | the standing demand signal already exists — never mint a sibling for a known anchor (`protocol/new-kind-pipeline.md`) |
|
|
37
|
+
| `knowledge/_rules.yaml` with rule items | the KB interview happened; skip to FINISH |
|
|
38
|
+
| A proposed bootstrap decision in `decisions/entries/` | the wrap-up draft exists; go straight to the validator run |
|
|
39
|
+
|
|
40
|
+
## The six steps
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
1. SURVEY read-only: engine/survey-map.js → triage, never traverse
|
|
44
|
+
2. GATE ONE human gate: scope + taxonomy together → survey-scope.yaml
|
|
45
|
+
3. EMIT concepts at their highest checkable rung, not exhaustively
|
|
46
|
+
4. MISS unreadable anchors → logs/misses/ via engine/log-entry.js
|
|
47
|
+
5. INTERVIEW knowledge-store skeleton from the human
|
|
48
|
+
6. FINISH both validators green, bootstrap decisions drafted
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 1. SURVEY — run the map, triage the artifact
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
node unknown-knowledge/engine/survey-map.js --root .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Raw repo traversal is a protocol violation.** The survey map is the
|
|
58
|
+
traversal surface: git-tracked files only, denylist applied, per-directory
|
|
59
|
+
extension histograms, and an anchor-candidate pre-scan sharing one regex
|
|
60
|
+
table with the extractor kinds. You *triage* this artifact — grep is free,
|
|
61
|
+
reading is expensive, judgment is what you are for. Add `--json` when you
|
|
62
|
+
need the histograms structured.
|
|
63
|
+
|
|
64
|
+
Exit codes: 0 clean; 1 = blind spots disclosed under `unsurveyed:`
|
|
65
|
+
(submodule gitlinks, out-of-root symlinks) — carry them to the gate, the
|
|
66
|
+
human decides; 2 = engine failure — **stop**, a check that never ran is a
|
|
67
|
+
blocking defect, never a silent pass.
|
|
68
|
+
|
|
69
|
+
From the map, prepare the gate material: the per-directory histograms (what
|
|
70
|
+
lives where), the ranked anchor-candidate list (what looks extractable, by
|
|
71
|
+
which kind), and the proposed include/exclude scope over top-level
|
|
72
|
+
directories.
|
|
73
|
+
|
|
74
|
+
**On resume:** always safe to re-run — the map is deterministic and honors
|
|
75
|
+
`survey-scope.yaml` once it exists (`scope (survey-scope.yaml): …` in the
|
|
76
|
+
output confirms the binding).
|
|
77
|
+
|
|
78
|
+
### 2. GATE — one combined scope + taxonomy review (human)
|
|
79
|
+
|
|
80
|
+
**ONE human gate, not two.** Present together, in the conversation — "here
|
|
81
|
+
is how I read your codebase":
|
|
82
|
+
|
|
83
|
+
1. **Scope** — which top-level areas are product surface (include) vs.
|
|
84
|
+
vendored/generated/infra (exclude), plus any `unsurveyed:` blind spots
|
|
85
|
+
the map disclosed. The kit dir itself belongs in the excludes: the map is
|
|
86
|
+
never the territory.
|
|
87
|
+
2. **Taxonomy** — the proposed top-level ontology class spine
|
|
88
|
+
(per-project, derived from the surveyed structure), with an id range per
|
|
89
|
+
class.
|
|
90
|
+
|
|
91
|
+
On confirmation, write both artifacts:
|
|
92
|
+
|
|
93
|
+
- `survey-scope.yaml` at the **repo root** (shape:
|
|
94
|
+
`schemas/survey-scope.schema.json` — `schema-version`, `include` with at
|
|
95
|
+
least one prefix, optional `exclude`; exclude wins; `.` covers root-level
|
|
96
|
+
files only; trailing slashes are normalized away).
|
|
97
|
+
- `ontology/_rules.yaml` — one rule per class with its `id-range`
|
|
98
|
+
(`{ class: 100-…, id-range: [K-100, K-199] }`).
|
|
99
|
+
|
|
100
|
+
Then re-run survey-map and confirm the output header reads
|
|
101
|
+
`scope (survey-scope.yaml): …` — the map is now bounded.
|
|
102
|
+
|
|
103
|
+
This is **the honor-it contract**: every future audit and reflect sweep is
|
|
104
|
+
bounded to this scope and never rescans excluded areas. Widening happens
|
|
105
|
+
via `retrieval-miss` findings through the normal loop — **never by
|
|
106
|
+
re-litigating the gate**. Once `survey-scope.yaml` exists the gate is
|
|
107
|
+
confirmed; on resume it is never re-asked.
|
|
108
|
+
|
|
109
|
+
**On resume:** `survey-scope.yaml` present → skip this step entirely.
|
|
110
|
+
|
|
111
|
+
### 3. EMIT — concepts at their highest checkable rung
|
|
112
|
+
|
|
113
|
+
Walk the in-scope anchor candidates and emit §3.1 concept records into
|
|
114
|
+
`ontology/classes/`, catalog rows into `ontology/_catalog.yaml`. Every
|
|
115
|
+
concept is born knowing its rung — emit at the **highest checkable** one:
|
|
116
|
+
|
|
117
|
+
- **Rung 2 (value agreement)** — a shipped extractor kind fits the anchor:
|
|
118
|
+
emit an `enumerates` descriptor (`kind` / `source` / `values`, plus
|
|
119
|
+
`symbol`/`emit` where the kind needs them). **Read the source file and
|
|
120
|
+
derive the values from it** — never guess from prose; equality is
|
|
121
|
+
byte-exact, case-sensitive, set-based (§3.5), and YAML 1.1 coercion is a
|
|
122
|
+
real trap (quote `on`, `no`, digit-leading keys).
|
|
123
|
+
- **Rung 1 (existence-only)** — no kind fits, or the concept is a grouping:
|
|
124
|
+
a `source-of-truth` pointer and prose, no descriptor. The pointer rule:
|
|
125
|
+
**point at a folder for identity, at a file for facts** — a vertical gets
|
|
126
|
+
its directory (and pair load-bearing folder pointers with the grouping's
|
|
127
|
+
entry file so the existence check has teeth); a value set gets the file
|
|
128
|
+
that declares it.
|
|
129
|
+
- Prose-only concepts carry `last-verified` (rung 4); the reverification
|
|
130
|
+
sweep maintains them.
|
|
131
|
+
|
|
132
|
+
**Deliberately not exhaustive: an ontology born complete is born wrong.**
|
|
133
|
+
Seed the load-bearing concepts — rung-1/2 coverage plus the high-value
|
|
134
|
+
prose concepts; the reverse audit (`engine/audit.js`, advisory) grows the
|
|
135
|
+
map proposal-first from there. Skipping a candidate is a normal triage
|
|
136
|
+
outcome, not a gap.
|
|
137
|
+
|
|
138
|
+
Verify each emitted batch immediately (repo-root `--root`; the
|
|
139
|
+
`--concepts` list is EXACTLY the ids the batch emitted — an id left off the
|
|
140
|
+
list is a check that never ran):
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
node unknown-knowledge/engine/validate.js --concepts K-100,K-110,K-120 --root .
|
|
144
|
+
node unknown-knowledge/engine/validate-values.js --concepts K-100,K-110,K-120 --root .
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Exit 1 = the draft disagrees with the source — fix the draft (re-read the
|
|
148
|
+
file); exit 2 = **stop**. A descriptor that hard-errors as out-of-envelope
|
|
149
|
+
does not get "simplified" until it passes — the anchor goes to MISS.
|
|
150
|
+
|
|
151
|
+
**On resume (idempotent by anchor identity):** before emitting for an
|
|
152
|
+
anchor, reverse-look it up —
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
node unknown-knowledge/engine/resolve.js --paths Sources/Canvas/CanvasTool.swift --root .
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If a concept's pointer already covers the path (folder pointers match
|
|
159
|
+
nested files), the anchor is emitted — skip it, never mint a duplicate
|
|
160
|
+
concept for the same anchor. `no concepts point at this path` means it
|
|
161
|
+
still needs one.
|
|
162
|
+
|
|
163
|
+
### 4. MISS — the anchors no shipped kind can read
|
|
164
|
+
|
|
165
|
+
Anchors with kind-shaped evidence but no shipped kind — a real registry the
|
|
166
|
+
library cannot read (computed arrays, conditional compilation, dynamic
|
|
167
|
+
derivation) — become miss entries, **one fragment each**, via the helper
|
|
168
|
+
(`--date` is injected, never wall-clock; note `--root` is the **kit dir**):
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
node unknown-knowledge/engine/log-entry.js create --log misses --date 2026-07-08 \
|
|
172
|
+
--root unknown-knowledge \
|
|
173
|
+
--entry '{"path":"Sources/Integrations/Providers.swift","shape":"computed Swift array: static let all = core + regional (concatenation, no literal value set); swift-const-array is out of envelope"}'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`shape` carries paths and structure only — never file contents verbatim
|
|
177
|
+
(§3.4). This backlog feeds the governed §5.2 pipeline
|
|
178
|
+
(`protocol/new-kind-pipeline.md`): agents draft parsers there, humans gate
|
|
179
|
+
them, and a kind you author is **never wired into the validator in the same
|
|
180
|
+
session** (D-005). Do not write a bespoke parser during bootstrap.
|
|
181
|
+
|
|
182
|
+
**On resume:** an open miss for the path already IS the demand signal —
|
|
183
|
+
leave it; never mint a sibling (`open → open` is illegal, and the helper
|
|
184
|
+
hard-errors on it).
|
|
185
|
+
|
|
186
|
+
### 5. INTERVIEW — the knowledge-store skeleton (human)
|
|
187
|
+
|
|
188
|
+
The knowledge store's truth anchor is the world, not the code — so its
|
|
189
|
+
spine comes from the **human**, in a structured interview seeded by the
|
|
190
|
+
vocabulary the survey surfaced: which external domains does this product
|
|
191
|
+
answer to (regulation, industry rules, user research…), and what divisions
|
|
192
|
+
matter inside each?
|
|
193
|
+
|
|
194
|
+
Write the skeleton: the domain/division spine plus governance notes into
|
|
195
|
+
`knowledge/_rules.yaml` — **writes are human-only through the kb-build
|
|
196
|
+
skill (the sole write path), and every leaf requires citations; an
|
|
197
|
+
unsourced claim is not promotable** (§3.2). Bootstrap emits the skeleton
|
|
198
|
+
and standing-room structure only; cited leaves land afterwards through
|
|
199
|
+
kb-build's human gate, never in this session.
|
|
200
|
+
|
|
201
|
+
**On resume:** `knowledge/_rules.yaml` already carrying rule items → the
|
|
202
|
+
interview happened; do not re-ask it.
|
|
203
|
+
|
|
204
|
+
### 6. FINISH — green validators, recorded decisions
|
|
205
|
+
|
|
206
|
+
Bootstrap surfaced decisions — the taxonomy acceptance, any scope
|
|
207
|
+
trade-offs. Record them through the §3.5 decisions path: draft entries in
|
|
208
|
+
`decisions/entries/` with provisional date-suffixed ids
|
|
209
|
+
(`D-2026-07-08-<slug>`), `status: proposed`, `relates-to` refs to the
|
|
210
|
+
concepts they touch, plus catalog rows. The steward mints final `D-NNN`s at
|
|
211
|
+
acceptance — never the agent.
|
|
212
|
+
|
|
213
|
+
Then the whole-store gate — the skill declares done **only** when both
|
|
214
|
+
validators run clean, unfiltered:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
node unknown-knowledge/engine/validate.js --root .
|
|
218
|
+
node unknown-knowledge/engine/validate-values.js --root .
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Exit 0 + 0 = done: report the confirmed scope, the class spine, the
|
|
222
|
+
concepts emitted per rung, the misses logged, and the KB skeleton — all of
|
|
223
|
+
it lands through the normal PR gate (agents draft; humans approve). Exit 1
|
|
224
|
+
= fix the store, re-run. Exit 2 = **stop and report**; never declare
|
|
225
|
+
bootstrap done over a check that never ran.
|
|
226
|
+
|
|
227
|
+
**On resume:** an existing proposed bootstrap decision is not re-drafted —
|
|
228
|
+
but the validator run is never skipped: verdicts are per-run (D-011), so a
|
|
229
|
+
resumed session always re-runs both validators before declaring done.
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# /knowledge-reflect — findings consolidation (PRD §8, D-019)
|
|
2
|
+
|
|
3
|
+
> Paths in this document are client-relative — relative to the vendored kit
|
|
4
|
+
> root after init (`ontology/…`, `engine/…`, `protocol/…`). In the kit repo
|
|
5
|
+
> itself these live under `payload/`. Commands are written to run from the
|
|
6
|
+
> **repo root** with the kit dir at its default name `unknown-knowledge/`;
|
|
7
|
+
> substitute your chosen kit dir name if it differs.
|
|
8
|
+
|
|
9
|
+
Sessions append findings; nobody judges them at capture time. This skill is
|
|
10
|
+
the judgment half — human-run, on cadence (weekly; daily at high finding
|
|
11
|
+
volume): read the fragment logs, cluster recurring signals, put a per-item
|
|
12
|
+
recommendation list in front of the human, apply what they approve, close
|
|
13
|
+
the loop with a validator re-run, and prune what never corroborated. You
|
|
14
|
+
operate under `protocol/AGENTS.md` throughout — every gate rule there binds
|
|
15
|
+
here, and its two `--root` conventions apply verbatim (store-reading CLIs
|
|
16
|
+
take the **repo root**; `log-entry.js` takes the **kit dir**).
|
|
17
|
+
|
|
18
|
+
Everything this run produces — applied diffs, transitioned fragments,
|
|
19
|
+
pruned fragments, the stamp — travels together as **one reflect PR**
|
|
20
|
+
(D-010): the improvement loop's own changes pass normal review and CI.
|
|
21
|
+
|
|
22
|
+
## The evidence standard
|
|
23
|
+
|
|
24
|
+
Any gated change requires multiple corroborating findings — **one
|
|
25
|
+
correction is a data point, three are a pattern**. The threshold is three
|
|
26
|
+
distinct fragments — distinct meaning **independent resolution events, not
|
|
27
|
+
files** (defined in full under Minting conduct below; a re-opened entry's
|
|
28
|
+
`occurrences` dates each count, three logs from one session do not).
|
|
29
|
+
Single-occurrence noise never reaches the
|
|
30
|
+
review queue, or the humans stop trusting it and the graduation path dies
|
|
31
|
+
before it starts. Two hard qualifiers:
|
|
32
|
+
|
|
33
|
+
- **A dispute never counts as corroboration** — mutually contradictory
|
|
34
|
+
corrections cancel, they do not add (see Disputed clusters below).
|
|
35
|
+
- Corroboration is per-cluster, never per-log: three findings about three
|
|
36
|
+
different concepts are three data points, not one pattern.
|
|
37
|
+
|
|
38
|
+
The corroboration rule is counted **by hand, here** — the engine never
|
|
39
|
+
counts it. `log-entry.js` appends fragments and transitions them; it has no
|
|
40
|
+
opinion about how many make a pattern, and no CLI reports a corroboration
|
|
41
|
+
score. Reflect is the judgment half, and this threshold is judgment.
|
|
42
|
+
|
|
43
|
+
### Residue and candidate findings — the misses that become edges
|
|
44
|
+
|
|
45
|
+
Sessions append two kinds of finding that exist to be minted from
|
|
46
|
+
(UCS-1160), both through `log-entry.js` like every other fragment:
|
|
47
|
+
|
|
48
|
+
- **Residue** — from `resolve`'s `decomposition.residue`: the non-stopword
|
|
49
|
+
tokens no join consumed. Each fragment carries `resolved-context`, the
|
|
50
|
+
operations, concept ids, and jurisdictions that *did* resolve in the same
|
|
51
|
+
ask. A bare unresolved token is a finding nobody can act on; `stencil`
|
|
52
|
+
unresolved in an ask that resolved `add-tool` and `eu-eaa` localizes
|
|
53
|
+
the gap precisely enough that the minting decision writes itself.
|
|
54
|
+
- **Document candidates** — from `resolve --doc`'s ranked
|
|
55
|
+
`candidates-ranked`: the document's own residue. Each fragment adds a
|
|
56
|
+
`section` locator (document path, heading address, line or page), so
|
|
57
|
+
clustering opens the section just-in-time instead of re-reading the
|
|
58
|
+
document.
|
|
59
|
+
|
|
60
|
+
Cluster these by their `residue` terms, and read `resolved-context` (and,
|
|
61
|
+
for candidates, the located section) as the cluster's evidence. Zero
|
|
62
|
+
resolution is a normal outcome, not a miss — `resolve` says so in its own
|
|
63
|
+
payload; append a residue finding only when the topic plausibly should be
|
|
64
|
+
mapped.
|
|
65
|
+
|
|
66
|
+
## Minting conduct — how a miss becomes a deterministic edge
|
|
67
|
+
|
|
68
|
+
A corroborated residue cluster is evidence the store has no word for
|
|
69
|
+
something the material keeps naming. Minting that word is the loop's whole
|
|
70
|
+
point, and it is a governed act. Four vocabularies can be minted from
|
|
71
|
+
reflect: **terms**, **aliases**, **operations**, and **domain classes**.
|
|
72
|
+
|
|
73
|
+
### What "three distinct fragments" means
|
|
74
|
+
|
|
75
|
+
The evidence standard counts **independent resolution events, not files.**
|
|
76
|
+
Three fragments are distinct when each records a *separate occasion on which
|
|
77
|
+
the store failed to resolve the thing* — which in practice means a different
|
|
78
|
+
session, or the same session on a different date.
|
|
79
|
+
|
|
80
|
+
The case this rules out: one session that hit `stencil` three times in a
|
|
81
|
+
row and logged three fragments. That is **one** data point wearing three
|
|
82
|
+
filenames. Nothing was independently corroborated — the same agent, the same
|
|
83
|
+
ask, the same unresolved token — and minting from it would let a single
|
|
84
|
+
session vote three times. Cluster them as one.
|
|
85
|
+
|
|
86
|
+
The case it admits: a re-opened entry. Each date in `occurrences` is a
|
|
87
|
+
genuinely separate occasion (the issue fired again, later, after someone
|
|
88
|
+
thought it was closed), so each counts. Same for the same term surfacing as
|
|
89
|
+
query residue in one session and as a document candidate in another — two
|
|
90
|
+
occasions, two data points.
|
|
91
|
+
|
|
92
|
+
When in doubt, ask what the fragment is evidence *of*. A file is evidence
|
|
93
|
+
that someone pressed enter; an occasion is evidence that the store has a
|
|
94
|
+
hole. The threshold counts holes.
|
|
95
|
+
|
|
96
|
+
Three rules bind every one of them:
|
|
97
|
+
|
|
98
|
+
1. **Literary warrant, always.** A value is minted only when material
|
|
99
|
+
exists to fill it. Corroboration says the word keeps coming up; warrant
|
|
100
|
+
says there is something for it to hold. Both, or neither — a term minted
|
|
101
|
+
on three findings with no material behind it is speculative shelving
|
|
102
|
+
wearing evidence. Read the source before proposing: a candidate is a
|
|
103
|
+
claim about the map until someone opens the document its `section`
|
|
104
|
+
locator addresses.
|
|
105
|
+
2. **Evidence attached.** The proposal names the corroborating fragment
|
|
106
|
+
paths verbatim, exactly as every other recommendation item does. A mint
|
|
107
|
+
proposal without its findings attached is not reviewable and does not go
|
|
108
|
+
on the list.
|
|
109
|
+
3. **One Decisions entry per minting.** Every minted value — each domain
|
|
110
|
+
segment, each alias, each operation — carries its own entry recording
|
|
111
|
+
the warrant and the evidence. Draft it from
|
|
112
|
+
`templates/decisions/reflect-mint-proposal.yaml`; its `id` and `date`
|
|
113
|
+
are deliberately invalid placeholders, so a proposal pasted unedited
|
|
114
|
+
fails validation rather than reaching the Decisions store with a
|
|
115
|
+
rationale nobody wrote. A suppression uses the same shape and the same
|
|
116
|
+
entry: a refused term stays listed with `status: suppressed` so the next
|
|
117
|
+
cycle that clusters the same residue can see it was already considered.
|
|
118
|
+
|
|
119
|
+
Minting is a `mint-proposal` item at the GATE like any other item —
|
|
120
|
+
proposal-first, agents draft and humans approve. Reflect never edits a
|
|
121
|
+
registry ahead of its approval, and never mints a child path segment whose
|
|
122
|
+
parent is unminted.
|
|
123
|
+
|
|
124
|
+
## Resumable by construction
|
|
125
|
+
|
|
126
|
+
A dead session costs the remaining steps, never a restart. **On entry,
|
|
127
|
+
detect existing artifacts and resume from the first incomplete step** —
|
|
128
|
+
each step below also carries its own "On resume" rule:
|
|
129
|
+
|
|
130
|
+
| Artifact found on entry | What it means |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `logs/last-reflect.yaml` | prior cycles ran — read `cycles:` for archival counting (STAMP); this run appends its date, never rewrites history |
|
|
133
|
+
| Fragments at `status: proposed` | a prior reflect died between RECOMMEND and APPLY: those items are already on a recommendation list — re-present them at the gate as-is, never re-cluster them into new items |
|
|
134
|
+
| A store diff already applied but its justifying findings still `proposed` | the close-the-loop re-run never happened — run the filtered validators now; a check that never ran is a blocking defect |
|
|
135
|
+
| A `resolved`/`rejected` fragment whose issue fired again | **re-open, not duplicate**: transition the original back to `open`, never mint a sibling |
|
|
136
|
+
|
|
137
|
+
## The six steps
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
1. SWEEP read-only: inventory open/proposed fragments in logs/
|
|
141
|
+
2. CLUSTER group by concept/path/trigger; flag disputed clusters
|
|
142
|
+
3. RECOMMEND evidence-gated per-item list, justifying findings attached
|
|
143
|
+
4. GATE human approves/rejects PER ITEM — never in bulk
|
|
144
|
+
5. APPLY approved diffs + filtered validator re-run close the loop
|
|
145
|
+
6. STAMP prune uncorroborated-after-N; write logs/last-reflect.yaml
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 1. SWEEP — inventory the queue, read-only
|
|
149
|
+
|
|
150
|
+
Read every `open` and `proposed` fragment under `logs/findings/` (and the
|
|
151
|
+
sibling logs — `logs/misses/`, `logs/gaps/` — same lifecycle, same
|
|
152
|
+
machinery). Fragments are one-file-per-entry and small: grep is free,
|
|
153
|
+
reading a fragment is cheap, and the fragment IS the entry — there is no
|
|
154
|
+
index to consult. `resolved`/`rejected` fragments are swept only to catch
|
|
155
|
+
recurrences (re-open, not duplicate).
|
|
156
|
+
|
|
157
|
+
The sweep is bounded by `survey-scope.yaml` — the honor-it contract from
|
|
158
|
+
bootstrap. Findings pointing outside the confirmed scope are widening
|
|
159
|
+
signals (`scope-widen` items, below), **never** cause to re-litigate the
|
|
160
|
+
gate or rescan excluded areas.
|
|
161
|
+
|
|
162
|
+
**On resume:** always safe to re-run — the sweep writes nothing.
|
|
163
|
+
|
|
164
|
+
### 2. CLUSTER — group signals, flag disputes
|
|
165
|
+
|
|
166
|
+
Group the swept fragments into clusters by, in order of preference: the
|
|
167
|
+
`consulted:` concept refs, the file paths named in `summary`, then the
|
|
168
|
+
trigger kind. A path-only fragment joins a concept cluster via the reverse
|
|
169
|
+
lookup:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
node unknown-knowledge/engine/resolve.js --paths Sources/Canvas/CanvasTool.swift --root .
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Completion criterion: **every swept open fragment is in exactly one
|
|
176
|
+
cluster** — a fragment that fits nowhere is its own cluster of one (that is
|
|
177
|
+
what uncorroborated means), never silently dropped.
|
|
178
|
+
|
|
179
|
+
While clustering, flag every cluster whose corrections **mutually
|
|
180
|
+
contradict** (two findings asserting opposite facts about the same claim)
|
|
181
|
+
as `disputed` — a cluster flag for this run, never a fragment status. A
|
|
182
|
+
disputed cluster does not proceed to RECOMMEND on its correction count;
|
|
183
|
+
it takes the Disputed-clusters procedure (below) first.
|
|
184
|
+
|
|
185
|
+
**On resume:** re-cluster from the current fragments — clustering is
|
|
186
|
+
derived, never stored; `proposed` fragments keep their prior item
|
|
187
|
+
membership (see the resume table).
|
|
188
|
+
|
|
189
|
+
### 3. RECOMMEND — the evidence-gated list
|
|
190
|
+
|
|
191
|
+
Build the recommendation list. One item per cluster that **meets the
|
|
192
|
+
evidence standard**; each item carries:
|
|
193
|
+
|
|
194
|
+
- **category** — one of the closed change-category vocabulary (additive,
|
|
195
|
+
§3.5): `concept-fix`, `alias-addition`, `ssot-repoint`, `scope-widen`,
|
|
196
|
+
`knowledge-promotion`, `extractor-draft`, `mint-proposal`. Categories are what approval
|
|
197
|
+
outcomes are recorded against (STAMP) and what trust graduation is
|
|
198
|
+
measured per — a miscategorized item corrupts the graduation signal.
|
|
199
|
+
- **the concrete diff** — the exact store change proposed (fix a concept's
|
|
200
|
+
descriptor, add an alias, repoint an SSOT, widen `survey-scope.yaml`,
|
|
201
|
+
promote a finding to knowledge, draft an extractor). Draft it from the
|
|
202
|
+
**source artifact, never from the findings' prose** — the map is never
|
|
203
|
+
the fact, and a finding is a claim about the map. Follow the concept's
|
|
204
|
+
pointer and read the file before writing the diff.
|
|
205
|
+
- **the justifying findings** — the cluster's fragment paths, verbatim.
|
|
206
|
+
An item without its evidence attached is not reviewable and does not go
|
|
207
|
+
on the list.
|
|
208
|
+
|
|
209
|
+
Two categories recommend a *handoff*, never a direct diff:
|
|
210
|
+
`knowledge-promotion` items point into the kb-build skill (the sole
|
|
211
|
+
knowledge write path — reflect never writes a leaf); `extractor-draft`
|
|
212
|
+
items point into `protocol/new-kind-pipeline.md` (D-005 — a parser is
|
|
213
|
+
never drafted and wired in the same session, and never by reflect).
|
|
214
|
+
|
|
215
|
+
Clusters below the threshold get **no item**: they stay `open` and age
|
|
216
|
+
(STAMP counts their cycles). Completion criterion: every cluster is either
|
|
217
|
+
on the list, explicitly held as under-corroborated, or flagged disputed —
|
|
218
|
+
none unaccounted for.
|
|
219
|
+
|
|
220
|
+
**On resume:** items whose fragments are already `proposed` are re-presented
|
|
221
|
+
as-is; only clusters never yet listed get new items.
|
|
222
|
+
|
|
223
|
+
### 4. GATE — per-item human approval
|
|
224
|
+
|
|
225
|
+
**The moderator's interface is the reflect queue, not the store.** A human
|
|
226
|
+
governing this system reviews what reflect puts in front of them; they do
|
|
227
|
+
not browse `knowledge/` or `ontology/` looking for things to fix. Browsing
|
|
228
|
+
a store is unbounded and finds whatever the eye lands on, while the queue
|
|
229
|
+
is bounded, evidenced, and complete — every item carries its justifying
|
|
230
|
+
findings, and every swept fragment is accounted for. The queue has exactly
|
|
231
|
+
four sections, presented in this order:
|
|
232
|
+
|
|
233
|
+
| Section | What it holds |
|
|
234
|
+
|---|---|
|
|
235
|
+
| **Mint proposals** | `mint-proposal` items — the proposed value, its literary warrant, and the corroborating fragments, one draft Decisions entry each |
|
|
236
|
+
| **Corroborated findings** | every other item that met the evidence standard, with its concrete diff and its justifying fragment paths |
|
|
237
|
+
| **Drafts awaiting promotion** | handoff items (`knowledge-promotion`, `extractor-draft`) — drafted here, written elsewhere; reflect reports them as handed off, never writes them |
|
|
238
|
+
| **Sampled spot-checks** | a sample of what reflect did NOT raise — under-corroborated clusters and fragments due to age out — so the moderator can audit the threshold itself rather than only the items that cleared it |
|
|
239
|
+
|
|
240
|
+
The spot-check sample is what keeps the queue honest: without it the human
|
|
241
|
+
only ever sees what the evidence standard admitted, and a threshold nobody
|
|
242
|
+
audits is a threshold nobody can tune. Present the sample as
|
|
243
|
+
under-corroborated, explicitly — it is context for judging the queue, never
|
|
244
|
+
a recommendation, and approving one does not bypass the standard.
|
|
245
|
+
|
|
246
|
+
Present the list in the conversation and transition each listed item's
|
|
247
|
+
justifying findings `open → proposed` — entering the review queue IS the
|
|
248
|
+
proposal:
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
node unknown-knowledge/engine/log-entry.js transition --file logs/findings/2026-07-01-00000001.yaml \
|
|
252
|
+
--to proposed --date 2026-07-09 --root unknown-knowledge
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The human decides **per item — approve / approve-with-modification /
|
|
256
|
+
reject — never as a bulk yes**. Record each outcome (it feeds the STAMP).
|
|
257
|
+
For every rejection, capture the human's reason and transition the item's
|
|
258
|
+
findings immediately — the helper refuses a reasonless rejection:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
node unknown-knowledge/engine/log-entry.js transition --file logs/findings/2026-07-04-00000005.yaml \
|
|
262
|
+
--to rejected --date 2026-07-09 --reason "steward: intended behavior, store is right" --root unknown-knowledge
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Nothing is applied before its item is approved — proposal-first, agents
|
|
266
|
+
draft and humans approve. Completion criterion: every listed item has a
|
|
267
|
+
recorded outcome and every rejected item's findings are `rejected` with
|
|
268
|
+
the reason.
|
|
269
|
+
|
|
270
|
+
**On resume:** an item already approved but not applied goes straight to
|
|
271
|
+
APPLY; never re-ask a recorded outcome.
|
|
272
|
+
|
|
273
|
+
### 5. APPLY — approved diffs, then close the loop
|
|
274
|
+
|
|
275
|
+
Apply each approved diff (as modified, if approve-with-modification), then
|
|
276
|
+
re-run **both validators filtered to exactly the concepts the diff
|
|
277
|
+
touched** — an id left off the list is a check that never ran:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
node unknown-knowledge/engine/validate.js --concepts K-110 --root .
|
|
281
|
+
node unknown-knowledge/engine/validate-values.js --concepts K-110 --root .
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- **Exit 0 + 0** — the loop is closed: transition the item's findings
|
|
285
|
+
`proposed → resolved` (the helper stamps `verified` with the run date).
|
|
286
|
+
A finding is never resolved ahead of the green re-run — green first,
|
|
287
|
+
then the transition.
|
|
288
|
+
- **Exit 1** — the applied diff disagrees with the source: re-read the
|
|
289
|
+
source and fix the diff, then re-run. If it cannot be made green this
|
|
290
|
+
session, revert the diff and return the item to the queue with the
|
|
291
|
+
failure on record: `--to rejected --reason "re-validation failed: …"`,
|
|
292
|
+
then `--to open` (re-open, not duplicate — the signal is not lost, the
|
|
293
|
+
next cycle sees it with its history).
|
|
294
|
+
- **Exit 2** — **stop.** A check that never ran is a blocking defect,
|
|
295
|
+
never a silent pass; no finding transitions to `resolved` over it.
|
|
296
|
+
|
|
297
|
+
Handoff categories (`knowledge-promotion`, `extractor-draft`) have no diff
|
|
298
|
+
to apply here: their findings stay `proposed` and resolve when the
|
|
299
|
+
downstream gate (kb-build / new-kind pipeline) lands — reflect reports
|
|
300
|
+
them as handed off.
|
|
301
|
+
|
|
302
|
+
Completion criterion: every approved item is either resolved over a green
|
|
303
|
+
filtered re-run, reverted-and-re-opened with the failure recorded, or
|
|
304
|
+
handed off — and no fragment was ever edited by hand (`log-entry.js` is
|
|
305
|
+
the only write path into `logs/`).
|
|
306
|
+
|
|
307
|
+
**On resume:** per the resume table — an applied diff whose findings are
|
|
308
|
+
still `proposed` gets its filtered re-run now, before anything else.
|
|
309
|
+
|
|
310
|
+
### 6. STAMP — prune, then make the cycle observable
|
|
311
|
+
|
|
312
|
+
First the hygiene prune (Archival mechanics below): every `open` fragment
|
|
313
|
+
still uncorroborated after **N reflect cycles** (default **N = 3** — this
|
|
314
|
+
file is client-owned protocol markdown; tune N by editing it here) is
|
|
315
|
+
archived — the fragment file is deleted in the reflect PR and a rollup
|
|
316
|
+
line records it in the stamp. Completion criterion: every open fragment
|
|
317
|
+
was either kept (with its cycle count still below N) or archived with a
|
|
318
|
+
rollup line — none skipped.
|
|
319
|
+
|
|
320
|
+
Then write the stamp — `logs/last-reflect.yaml` in the kit dir, plain
|
|
321
|
+
engine-readable YAML (the knowledge-audit heartbeat reads it for
|
|
322
|
+
days-since-last-reflect; the trust-graduation trigger reads the per-category
|
|
323
|
+
outcomes — this stamp is the only place either is observable):
|
|
324
|
+
|
|
325
|
+
```yaml
|
|
326
|
+
schema-version: 1
|
|
327
|
+
date: 2026-07-09 # this run — heartbeat: days-since-last-reflect
|
|
328
|
+
cycles: [2026-06-25, 2026-07-02, 2026-07-09] # every run, appended
|
|
329
|
+
outcomes: # per-item approval outcome BY CATEGORY, this run
|
|
330
|
+
concept-fix: { approved: 1, approved-with-modification: 0, rejected: 0 }
|
|
331
|
+
ssot-repoint: { approved: 0, approved-with-modification: 0, rejected: 1 }
|
|
332
|
+
archived: # the rollup note for this run's prune
|
|
333
|
+
- file: logs/findings/2026-04-02-9c11d0aa.yaml
|
|
334
|
+
summary: "retrieval-struggle: K-130 alias missing"
|
|
335
|
+
reason: uncorroborated after 3 reflect cycles
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The stamp is reflect output, not a log fragment — it is the one file this
|
|
339
|
+
skill writes directly (never via `log-entry.js`, and never by another
|
|
340
|
+
skill). Append to `cycles:` and replace `date:`/`outcomes:`/`archived:`
|
|
341
|
+
with this run's values; prior cycles' dates are history, never rewritten.
|
|
342
|
+
|
|
343
|
+
Reflect declares done only when: every gate outcome is recorded in
|
|
344
|
+
`outcomes:`, every close-the-loop re-run was green (or its item
|
|
345
|
+
reverted/handed off), the stamp is written, and the whole bundle is on the
|
|
346
|
+
reflect PR. Then report: clusters formed, items recommended, per-category
|
|
347
|
+
outcomes, fragments resolved/rejected/re-opened/archived.
|
|
348
|
+
|
|
349
|
+
**On resume:** if fragments transitioned this cycle but no stamp carries
|
|
350
|
+
today's date, the cycle is unfinished — the prune and the stamp still
|
|
351
|
+
count as steps; a reflect that mutated the queue but never stamped is
|
|
352
|
+
invisible to the heartbeat.
|
|
353
|
+
|
|
354
|
+
## Disputed clusters — resolve by reading the SSOT
|
|
355
|
+
|
|
356
|
+
When a cluster's corrections mutually contradict (flagged in CLUSTER):
|
|
357
|
+
|
|
358
|
+
1. **Read the SSOT** — follow the concept's `source-of-truth` pointer and
|
|
359
|
+
read the file; the map is never the fact, and neither is either finding.
|
|
360
|
+
Cite what you read (path and line) — the citation is the resolution's
|
|
361
|
+
evidence.
|
|
362
|
+
2. Where the descriptor is machine-checkable, let the engine confirm the
|
|
363
|
+
read: `validate.js` / `validate-values.js` filtered to the concept.
|
|
364
|
+
3. Transition each finding on the side the SSOT **contradicts**:
|
|
365
|
+
`open → proposed`, then `--to rejected --reason` citing the SSOT read
|
|
366
|
+
(path, line, what it declares).
|
|
367
|
+
4. The side the SSOT **supports**: if the store already agrees with the
|
|
368
|
+
source, the finding resolves over the green filtered re-run (step 2);
|
|
369
|
+
if the store is wrong, the surviving findings re-enter CLUSTER as an
|
|
370
|
+
ordinary cluster — which must meet the evidence standard **on its own
|
|
371
|
+
count**: a dispute never counts as corroboration, so the contradicted
|
|
372
|
+
exchange adds nothing.
|
|
373
|
+
5. If the SSOT itself is ambiguous (the pointer is stale, the file does
|
|
374
|
+
not decide it), the cluster goes to the GATE as a flagged question for
|
|
375
|
+
the human — never as a recommendation, and never silently dropped.
|
|
376
|
+
|
|
377
|
+
## Archival mechanics — uncorroborated `open` findings
|
|
378
|
+
|
|
379
|
+
Unbounded open fragments drown reflect by month ten; the prune keeps the
|
|
380
|
+
queue trustworthy. An `open` fragment is **archived** when at least N
|
|
381
|
+
stamped cycle dates in `logs/last-reflect.yaml` postdate its `date` (or
|
|
382
|
+
its latest `occurrences` entry, if re-opened) and its cluster never met
|
|
383
|
+
the evidence standard:
|
|
384
|
+
|
|
385
|
+
- **Delete the fragment file** in the reflect PR — git history preserves
|
|
386
|
+
it; the deletion is reviewable like any other change. This prune is the
|
|
387
|
+
one sanctioned deletion in `logs/` (the AGENTS.md rule against deleting
|
|
388
|
+
findings guards gate-bypass, not consolidation) — it happens only here,
|
|
389
|
+
only in a reflect PR, only with a rollup line.
|
|
390
|
+
- **Record the rollup line** under `archived:` in the stamp: fragment
|
|
391
|
+
path, one-line summary, `uncorroborated after N reflect cycles`.
|
|
392
|
+
- `archived` is **not a status** — `log-entry.js` has no such transition
|
|
393
|
+
and hard-errors on it; never try to transition a fragment there.
|
|
394
|
+
|
|
395
|
+
If an archived signal was real, it will fire again — the new fragment
|
|
396
|
+
starts a fresh cluster with a fresh count, and the rollup note in git
|
|
397
|
+
history is the paper trail that it aged out once before.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:unknown-knowledge:schema:catalog",
|
|
4
|
+
"title": "Store catalog (_catalog.yaml)",
|
|
5
|
+
"description": "The navigational entry point every store shares: _catalog.yaml → _rules.yaml → class files / tree leaves (PRD §3). The map is never the fact — catalogs point at files, they never embed record content. Entry ids follow the owning store's id grammar (K-NNN, notation, D-NNN), so they are plain strings here; id shape and file resolution are structural-validator checks (KK-05). Schema evolution is additive-only (§3.5, D-013).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schema-version", "store", "entries"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema-version": { "type": "integer", "minimum": 1 },
|
|
11
|
+
"store": { "enum": ["ontology", "knowledge", "decisions"] },
|
|
12
|
+
"entries": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": { "$ref": "#/$defs/catalogEntry" }
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"$defs": {
|
|
18
|
+
"catalogEntry": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"required": ["id", "title", "file"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"id": { "type": "string" },
|
|
24
|
+
"title": { "type": "string" },
|
|
25
|
+
"file": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "Path relative to the store root, or a documented pending marker while the record is being imported."
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|