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,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform wrapper generation (KK-18, PRD §6/§9.2) — the second half of the
|
|
3
|
+
* init copy layer: thin pointer files at each selected agent platform's
|
|
4
|
+
* conventional path, aiming the platform at <root>/protocol/AGENTS.md. Like
|
|
5
|
+
* copy-payload.js this is the ENGINE only; the multi-select prompt is
|
|
6
|
+
* KK-19's, callers pass the chosen platform ids.
|
|
7
|
+
*
|
|
8
|
+
* The registry is DATA, not code: the `platforms:` section of
|
|
9
|
+
* cli/kit.manifest.yaml (id → { name, template, target, mode }). Adding a
|
|
10
|
+
* platform later = adding a manifest entry (+ a template under
|
|
11
|
+
* payload/wrappers/ if the generic pointer doesn't fit). Templates live in
|
|
12
|
+
* payload/ under the same D-007 constructional guards as copy sources;
|
|
13
|
+
* targets are CLIENT-REPO-ROOT-relative conventional paths (dotted dirs
|
|
14
|
+
* allowed — the §6 never-dotted rule governs the seeded root only).
|
|
15
|
+
* Wrappers duplicate nothing: protocol/AGENTS.md stays the single source of
|
|
16
|
+
* truth; a wrapper is a few pointer lines rendered from its template with
|
|
17
|
+
* `{{root}}` replaced by the seeded root name.
|
|
18
|
+
*
|
|
19
|
+
* Collision policy (§6), per the registry's `mode`:
|
|
20
|
+
* shared — ecosystem-shared instruction files (root AGENTS.md,
|
|
21
|
+
* .github/copilot-instructions.md). Fresh file → created
|
|
22
|
+
* holding just the sentinel block. Existing file without
|
|
23
|
+
* sentinels → APPENDED between sentinel markers, existing
|
|
24
|
+
* content byte-preserved. Existing well-formed sentinel block
|
|
25
|
+
* → content REPLACED WITHIN the sentinels (the idempotent
|
|
26
|
+
* choice: re-generation converges instead of refusing, and a
|
|
27
|
+
* root rename updates the pointer in place). Malformed
|
|
28
|
+
* sentinels (unbalanced/reversed/multiple) → skip-and-report,
|
|
29
|
+
* never guess.
|
|
30
|
+
* dedicated — single-tool files (CLAUDE.md, GEMINI.md, .cursor rule).
|
|
31
|
+
* Created if absent; an existing file is the user's own —
|
|
32
|
+
* skip-and-report, never clobbered.
|
|
33
|
+
* Symlinked targets are skipped, never written through (D-007 posture).
|
|
34
|
+
*
|
|
35
|
+
* Deterministic by construction: pure render of template x root name,
|
|
36
|
+
* platforms processed sorted, no wall-clock reads. Skips are REPORTED
|
|
37
|
+
* results, not errors — a partial wrapper set never fails the seed.
|
|
38
|
+
*/
|
|
39
|
+
import { lstatSync, mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
40
|
+
import { dirname, join, resolve } from 'node:path';
|
|
41
|
+
import { DEFAULT_ROOT, loadManifest, validateRootName } from './copy-payload.js';
|
|
42
|
+
|
|
43
|
+
export const SENTINEL_BEGIN = '<!-- unknown-knowledge:begin -->';
|
|
44
|
+
export const SENTINEL_END = '<!-- unknown-knowledge:end -->';
|
|
45
|
+
|
|
46
|
+
/** Refuse unknown platform ids against the manifest registry (pre-seed check). */
|
|
47
|
+
export function assertKnownPlatforms(manifest, ids) {
|
|
48
|
+
const known = Object.keys(manifest.platforms).sort();
|
|
49
|
+
for (const id of ids) {
|
|
50
|
+
if (!known.includes(id)) {
|
|
51
|
+
throw new Error(`unknown platform ${JSON.stringify(id)} — manifest defines: ${known.join(', ') || '(none)'}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Pure template render: {{root}} → seeded root name; leftovers are a template bug. */
|
|
57
|
+
function renderTemplate(text, rootName, templateRel) {
|
|
58
|
+
const out = text.replaceAll('{{root}}', rootName);
|
|
59
|
+
const leftover = out.match(/\{\{[a-z0-9-]+\}\}/);
|
|
60
|
+
if (leftover) throw new Error(`wrapper template ${templateRel}: unresolved placeholder ${leftover[0]}`);
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function sentinelBlock(body) {
|
|
65
|
+
return `${SENTINEL_BEGIN}\n${body.trimEnd()}\n${SENTINEL_END}\n`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** lstat that treats absence as null (a dangling symlink still counts as present). */
|
|
69
|
+
function lstatOrNull(path) {
|
|
70
|
+
try {
|
|
71
|
+
return lstatSync(path);
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const countOf = (text, needle) => text.split(needle).length - 1;
|
|
78
|
+
|
|
79
|
+
/** §6 shared-file policy: sentinel-append / replace-within-sentinels, never clobber. */
|
|
80
|
+
function writeShared(targetAbs, body) {
|
|
81
|
+
const block = sentinelBlock(body);
|
|
82
|
+
const stat = lstatOrNull(targetAbs);
|
|
83
|
+
if (stat === null) {
|
|
84
|
+
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
85
|
+
writeFileSync(targetAbs, block);
|
|
86
|
+
return { action: 'created' };
|
|
87
|
+
}
|
|
88
|
+
if (stat.isSymbolicLink()) {
|
|
89
|
+
return { action: 'skipped', reason: 'target is a symlink — wrappers are never written through links' };
|
|
90
|
+
}
|
|
91
|
+
const text = readFileSync(targetAbs, 'utf8');
|
|
92
|
+
const begins = countOf(text, SENTINEL_BEGIN);
|
|
93
|
+
const ends = countOf(text, SENTINEL_END);
|
|
94
|
+
if (begins === 0 && ends === 0) {
|
|
95
|
+
const sep = text.length === 0 ? '' : text.endsWith('\n') ? '\n' : '\n\n';
|
|
96
|
+
writeFileSync(targetAbs, `${text}${sep}${block}`);
|
|
97
|
+
return { action: 'appended' };
|
|
98
|
+
}
|
|
99
|
+
if (begins === 1 && ends === 1 && text.indexOf(SENTINEL_BEGIN) < text.indexOf(SENTINEL_END)) {
|
|
100
|
+
const start = text.indexOf(SENTINEL_BEGIN);
|
|
101
|
+
let after = text.indexOf(SENTINEL_END) + SENTINEL_END.length;
|
|
102
|
+
if (text[after] === '\n') after += 1; // the block carries its own trailing newline
|
|
103
|
+
writeFileSync(targetAbs, text.slice(0, start) + block + text.slice(after));
|
|
104
|
+
return { action: 'replaced' };
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
action: 'skipped',
|
|
108
|
+
reason: `existing sentinel markers are malformed (expected exactly one ${SENTINEL_BEGIN} before one ${SENTINEL_END}) — resolve the file by hand, then re-add the pointer`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** §6 dedicated-file policy: create if absent; an existing file is never touched. */
|
|
113
|
+
function writeDedicated(targetAbs, body, rootName) {
|
|
114
|
+
if (lstatOrNull(targetAbs) !== null) {
|
|
115
|
+
return {
|
|
116
|
+
action: 'skipped',
|
|
117
|
+
reason: `already exists — dedicated wrapper targets are never overwritten (§6); add the pointer yourself: read ${rootName}/protocol/AGENTS.md before working`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
121
|
+
writeFileSync(targetAbs, body);
|
|
122
|
+
return { action: 'created' };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Generate wrappers for the selected platforms into targetDir (the client
|
|
127
|
+
* repo root — wrapper targets are root-relative conventional paths, NOT
|
|
128
|
+
* inside the seeded kit dir).
|
|
129
|
+
*
|
|
130
|
+
* @param {object} options
|
|
131
|
+
* @param {string} options.kitRoot kit repo root (holds payload/ + cli/)
|
|
132
|
+
* @param {string} options.targetDir client repo root receiving the wrappers
|
|
133
|
+
* @param {string} [options.rootName] seeded kit dir name the pointers cite
|
|
134
|
+
* @param {string[]} [options.platforms] selected registry ids
|
|
135
|
+
* @param {string} [options.manifestPath] override, for tests
|
|
136
|
+
* @returns {Array<{ platform: string, name: string, target: string, mode: string,
|
|
137
|
+
* action: 'created'|'appended'|'replaced'|'skipped', reason?: string }>}
|
|
138
|
+
*/
|
|
139
|
+
export function generateWrappers({ kitRoot, targetDir, rootName = DEFAULT_ROOT, platforms = [], manifestPath }) {
|
|
140
|
+
validateRootName(rootName);
|
|
141
|
+
const manifest = loadManifest(kitRoot, manifestPath);
|
|
142
|
+
assertKnownPlatforms(manifest, platforms);
|
|
143
|
+
if (!existsSync(resolve(targetDir))) {
|
|
144
|
+
throw new Error(`target dir ${resolve(targetDir)} does not exist`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const results = [];
|
|
148
|
+
for (const id of [...new Set(platforms)].sort()) {
|
|
149
|
+
const spec = manifest.platforms[id];
|
|
150
|
+
const templateAbs = resolve(manifest.payloadRoot, spec.template);
|
|
151
|
+
if (!existsSync(templateAbs)) {
|
|
152
|
+
throw new Error(`platforms.${id}: template ${spec.template} missing from payload/ — the registry and the payload tree have drifted`);
|
|
153
|
+
}
|
|
154
|
+
const body = renderTemplate(readFileSync(templateAbs, 'utf8'), rootName, spec.template);
|
|
155
|
+
const targetAbs = join(resolve(targetDir), spec.target);
|
|
156
|
+
const outcome = spec.mode === 'shared'
|
|
157
|
+
? writeShared(targetAbs, body)
|
|
158
|
+
: writeDedicated(targetAbs, body, rootName);
|
|
159
|
+
results.push({ platform: id, name: spec.name, target: spec.target, mode: spec.mode, ...outcome });
|
|
160
|
+
}
|
|
161
|
+
return results;
|
|
162
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "unknown-knowledge",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Free OSS kit that stands up self-improving knowledge-base + ontology structures in any codebase: three governed YAML stores, a deterministic engine, and an agent protocol.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/doterodesign/unknown-knowledge.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/doterodesign/unknown-knowledge/issues"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/doterodesign/unknown-knowledge#readme",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"bin": {
|
|
16
|
+
"unknown-knowledge": "cli/init.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"cli/",
|
|
20
|
+
"payload/",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"NOTICE",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=22.0.0"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"test": "node --test \"tests/**/*.test.js\"",
|
|
30
|
+
"lint": "node scripts/lint.js",
|
|
31
|
+
"acceptance": "node acceptance/run.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"js-yaml": "^5.4.1"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# adapter-fixtures — the sample/expected pairs for format adapters
|
|
2
|
+
|
|
3
|
+
One directory per format, each carrying a `sample.<ext>` document and the
|
|
4
|
+
`EXPECTED.yaml` intermediate representation the adapter must produce from it.
|
|
5
|
+
The shape is deliberately IDENTICAL to the extractor-kind pairs — sample plus
|
|
6
|
+
expectation, pinned by kit CI — because these fixtures do the same double
|
|
7
|
+
duty: they are the runnable gate, and they are the authoring template a client
|
|
8
|
+
imitates when drafting an adapter for a format the kit does not ship (D-005:
|
|
9
|
+
only vendored, versioned, test-covered code ever runs).
|
|
10
|
+
|
|
11
|
+
Every sample is adversarial-but-adaptable on purpose: reflowed paragraphs,
|
|
12
|
+
code whose indentation is content, entities, nested block elements, PDF
|
|
13
|
+
kerning arrays and escapes. Gnarly input that stays INSIDE the envelope.
|
|
14
|
+
Out-of-envelope shapes (a `.docx` submission, an encrypted PDF, a scanned page
|
|
15
|
+
with no text) are NOT here: those hard-error by design, so there is no IR to
|
|
16
|
+
expect from them.
|
|
17
|
+
|
|
18
|
+
`EXPECTED.yaml` fields: `format` + `file` + `adapter` (the versioned name, e.g.
|
|
19
|
+
`md@1`) + `hash` (FNV-1a over the sample's bytes) + `blocks`. Each block is
|
|
20
|
+
`kind` + `text` + `locator`, plus `level` on headings.
|
|
21
|
+
|
|
22
|
+
**Order is contract.** Extractor pairs compare value SETS (§3.5, order is
|
|
23
|
+
presentation); adapter pairs compare an ORDERED SEQUENCE, because the IR
|
|
24
|
+
preserves document order and everything downstream reads it that way.
|
|
25
|
+
|
|
26
|
+
**Locators** are per-format, and each is deterministic:
|
|
27
|
+
|
|
28
|
+
| format | locator | meaning |
|
|
29
|
+
|--------|---------|---------|
|
|
30
|
+
| md, txt, html | `{ line, endLine }` | 1-based inclusive lines in the sample |
|
|
31
|
+
| pdf | `{ page, object }` | 1-based page ordinal, then text-operation ordinal within that page's content stream |
|
|
32
|
+
|
|
33
|
+
A PDF has no lines to point at, so it gets the coordinates it actually has.
|
|
34
|
+
|
|
35
|
+
## Authoring a new adapter
|
|
36
|
+
|
|
37
|
+
1. Add a versioned entry to `ADAPTERS` in `engine/lib/format-adapters.js`: a
|
|
38
|
+
pure `adapt(source) -> Block[]`, lexical only — no client-code execution,
|
|
39
|
+
no subprocess, no network, no eval (D-014).
|
|
40
|
+
2. Declare its envelope in the module doc comment, and make everything outside
|
|
41
|
+
that envelope a HARD ERROR that names what was encountered. Never a partial
|
|
42
|
+
parse: a document reported as covered when half of it was never read is the
|
|
43
|
+
false-all-clear failure class (D-005/D-012), and it is worse than no
|
|
44
|
+
coverage at all.
|
|
45
|
+
3. Ship a pair here, and pin it in the kit's tests the way the shipped four
|
|
46
|
+
are pinned.
|
|
47
|
+
|
|
48
|
+
**Versioning.** Bump an adapter's version when the same input would produce
|
|
49
|
+
different IR bytes (a new block kind, a changed locator scheme, different
|
|
50
|
+
splitting or ordering) — maps built under different versions are not
|
|
51
|
+
comparable, and the version is what says so. Do not bump for a widened
|
|
52
|
+
envelope that leaves previously-accepted input byte-identical. A bump updates
|
|
53
|
+
the fixture pair in the same commit.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Expected IR for sample.html — the html@1 adapter (UCS-1153).
|
|
2
|
+
#
|
|
3
|
+
# Locators are 1-based inclusive line numbers, derived from the byte offsets of
|
|
4
|
+
# each element's open and close tags.
|
|
5
|
+
#
|
|
6
|
+
# What this pair pins: <script> and <style> bodies NEVER reach the IR (they are
|
|
7
|
+
# code and presentation, and feeding CSS to a lexicon would manufacture matches
|
|
8
|
+
# from selectors) — note that the sample's style block contains the word
|
|
9
|
+
# "settled" and its script contains it too, yet neither appears below; inline
|
|
10
|
+
# markup inside a block is stripped to text; the five XML entities decode
|
|
11
|
+
# (& -> &, <not> -> <not>); a <p> nested inside an <li> closes the
|
|
12
|
+
# list item, so the item is emitted once, not twice; <pre> keeps its newlines;
|
|
13
|
+
# and table cells are joined with the same " | " separator the md adapter uses,
|
|
14
|
+
# so a table row means the same thing whatever format it arrived in.
|
|
15
|
+
#
|
|
16
|
+
# D-014: this adapter never executes anything. No DOM is built, no script runs,
|
|
17
|
+
# no resource is fetched. The document is bytes.
|
|
18
|
+
format: html
|
|
19
|
+
file: sample.html
|
|
20
|
+
adapter: html@1
|
|
21
|
+
hash: fnv1a64:062e49c39e1bf5c1
|
|
22
|
+
blocks:
|
|
23
|
+
- kind: heading
|
|
24
|
+
level: 1
|
|
25
|
+
text: Font licensing onboarding
|
|
26
|
+
locator: {line: 11, endLine: 11}
|
|
27
|
+
- kind: paragraph
|
|
28
|
+
text: The foundry must expose a CDN endpoint and a self-hosted fallback. Render budget is 400ms & measured end-to-end.
|
|
29
|
+
locator: {line: 13, endLine: 14}
|
|
30
|
+
- kind: list-item
|
|
31
|
+
text: CDN endpoint, TLS only
|
|
32
|
+
locator: {line: 22, endLine: 22}
|
|
33
|
+
- kind: paragraph
|
|
34
|
+
text: Self-hosted fallback for offline
|
|
35
|
+
locator: {line: 23, endLine: 23}
|
|
36
|
+
- kind: code
|
|
37
|
+
text: |-
|
|
38
|
+
foundry:
|
|
39
|
+
name: typeco
|
|
40
|
+
timeout-ms: 400
|
|
41
|
+
locator: {line: 26, endLine: 28}
|
|
42
|
+
- kind: table-row
|
|
43
|
+
text: Field | Meaning
|
|
44
|
+
locator: {line: 31, endLine: 31}
|
|
45
|
+
- kind: table-row
|
|
46
|
+
text: pending | license requested, <not> granted
|
|
47
|
+
locator: {line: 32, endLine: 32}
|
|
48
|
+
- kind: paragraph
|
|
49
|
+
text: Page the design-ops rotation when the CDN degrades for more than ninety seconds.
|
|
50
|
+
locator: {line: 35, endLine: 36}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title>Font licensing onboarding</title>
|
|
5
|
+
<style>h1 { color: rebeccapurple; content: "granted"; }</style>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<!-- Adapter fixture — html. Adversarial-but-adaptable: script and style
|
|
9
|
+
bodies that must never reach the IR, inline markup inside blocks,
|
|
10
|
+
XML entities, a nested block element, and a table. -->
|
|
11
|
+
<h1>Font licensing onboarding</h1>
|
|
12
|
+
|
|
13
|
+
<p>The foundry must expose a <strong>CDN</strong> endpoint and a
|
|
14
|
+
self-hosted fallback. Render budget is 400ms & measured end-to-end.</p>
|
|
15
|
+
|
|
16
|
+
<script>
|
|
17
|
+
// Executing this would be a D-014 violation. It is discarded as text.
|
|
18
|
+
document.title = "granted";
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<ul>
|
|
22
|
+
<li>CDN endpoint, TLS only</li>
|
|
23
|
+
<li><p>Self-hosted fallback for offline</p></li>
|
|
24
|
+
</ul>
|
|
25
|
+
|
|
26
|
+
<pre>foundry:
|
|
27
|
+
name: typeco
|
|
28
|
+
timeout-ms: 400</pre>
|
|
29
|
+
|
|
30
|
+
<table>
|
|
31
|
+
<tr><th>Field</th><th>Meaning</th></tr>
|
|
32
|
+
<tr><td>pending</td><td>license requested, <not> granted</td></tr>
|
|
33
|
+
</table>
|
|
34
|
+
|
|
35
|
+
<blockquote>Page the design-ops rotation when the CDN degrades for more
|
|
36
|
+
than ninety seconds.</blockquote>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Expected IR for sample.md — the md@1 adapter (UCS-1153).
|
|
2
|
+
#
|
|
3
|
+
# Ordered blocks with kinds and source locators. Order is CONTRACT here (unlike
|
|
4
|
+
# the extractor pairs, whose values are sets): the IR preserves document order,
|
|
5
|
+
# and a coverage map reads it that way. Locators are 1-based inclusive line
|
|
6
|
+
# numbers into the ORIGINAL sample, so a reader can open the file at the line.
|
|
7
|
+
#
|
|
8
|
+
# What this pair pins beyond the happy path: a paragraph reflowed from three
|
|
9
|
+
# source lines onto one block (its locator keeps the full span), fenced code
|
|
10
|
+
# whose newlines and indentation SURVIVE (whitespace is semantic in code, so it
|
|
11
|
+
# is never flattened), all three list markers, the table delimiter row dropped
|
|
12
|
+
# as presentation, and the trailing hashes of a closed ATX heading stripped.
|
|
13
|
+
format: md
|
|
14
|
+
file: sample.md
|
|
15
|
+
adapter: md@1
|
|
16
|
+
hash: fnv1a64:261b6b2f06931422
|
|
17
|
+
blocks:
|
|
18
|
+
- kind: heading
|
|
19
|
+
level: 1
|
|
20
|
+
text: Font licensing onboarding
|
|
21
|
+
locator: {line: 1, endLine: 1}
|
|
22
|
+
- kind: paragraph
|
|
23
|
+
text: 'Adapter fixture — markdown. Adversarial-but-adaptable on purpose: a paragraph wrapped across several source lines, a fenced code block whose indentation is content, both list markers, a table, and a heading with trailing hashes.'
|
|
24
|
+
locator: {line: 3, endLine: 5}
|
|
25
|
+
- kind: heading
|
|
26
|
+
level: 2
|
|
27
|
+
text: Foundry requirements
|
|
28
|
+
locator: {line: 7, endLine: 7}
|
|
29
|
+
- kind: paragraph
|
|
30
|
+
text: The foundry must expose a CDN endpoint and a self-hosted fallback. Render budget is four hundred milliseconds end-to-end, measured from request to paint.
|
|
31
|
+
locator: {line: 9, endLine: 11}
|
|
32
|
+
- kind: list-item
|
|
33
|
+
text: CDN endpoint, TLS only
|
|
34
|
+
locator: {line: 13, endLine: 13}
|
|
35
|
+
- kind: list-item
|
|
36
|
+
text: Self-hosted fallback for offline
|
|
37
|
+
locator: {line: 14, endLine: 14}
|
|
38
|
+
- kind: list-item
|
|
39
|
+
text: Trial license before production
|
|
40
|
+
locator: {line: 15, endLine: 15}
|
|
41
|
+
- kind: paragraph
|
|
42
|
+
text: 'Configuration lives in one block:'
|
|
43
|
+
locator: {line: 17, endLine: 17}
|
|
44
|
+
- kind: code
|
|
45
|
+
text: |-
|
|
46
|
+
foundry:
|
|
47
|
+
name: typeco
|
|
48
|
+
timeout-ms: 400
|
|
49
|
+
locator: {line: 19, endLine: 23}
|
|
50
|
+
- kind: table-row
|
|
51
|
+
text: Field | Meaning
|
|
52
|
+
locator: {line: 25, endLine: 25}
|
|
53
|
+
- kind: table-row
|
|
54
|
+
text: '`pending` | license requested, not granted'
|
|
55
|
+
locator: {line: 27, endLine: 27}
|
|
56
|
+
- kind: table-row
|
|
57
|
+
text: '`granted` | license final'
|
|
58
|
+
locator: {line: 28, endLine: 28}
|
|
59
|
+
- kind: heading
|
|
60
|
+
level: 3
|
|
61
|
+
text: Escalation
|
|
62
|
+
locator: {line: 30, endLine: 30}
|
|
63
|
+
- kind: paragraph
|
|
64
|
+
text: Page the design-ops rotation when the CDN degrades for more than ninety seconds.
|
|
65
|
+
locator: {line: 32, endLine: 32}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Font licensing onboarding
|
|
2
|
+
|
|
3
|
+
Adapter fixture — markdown. Adversarial-but-adaptable on purpose: a paragraph
|
|
4
|
+
wrapped across several source lines, a fenced code block whose indentation is
|
|
5
|
+
content, both list markers, a table, and a heading with trailing hashes.
|
|
6
|
+
|
|
7
|
+
## Foundry requirements ##
|
|
8
|
+
|
|
9
|
+
The foundry must expose a CDN endpoint and a self-hosted fallback. Render
|
|
10
|
+
budget is four hundred milliseconds end-to-end, measured from request to
|
|
11
|
+
paint.
|
|
12
|
+
|
|
13
|
+
- CDN endpoint, TLS only
|
|
14
|
+
* Self-hosted fallback for offline
|
|
15
|
+
1. Trial license before production
|
|
16
|
+
|
|
17
|
+
Configuration lives in one block:
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
foundry:
|
|
21
|
+
name: typeco
|
|
22
|
+
timeout-ms: 400
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
| Field | Meaning |
|
|
26
|
+
|-------|---------|
|
|
27
|
+
| `pending` | license requested, not granted |
|
|
28
|
+
| `granted` | license final |
|
|
29
|
+
|
|
30
|
+
### Escalation
|
|
31
|
+
|
|
32
|
+
Page the design-ops rotation when the CDN degrades for more than ninety seconds.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Expected IR for sample.pdf — the pdf@1 adapter (UCS-1153).
|
|
2
|
+
#
|
|
3
|
+
# LOCATOR SCHEME differs from the text formats, because a PDF is not line-
|
|
4
|
+
# addressable: { page, object } is the 1-based page ordinal in document order
|
|
5
|
+
# plus the 1-based ordinal of the text-showing operation within that page's
|
|
6
|
+
# content stream. Both derive from content-stream order, never from object
|
|
7
|
+
# numbering or enumeration order, so they are stable for identical bytes.
|
|
8
|
+
#
|
|
9
|
+
# The sample is hand-crafted by scripts/make-pdf-fixture.js so this expectation
|
|
10
|
+
# is genuinely reviewable rather than checked against an opaque binary. It
|
|
11
|
+
# exercises exactly the pdf@1 envelope: page 1 is an UNCOMPRESSED stream using
|
|
12
|
+
# Tj and a TJ kerning array (whose fragments join into one block), with an
|
|
13
|
+
# escaped paren \( and an octal \050 both decoding to literal parens; page 2 is
|
|
14
|
+
# a FLATEDECODE stream (inflated with node:zlib — stdlib decompression, never
|
|
15
|
+
# execution) using the ' (next-line-and-show) operator and a hex <...> string.
|
|
16
|
+
#
|
|
17
|
+
# Every kind here is a paragraph: PDF has no paragraph or heading concept, and
|
|
18
|
+
# clustering text by coordinates to invent one would be a guess. One text-
|
|
19
|
+
# showing operation, one block, one locator.
|
|
20
|
+
format: pdf
|
|
21
|
+
file: sample.pdf
|
|
22
|
+
adapter: pdf@1
|
|
23
|
+
hash: fnv1a64:0a290a783b026774
|
|
24
|
+
blocks:
|
|
25
|
+
- kind: paragraph
|
|
26
|
+
text: Font licensing onboarding
|
|
27
|
+
locator: {page: 1, object: 1}
|
|
28
|
+
- kind: paragraph
|
|
29
|
+
text: The foundry must expose a CDN endpoint and a self-hosted fallback.
|
|
30
|
+
locator: {page: 1, object: 2}
|
|
31
|
+
- kind: paragraph
|
|
32
|
+
text: Render budget is 400ms (end-to-end), measured from request to paint.
|
|
33
|
+
locator: {page: 1, object: 3}
|
|
34
|
+
- kind: paragraph
|
|
35
|
+
text: Pending (not granted) is a distinct state.
|
|
36
|
+
locator: {page: 1, object: 4}
|
|
37
|
+
- kind: paragraph
|
|
38
|
+
text: Escalation
|
|
39
|
+
locator: {page: 2, object: 1}
|
|
40
|
+
- kind: paragraph
|
|
41
|
+
text: Page the design-ops rotation when the CDN degrades for more than ninety seconds.
|
|
42
|
+
locator: {page: 2, object: 2}
|
|
43
|
+
- kind: paragraph
|
|
44
|
+
text: Foundry credentials are sandboxed.
|
|
45
|
+
locator: {page: 2, object: 3}
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Expected IR for sample.txt — the txt@1 adapter (UCS-1153).
|
|
2
|
+
#
|
|
3
|
+
# Every block is a paragraph. That is the whole point of this pair: plain text
|
|
4
|
+
# carries no marked-up structure, and the adapter INVENTS NONE. The sample
|
|
5
|
+
# deliberately tempts a heuristic parser twice — a four-space-indented run that
|
|
6
|
+
# a markdown adapter would call code, and an ALL-CAPS line that looks like a
|
|
7
|
+
# heading — and both stay paragraphs. Guessed structure would put sections in a
|
|
8
|
+
# coverage map that the document never had.
|
|
9
|
+
format: txt
|
|
10
|
+
file: sample.txt
|
|
11
|
+
adapter: txt@1
|
|
12
|
+
hash: fnv1a64:4c921cb8fa2f2059
|
|
13
|
+
blocks:
|
|
14
|
+
- kind: paragraph
|
|
15
|
+
text: Font licensing onboarding
|
|
16
|
+
locator: {line: 1, endLine: 1}
|
|
17
|
+
- kind: paragraph
|
|
18
|
+
text: 'Adapter fixture — plain text. Plain text carries no marked-up structure, so every block is a paragraph: the adapter invents no headings and no code, and this sample is shaped to tempt it into doing both.'
|
|
19
|
+
locator: {line: 3, endLine: 5}
|
|
20
|
+
- kind: paragraph
|
|
21
|
+
text: This line is indented four spaces. A markdown adapter would call it code. The txt adapter calls it prose, because plain text has no code fences and guessing would manufacture structure the document never had.
|
|
22
|
+
locator: {line: 7, endLine: 9}
|
|
23
|
+
- kind: paragraph
|
|
24
|
+
text: FOUNDRY REQUIREMENTS
|
|
25
|
+
locator: {line: 11, endLine: 11}
|
|
26
|
+
- kind: paragraph
|
|
27
|
+
text: The line above is shouting, and a heuristic adapter would promote it to a heading. It stays a paragraph. Degraded structure, identical process — the coverage map is bounded by content richness, and this is the honest floor.
|
|
28
|
+
locator: {line: 13, endLine: 15}
|
|
29
|
+
- kind: paragraph
|
|
30
|
+
text: Render budget is four hundred milliseconds end-to-end, measured from request to paint.
|
|
31
|
+
locator: {line: 17, endLine: 18}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Font licensing onboarding
|
|
2
|
+
|
|
3
|
+
Adapter fixture — plain text. Plain text carries no marked-up structure, so
|
|
4
|
+
every block is a paragraph: the adapter invents no headings and no code, and
|
|
5
|
+
this sample is shaped to tempt it into doing both.
|
|
6
|
+
|
|
7
|
+
This line is indented four spaces. A markdown adapter would call it code.
|
|
8
|
+
The txt adapter calls it prose, because plain text has no code fences and
|
|
9
|
+
guessing would manufacture structure the document never had.
|
|
10
|
+
|
|
11
|
+
FOUNDRY REQUIREMENTS
|
|
12
|
+
|
|
13
|
+
The line above is shouting, and a heuristic adapter would promote it to a
|
|
14
|
+
heading. It stays a paragraph. Degraded structure, identical process — the
|
|
15
|
+
coverage map is bounded by content richness, and this is the honest floor.
|
|
16
|
+
|
|
17
|
+
Render budget is four hundred milliseconds end-to-end, measured from request
|
|
18
|
+
to paint.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# unknown-knowledge — this repo's knowledge base
|
|
2
|
+
|
|
3
|
+
This directory was seeded once by the [unknown-knowledge](https://github.com/doterodesign/unknown-knowledge)
|
|
4
|
+
kit and is now yours (D-001): three YAML stores that map the system
|
|
5
|
+
(`ontology/`, `knowledge/`, `decisions/`), a deterministic engine that checks
|
|
6
|
+
the map (`engine/`), and the agent protocol that runs the loop (`protocol/`).
|
|
7
|
+
There is no service, no runtime, and no update channel — everything is files
|
|
8
|
+
in this repo, branched and merged by your normal PRs.
|
|
9
|
+
|
|
10
|
+
One idea governs everything here: **the map is never the fact.** Stores hold
|
|
11
|
+
claims and pointers; your source files hold facts. The engine's job is to
|
|
12
|
+
diff the two and say exactly where they disagree.
|
|
13
|
+
|
|
14
|
+
> Commands run from the **repo root** with this directory at its default
|
|
15
|
+
> name `unknown-knowledge/`; substitute your chosen name if it differs.
|
|
16
|
+
|
|
17
|
+
## What you own vs. what was vendored
|
|
18
|
+
|
|
19
|
+
Everything is client-owned after seeding; the zone map in
|
|
20
|
+
`kit.manifest.yaml` records what an uninstall or audit needs to know — which
|
|
21
|
+
paths arrived from the kit and which your own loop produced.
|
|
22
|
+
|
|
23
|
+
| Zone | Paths | Meaning |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| seeded | `engine/`, `protocol/`, `schemas/`, `templates/`, `kit.manifest.yaml` | vendored at init: engine code, schemas, protocol markdown. Protocol conduct policy is explicitly yours to edit (see `docs/boundaries.md`) |
|
|
26
|
+
| client | `ontology/`, `knowledge/`, `decisions/`, `logs/`, `survey-scope.yaml` | your team's data. The kit shipped only empty scaffolding here; everything else was written by your loop |
|
|
27
|
+
|
|
28
|
+
## Running the gates
|
|
29
|
+
|
|
30
|
+
The engine is plain Node (≥ 22, no build step) with one library
|
|
31
|
+
dependency, `js-yaml`, resolved from your repo like any other package: if
|
|
32
|
+
your repo does not already carry it, run `npm install --save-dev js-yaml`
|
|
33
|
+
once.
|
|
34
|
+
|
|
35
|
+
The blocking-grade checks all take `--root` as the **repo root** and share
|
|
36
|
+
one exit-code contract: 0 = clean, 1 = findings/quarantines, 2 = the check
|
|
37
|
+
never ran. **A check that never ran is a blocking defect, never a silent
|
|
38
|
+
pass** — treat exit 2 as a stop, not a shrug.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
node unknown-knowledge/engine/validate.js --root . # structure: ids, refs, pointers
|
|
42
|
+
node unknown-knowledge/engine/validate-values.js --root . # enumerated values vs. source
|
|
43
|
+
node unknown-knowledge/engine/preflight.js --root . # store health + per-concept verdicts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`engine/audit.js` is different in kind — advisory (never blocking). It
|
|
47
|
+
proposes draft concepts for anchors the map does not cover yet; a human
|
|
48
|
+
reviews every draft. Run it on the steward cadence, never as a gate
|
|
49
|
+
(`docs/steward-guide.md`).
|
|
50
|
+
|
|
51
|
+
## How the loop works
|
|
52
|
+
|
|
53
|
+
The runtime contract — `RESOLVE → PREFLIGHT → GATHER → ACT → RECORD` — lives
|
|
54
|
+
in [`protocol/AGENTS.md`](protocol/AGENTS.md). That file is the single
|
|
55
|
+
source of truth for how agents navigate the stores, what a verdict obliges,
|
|
56
|
+
and when findings get appended; start every integration question there. The
|
|
57
|
+
procedures live in the skills under `protocol/skills/`, referenced by name
|
|
58
|
+
(D-019): `/knowledge-bootstrap` (first population), `/knowledge-reflect`
|
|
59
|
+
(consolidating findings into reviewed fixes), `/kb-build` (cited knowledge
|
|
60
|
+
writes), `/knowledge-audit` (the loop's heartbeat report).
|
|
61
|
+
|
|
62
|
+
## Extractor fixtures and later stacks (D-009)
|
|
63
|
+
|
|
64
|
+
Extractor fixtures for the stacks selected at init are included under
|
|
65
|
+
`engine/tests`. If you adopt another stack later, you author your own pack
|
|
66
|
+
from the included template (`templates/new-kind/`, plus the fixture
|
|
67
|
+
authoring README seeded beside the packs) — there is no update channel. The
|
|
68
|
+
governed path for teaching the engine a new anchor shape is
|
|
69
|
+
`protocol/new-kind-pipeline.md`.
|
|
70
|
+
|
|
71
|
+
## CI
|
|
72
|
+
|
|
73
|
+
Session-level preflight is a sufficient gate for a small team, not for
|
|
74
|
+
hundreds of engineers. At team scale, wire the validators into CI — copyable
|
|
75
|
+
templates and the PR drift-attribution recipe are in
|
|
76
|
+
[`docs/ci-wiring.md`](docs/ci-wiring.md). Init never wires CI for you
|
|
77
|
+
(D-006).
|
|
78
|
+
|
|
79
|
+
## Version stamp and license
|
|
80
|
+
|
|
81
|
+
`kit-version` in `kit.manifest.yaml` records the kit version that seeded
|
|
82
|
+
this directory — a birth certificate, not a dependency pin (D-021): it says
|
|
83
|
+
which schema revision, extractor-kind set, and fixture vintage the seed was
|
|
84
|
+
born with, and implies no update channel. The vendored code is Apache-2.0
|
|
85
|
+
(D-020); the seeded `LICENSE` and `NOTICE` carry the terms and the
|
|
86
|
+
attribution. Your stores and logs are your own content, not the kit's.
|
|
87
|
+
|
|
88
|
+
## Uninstalling
|
|
89
|
+
|
|
90
|
+
Delete this directory and remove the thin per-platform wrapper files init
|
|
91
|
+
generated at their conventional paths (e.g. under `.claude/`) — that is the
|
|
92
|
+
whole uninstall; nothing else in your repo belongs to the kit. Before you
|
|
93
|
+
delete, mind the zone map above: `ontology/`, `knowledge/`, `decisions/`,
|
|
94
|
+
`logs/`, and `survey-scope.yaml` are your team's data, and `logs/` in
|
|
95
|
+
particular is the recorded history of where your map and your code
|
|
96
|
+
disagreed — export what you want to keep first.
|
|
97
|
+
|
|
98
|
+
## Further reading
|
|
99
|
+
|
|
100
|
+
- [`docs/ci-wiring.md`](docs/ci-wiring.md) — CI templates + PR drift attribution (D-012)
|
|
101
|
+
- [`docs/steward-guide.md`](docs/steward-guide.md) — the steward role, cadence, CODEOWNERS, hygiene recipes
|
|
102
|
+
- [`docs/boundaries.md`](docs/boundaries.md) — what the kit guarantees, and what it will never catch
|