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.
Files changed (147) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +167 -0
  4. package/cli/.gitkeep +0 -0
  5. package/cli/commands/init-copy.js +90 -0
  6. package/cli/commands/init.js +386 -0
  7. package/cli/init-copy.js +24 -0
  8. package/cli/init.js +24 -0
  9. package/cli/kit.manifest.yaml +256 -0
  10. package/cli/lib/copy-payload.js +334 -0
  11. package/cli/lib/generate-wrappers.js +162 -0
  12. package/package.json +36 -0
  13. package/payload/adapter-fixtures/README.md +53 -0
  14. package/payload/adapter-fixtures/html/EXPECTED.yaml +50 -0
  15. package/payload/adapter-fixtures/html/sample.html +38 -0
  16. package/payload/adapter-fixtures/md/EXPECTED.yaml +65 -0
  17. package/payload/adapter-fixtures/md/sample.md +32 -0
  18. package/payload/adapter-fixtures/pdf/EXPECTED.yaml +45 -0
  19. package/payload/adapter-fixtures/pdf/sample.pdf +0 -0
  20. package/payload/adapter-fixtures/txt/EXPECTED.yaml +31 -0
  21. package/payload/adapter-fixtures/txt/sample.txt +18 -0
  22. package/payload/docs/README.md +102 -0
  23. package/payload/docs/boundaries.md +60 -0
  24. package/payload/docs/ci-wiring.md +109 -0
  25. package/payload/docs/steward-guide.md +238 -0
  26. package/payload/engine/audit.js +34 -0
  27. package/payload/engine/commands/audit.js +289 -0
  28. package/payload/engine/commands/derive.js +334 -0
  29. package/payload/engine/commands/ingest.js +124 -0
  30. package/payload/engine/commands/log-entry.js +85 -0
  31. package/payload/engine/commands/phoenix.js +206 -0
  32. package/payload/engine/commands/preflight.js +530 -0
  33. package/payload/engine/commands/resolve.js +1678 -0
  34. package/payload/engine/commands/survey-map.js +351 -0
  35. package/payload/engine/commands/validate-values.js +315 -0
  36. package/payload/engine/commands/validate.js +1426 -0
  37. package/payload/engine/derive.js +34 -0
  38. package/payload/engine/ingest.js +34 -0
  39. package/payload/engine/lib/anchor-signatures.js +126 -0
  40. package/payload/engine/lib/boot.js +39 -0
  41. package/payload/engine/lib/call-numbers.js +133 -0
  42. package/payload/engine/lib/cli.js +147 -0
  43. package/payload/engine/lib/coverage.js +849 -0
  44. package/payload/engine/lib/decomposition.js +225 -0
  45. package/payload/engine/lib/derived.js +494 -0
  46. package/payload/engine/lib/engine-refusal.js +40 -0
  47. package/payload/engine/lib/exit-codes.js +14 -0
  48. package/payload/engine/lib/extractor-kinds.js +955 -0
  49. package/payload/engine/lib/format-adapters.js +802 -0
  50. package/payload/engine/lib/id-grammars.js +178 -0
  51. package/payload/engine/lib/iso-date.js +55 -0
  52. package/payload/engine/lib/kit-root.js +101 -0
  53. package/payload/engine/lib/load-stores.js +1624 -0
  54. package/payload/engine/lib/log-entry.js +196 -0
  55. package/payload/engine/lib/phoenix.js +628 -0
  56. package/payload/engine/lib/scoring.js +150 -0
  57. package/payload/engine/lib/suppressions.js +172 -0
  58. package/payload/engine/lib/time-verdicts.js +282 -0
  59. package/payload/engine/lib/usage-error.js +14 -0
  60. package/payload/engine/lib/validate-record.js +504 -0
  61. package/payload/engine/log-entry.js +34 -0
  62. package/payload/engine/phoenix.js +39 -0
  63. package/payload/engine/preflight.js +34 -0
  64. package/payload/engine/resolve.js +34 -0
  65. package/payload/engine/survey-map.js +34 -0
  66. package/payload/engine/validate-values.js +34 -0
  67. package/payload/engine/validate.js +34 -0
  68. package/payload/extractor-fixtures/.gitkeep +0 -0
  69. package/payload/extractor-fixtures/README.md +29 -0
  70. package/payload/extractor-fixtures/swift/strings-keys/EXPECTED.yaml +8 -0
  71. package/payload/extractor-fixtures/swift/strings-keys/sample.strings +15 -0
  72. package/payload/extractor-fixtures/swift/swift-const-array/EXPECTED.yaml +7 -0
  73. package/payload/extractor-fixtures/swift/swift-const-array/sample.swift +21 -0
  74. package/payload/extractor-fixtures/swift/swift-enum/EXPECTED.yaml +8 -0
  75. package/payload/extractor-fixtures/swift/swift-enum/sample.swift +30 -0
  76. package/payload/extractor-fixtures/swift/yaml-keys/EXPECTED.yaml +6 -0
  77. package/payload/extractor-fixtures/swift/yaml-keys/sample.yaml +23 -0
  78. package/payload/extractor-fixtures/swift/yaml-map-keys/EXPECTED.yaml +7 -0
  79. package/payload/extractor-fixtures/swift/yaml-map-keys/sample.yaml +15 -0
  80. package/payload/extractor-fixtures/ts/dir-modules/EXPECTED.yaml +12 -0
  81. package/payload/extractor-fixtures/ts/dir-modules/sample-modules/alpha.widget.ts +1 -0
  82. package/payload/extractor-fixtures/ts/dir-modules/sample-modules/beta.widget.ts +1 -0
  83. package/payload/extractor-fixtures/ts/dir-modules/sample-modules/gamma.widget.ts +1 -0
  84. package/payload/extractor-fixtures/ts/dir-modules/sample-modules/helpers/format.ts +3 -0
  85. package/payload/extractor-fixtures/ts/dir-modules/sample-modules/widgets.test.ts +2 -0
  86. package/payload/extractor-fixtures/ts/json-keys/EXPECTED.yaml +7 -0
  87. package/payload/extractor-fixtures/ts/json-keys/sample.json +5 -0
  88. package/payload/extractor-fixtures/ts/json-map-keys/EXPECTED.yaml +7 -0
  89. package/payload/extractor-fixtures/ts/json-map-keys/sample.json +13 -0
  90. package/payload/extractor-fixtures/ts/ts-const-array/EXPECTED.yaml +6 -0
  91. package/payload/extractor-fixtures/ts/ts-const-array/sample.ts +13 -0
  92. package/payload/extractor-fixtures/ts/ts-enum/EXPECTED.yaml +7 -0
  93. package/payload/extractor-fixtures/ts/ts-enum/sample.ts +11 -0
  94. package/payload/extractor-fixtures/ts/ts-object-keys/EXPECTED.yaml +6 -0
  95. package/payload/extractor-fixtures/ts/ts-object-keys/sample.tsx +23 -0
  96. package/payload/extractor-fixtures/ts/ts-union/EXPECTED.yaml +5 -0
  97. package/payload/extractor-fixtures/ts/ts-union/sample.ts +9 -0
  98. package/payload/hooks/pre-commit +37 -0
  99. package/payload/hooks/reverse-lookup +66 -0
  100. package/payload/package.json +3 -0
  101. package/payload/protocol/.gitkeep +0 -0
  102. package/payload/protocol/AGENTS.md +239 -0
  103. package/payload/protocol/derived-layer.md +174 -0
  104. package/payload/protocol/new-kind-pipeline.md +179 -0
  105. package/payload/protocol/registry-warrant.md +162 -0
  106. package/payload/protocol/skills/kb-build.md +303 -0
  107. package/payload/protocol/skills/knowledge-audit.md +183 -0
  108. package/payload/protocol/skills/knowledge-bootstrap.md +229 -0
  109. package/payload/protocol/skills/knowledge-reflect.md +397 -0
  110. package/payload/schemas/catalog.schema.json +32 -0
  111. package/payload/schemas/decision-entry.schema.json +122 -0
  112. package/payload/schemas/finding.schema.json +77 -0
  113. package/payload/schemas/gap.schema.json +52 -0
  114. package/payload/schemas/graduation-categories.schema.json +64 -0
  115. package/payload/schemas/knowledge-leaf.schema.json +194 -0
  116. package/payload/schemas/miss.schema.json +45 -0
  117. package/payload/schemas/ontology-concept.schema.json +115 -0
  118. package/payload/schemas/phoenix-event.schema.json +76 -0
  119. package/payload/schemas/registry.schema.json +57 -0
  120. package/payload/schemas/rules.schema.json +14 -0
  121. package/payload/schemas/survey-scope.schema.json +23 -0
  122. package/payload/templates/decisions/_catalog.yaml +7 -0
  123. package/payload/templates/decisions/_registries/graduation-categories.yaml +42 -0
  124. package/payload/templates/decisions/phoenix-event.yaml +74 -0
  125. package/payload/templates/decisions/reflect-mint-proposal.yaml +100 -0
  126. package/payload/templates/decisions/registry-minting.yaml +58 -0
  127. package/payload/templates/decisions/trust-graduation.yaml +120 -0
  128. package/payload/templates/decisions/trust-revocation.yaml +106 -0
  129. package/payload/templates/knowledge/_catalog.yaml +9 -0
  130. package/payload/templates/knowledge/_registries/anchor.yaml +42 -0
  131. package/payload/templates/knowledge/_registries/authority-tiers.yaml +32 -0
  132. package/payload/templates/knowledge/_registries/domains.yaml +43 -0
  133. package/payload/templates/knowledge/_registries/form.yaml +38 -0
  134. package/payload/templates/knowledge/_registries/jurisdictions.yaml +20 -0
  135. package/payload/templates/knowledge/_registries/operations.yaml +18 -0
  136. package/payload/templates/knowledge/_registries/stage.yaml +53 -0
  137. package/payload/templates/knowledge/_rules.yaml +6 -0
  138. package/payload/templates/new-kind/README.md +107 -0
  139. package/payload/templates/new-kind/descriptor.example.yaml +18 -0
  140. package/payload/templates/new-kind/fixture/EXPECTED.yaml +6 -0
  141. package/payload/templates/new-kind/fixture/demo-anchor.list +2 -0
  142. package/payload/templates/new-kind/fixture/sample.list +7 -0
  143. package/payload/templates/new-kind/parser.example.js +98 -0
  144. package/payload/templates/ontology/_catalog.yaml +6 -0
  145. package/payload/templates/ontology/_rules.yaml +6 -0
  146. package/payload/wrappers/cursor.mdc +15 -0
  147. package/payload/wrappers/pointer.md +10 -0
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * engine/validate-values.js — the entry shim (UCS-956).
4
+ *
5
+ * This file statically imports NOTHING. That is its entire job.
6
+ *
7
+ * Node exits 1 on an unhandled ES module load error, and exit 1 means FINDINGS
8
+ * (PRD §5). A SyntaxError in a lib/ module, or a missing `js-yaml`, must not
9
+ * tell an agent that the check ran and found problems. So the engine is reached
10
+ * only through `import()`, where a load failure is an ordinary catchable
11
+ * rejection rather than a process-level crash.
12
+ *
13
+ * Both specifiers are string literals naming the engine's own files. D-014
14
+ * forbids importing REPO CONTENT — the client's code — and nothing here can
15
+ * name it: there is no variable to point somewhere else.
16
+ *
17
+ * The command lives in commands/validate-values.js. Its invocation path is unchanged.
18
+ */
19
+ try {
20
+ const [{ boot }, command] = await Promise.all([
21
+ import('./lib/boot.js'),
22
+ import('./commands/validate-values.js'),
23
+ ]);
24
+ // exitCode, never process.exit(): exit() drops queued async stdout writes, so
25
+ // piped --json output would truncate at the pipe buffer — corrupt output
26
+ // wearing a clean exit code. Node exits on its own once stdout drains.
27
+ process.exitCode = await boot('validate-values', command);
28
+ } catch (error) {
29
+ // The engine could not be loaded, so no check ran. Exit 2 — never 1.
30
+ // Hardcoded, because reading it from lib/exit-codes.js is the very thing
31
+ // that may have just failed.
32
+ process.stderr.write(`validate-values: internal failure — the engine could not be loaded\n${error?.stack ?? error}\n`);
33
+ process.exitCode = 2;
34
+ }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * engine/validate.js — the entry shim (UCS-956).
4
+ *
5
+ * This file statically imports NOTHING. That is its entire job.
6
+ *
7
+ * Node exits 1 on an unhandled ES module load error, and exit 1 means FINDINGS
8
+ * (PRD §5). A SyntaxError in a lib/ module, or a missing `js-yaml`, must not
9
+ * tell an agent that the check ran and found problems. So the engine is reached
10
+ * only through `import()`, where a load failure is an ordinary catchable
11
+ * rejection rather than a process-level crash.
12
+ *
13
+ * Both specifiers are string literals naming the engine's own files. D-014
14
+ * forbids importing REPO CONTENT — the client's code — and nothing here can
15
+ * name it: there is no variable to point somewhere else.
16
+ *
17
+ * The command lives in commands/validate.js. Its invocation path is unchanged.
18
+ */
19
+ try {
20
+ const [{ boot }, command] = await Promise.all([
21
+ import('./lib/boot.js'),
22
+ import('./commands/validate.js'),
23
+ ]);
24
+ // exitCode, never process.exit(): exit() drops queued async stdout writes, so
25
+ // piped --json output would truncate at the pipe buffer — corrupt output
26
+ // wearing a clean exit code. Node exits on its own once stdout drains.
27
+ process.exitCode = await boot('validate', command);
28
+ } catch (error) {
29
+ // The engine could not be loaded, so no check ran. Exit 2 — never 1.
30
+ // Hardcoded, because reading it from lib/exit-codes.js is the very thing
31
+ // that may have just failed.
32
+ process.stderr.write(`validate: internal failure — the engine could not be loaded\n${error?.stack ?? error}\n`);
33
+ process.exitCode = 2;
34
+ }
File without changes
@@ -0,0 +1,29 @@
1
+ # extractor-fixtures — the D-009 shipped sample/expected pairs
2
+
3
+ One directory per stack, one directory per extractor kind, each carrying a
4
+ `sample.<ext>` anchor and the `EXPECTED.yaml` value set the kind must extract
5
+ from it. These are the fixtures `npx unknown-knowledge init` seeds for the
6
+ stacks you select (D-009) — they show, runnably, what each kind's syntactic
7
+ envelope accepts, and they are the shape the §5.2 new-kind pipeline's DRAFT
8
+ step imitates (see `templates/new-kind/`).
9
+
10
+ Every sample is adversarial-but-extractable on purpose (PRD §5.1): comments
11
+ between members, mixed quote styles, trailing commas, nested values — gnarly
12
+ formatting that stays inside the envelope. Out-of-envelope shapes (spread,
13
+ computed keys, re-exports) are NOT here: those hard-error by design and live
14
+ in the kit's acceptance fixtures.
15
+
16
+ `EXPECTED.yaml` fields: `kind` + `file` + `values`, plus `symbol`/`emit`/
17
+ `pattern`/`strip` where the kind needs them — the same fields the descriptor
18
+ would carry. Values are strings compared byte-exact, case-sensitive, as sets
19
+ (§3.5): order in the file is presentation only.
20
+
21
+ Directory kinds (dir-modules) reshape the pair the obvious way: the sample
22
+ is a DIRECTORY (`file` names it, e.g. `sample-modules/`) instead of a single
23
+ file, and the round-trip feeds the kind the deterministic listing
24
+ (`listDirectory` in the engine's extractor-kinds registry) rather than file
25
+ text. Everything else — adversarial-but-extractable contents, EXPECTED.yaml
26
+ as the descriptor's fields — is unchanged.
27
+
28
+ Kit CI pins every pair against the registered kind (tests/), so a sample and
29
+ its expectation can never rot apart.
@@ -0,0 +1,8 @@
1
+ # Expected extraction for sample.strings — strings-keys emits the KEYS of the
2
+ # `"key" = "value";` entries (facet: key strings); values — including the one
3
+ # carrying '=' and the one with escaped quotes — are skipped, never emitted.
4
+ # Dispatch is by the source file's extension: .strings here (the .xcstrings
5
+ # JSON-catalog side is exercised by the kit's acceptance fixtures).
6
+ kind: strings-keys
7
+ file: sample.strings
8
+ values: [account.title, account.plan, editor.confirm, editor.cancel, editor.retry]
@@ -0,0 +1,15 @@
1
+ /* D-009 extractor fixture — strings-keys, .strings side (facet: the keys;
2
+ the .xcstrings side of the kind dispatches by file extension).
3
+ Adversarial-but-extractable: block + line comments, an '=' inside a value,
4
+ escaped quotes inside a value, two entries on one line, and a
5
+ commented-out pair that must NOT be extracted. Pair: EXPECTED.yaml. */
6
+
7
+ /* Account */
8
+ "account.title" = "Your account";
9
+ "account.plan" = "Plan = seats x tier"; /* '=' inside the value */
10
+
11
+ // "account.legacy" = "Old copy"; — commented-out pair, not a key
12
+
13
+ /* Editor */
14
+ "editor.confirm" = "Tap \"Insert\" to confirm"; // escaped quotes in the value
15
+ "editor.cancel" = "Cancel"; "editor.retry" = "Retry"; // two entries on one line
@@ -0,0 +1,7 @@
1
+ # Expected extraction for sample.swift (§3.5: byte-exact, case-sensitive, as
2
+ # a set — order here is presentation only). The commented-out entry and the
3
+ # decoy sibling array never count.
4
+ kind: swift-const-array
5
+ file: sample.swift
6
+ symbol: activeTemplateKinds
7
+ values: [wireframe, moodboard, storyboard, flowchart, persona, brand-sheet]
@@ -0,0 +1,21 @@
1
+ import Foundation
2
+
3
+ enum TemplateCatalog {
4
+ /// D-009 extractor fixture — swift-const-array (facet: the element
5
+ /// strings). Adversarial-but-extractable: multi-line literal, line +
6
+ /// block comments between members, a commented-out entry, two values on
7
+ /// one line, a trailing comma, an explicit type annotation, and a decoy
8
+ /// sibling array. Pair: EXPECTED.yaml.
9
+ static let activeTemplateKinds: [String] = [
10
+ "wireframe",
11
+ "moodboard", // weekly refresh
12
+ // "sitemap", — commented-out entry must NOT be extracted
13
+ "storyboard", /* narrative frames */
14
+ "flowchart", "persona", // two on one line
15
+ "brand-sheet",
16
+ ]
17
+
18
+ /// Decoy: an extractor scoped to `activeTemplateKinds` must never bleed
19
+ /// `retired-template` into its value set.
20
+ static let retiredTemplateKinds = ["retired-template"]
21
+ }
@@ -0,0 +1,8 @@
1
+ # Expected extraction for sample.swift — `emit: case-name` pins the facet
2
+ # (§3.5): case names, not the SCREAMING_SNAKE raw values. The comma-joined
3
+ # cases count; the switch arms and the decoy sibling enum never do.
4
+ kind: swift-enum
5
+ file: sample.swift
6
+ symbol: RenderQuality
7
+ emit: case-name
8
+ values: [preview, balanced, high, draft, print]
@@ -0,0 +1,30 @@
1
+ import Foundation
2
+
3
+ /// D-009 extractor fixture — swift-enum (facet pinned by `emit:` — this
4
+ /// pair's EXPECTED.yaml pins `case-name`). Adversarial-but-extractable:
5
+ /// an interior comment containing the word `case`, aligned `=` padding, a
6
+ /// trailing comment with a stray " quote, a comma-joined case list, a
7
+ /// computed property whose `switch` arms look like case declarations, and a
8
+ /// decoy sibling enum. Pair: EXPECTED.yaml.
9
+ enum RenderQuality: String, CaseIterable {
10
+ case preview = "PREVIEW"
11
+ // The word case inside a comment — case in point — is not a declaration.
12
+ case balanced = "BALANCED" /* aligned '=' padding above */
13
+ case high = "HIGH" // trailing comment with a stray " quote
14
+ case draft, print // comma-joined list; implicit raw values
15
+
16
+ var label: String {
17
+ switch self {
18
+ case .preview: return "Preview"
19
+ case .balanced: return "Balanced"
20
+ case .high: return "High"
21
+ case .draft: return "Draft"
22
+ case .print: return "Print"
23
+ }
24
+ }
25
+ }
26
+
27
+ /// Decoy: an extractor scoped to `RenderQuality` must never bleed `metal` in.
28
+ enum RenderEngine: String {
29
+ case metal = "METAL"
30
+ }
@@ -0,0 +1,6 @@
1
+ # Expected extraction for sample.yaml — yaml-keys emits the TOP-LEVEL keys
2
+ # (facet: key strings). Nested keys, sequence members, and merge-key aliases
3
+ # never leak in; "on" stays the string "on" (quoted here too, §3.5).
4
+ kind: yaml-keys
5
+ file: sample.yaml
6
+ values: [service, defaults, limits, fallback, "on"]
@@ -0,0 +1,23 @@
1
+ # D-009 extractor fixture — yaml-keys (facet: the TOP-LEVEL keys).
2
+ # Adversarial-but-extractable: comments between keys, an anchor/alias pair
3
+ # with a merge key, nested maps and sequences whose child keys must NOT bleed
4
+ # into the top-level set, and a quoted "on" key — YAML 1.2 loads it as the
5
+ # string "on" (the 1.1 boolean coercion this kind coerce-refuses never
6
+ # fires here). Pair: EXPECTED.yaml.
7
+ service: renderer
8
+
9
+ # Nested block: `region` / `retries` are NOT top-level keys.
10
+ defaults: &renderer-defaults
11
+ region: us-east
12
+ retries: 3
13
+
14
+ limits:
15
+ - daily
16
+ - weekly
17
+
18
+ fallback:
19
+ <<: *renderer-defaults
20
+ retries: 5
21
+
22
+ "on":
23
+ export: notify
@@ -0,0 +1,7 @@
1
+ # Expected extraction for sample.yaml — yaml-map-keys emits the keys of the
2
+ # mapping at the dotted path (facet: key strings). The sibling flags.canvas
3
+ # block never leaks in; the digit-leading key stays a byte-exact string.
4
+ kind: yaml-map-keys
5
+ file: sample.yaml
6
+ symbol: flags.sharing
7
+ values: [link-sharing, public-profiles, 2fa-required]
@@ -0,0 +1,15 @@
1
+ # D-009 extractor fixture — yaml-map-keys (facet: the keys of the mapping at
2
+ # the descriptor's dotted `symbol:` path — here `flags.sharing`).
3
+ # Adversarial-but-extractable: a sibling map whose keys must NOT bleed in, a
4
+ # quoted digit-leading key ("2fa-required" — unquoted-lookalike, provably a
5
+ # string), and boolean VALUES that must never be mistaken for the emitted
6
+ # key set. Pair: EXPECTED.yaml.
7
+ schema: 2
8
+ flags:
9
+ sharing:
10
+ link-sharing: true
11
+ public-profiles: false # rollout paused
12
+ "2fa-required": true
13
+ canvas:
14
+ vector-networks: true
15
+ auto-layout: false
@@ -0,0 +1,12 @@
1
+ # Expected extraction for sample-modules/ (§3.5: byte-exact, case-sensitive,
2
+ # as a set — order here is presentation only). dir-modules is a DIRECTORY
3
+ # kind: `file` names the sample directory, not a file, and the caller feeds
4
+ # the kind a deterministic listing (see the extractor-fixtures README).
5
+ # `pattern` pins the FILE facet (`*.widget.ts`: widgets.test.ts is excluded,
6
+ # the helpers/ subdirectory is not part of the facet); `strip` removes the
7
+ # `.widget.ts` suffix from every emitted name.
8
+ kind: dir-modules
9
+ file: sample-modules
10
+ pattern: "*.widget.ts"
11
+ strip: .widget.ts
12
+ values: [alpha, beta, gamma]
@@ -0,0 +1 @@
1
+ export const widget = 'alpha';
@@ -0,0 +1 @@
1
+ export const widget = 'beta';
@@ -0,0 +1 @@
1
+ export const widget = 'gamma';
@@ -0,0 +1,3 @@
1
+ // helpers/ is a SUBDIRECTORY: with a pattern present the facet is matching
2
+ // FILE names, so this folder (and its contents) never joins the value set.
3
+ export const format = (s) => s;
@@ -0,0 +1,2 @@
1
+ // Excluded by the `*.widget.ts` pattern — test scenery beside the modules.
2
+ export const isTest = true;
@@ -0,0 +1,7 @@
1
+ # Expected extraction for sample.json — json-keys emits the TOP-LEVEL keys
2
+ # (facet: key strings). Boolean/nested values never coerce into the set; the
3
+ # nested max-variants key must not leak in. (JSON cannot carry comments, so
4
+ # this pair's adversarial content is nesting, not formatting.)
5
+ kind: json-keys
6
+ file: sample.json
7
+ values: [multiplayer-cursors, version-history, component-variants]
@@ -0,0 +1,5 @@
1
+ {
2
+ "multiplayer-cursors": true,
3
+ "version-history": false,
4
+ "component-variants": { "max-variants": 10 }
5
+ }
@@ -0,0 +1,7 @@
1
+ # Expected extraction for sample.json — json-map-keys emits the keys of the
2
+ # object at the descriptor's dotted `symbol:` path (facet: key strings).
3
+ # Sibling blocks (scripts) must not leak in.
4
+ kind: json-map-keys
5
+ file: sample.json
6
+ symbol: config.flags
7
+ values: [multiplayer-cursors, version-history, component-variants]
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "sample-app",
3
+ "config": {
4
+ "flags": {
5
+ "multiplayer-cursors": true,
6
+ "version-history": true,
7
+ "component-variants": false
8
+ }
9
+ },
10
+ "scripts": {
11
+ "dev": "vite"
12
+ }
13
+ }
@@ -0,0 +1,6 @@
1
+ # Expected extraction for sample.ts (§3.5: byte-exact, case-sensitive, as a
2
+ # set — order here is presentation only).
3
+ kind: ts-const-array
4
+ file: sample.ts
5
+ symbol: EXPORT_FORMATS
6
+ values: [png, svg, jpg, webp]
@@ -0,0 +1,13 @@
1
+ // D-009 extractor fixture — ts-const-array (facet: the element strings of an
2
+ // exported const array literal; reads .js the same way — kinds describe
3
+ // declaration shape, not file type). Adversarial-but-extractable: multi-line,
4
+ // trailing comma, line + block comments between members, mixed quote styles,
5
+ // `as const`. Pair: EXPECTED.yaml.
6
+ export const EXPORT_FORMATS = [
7
+ 'png', // raster default
8
+ "svg",
9
+ 'jpg', /* legacy raster */
10
+ 'webp',
11
+ ] as const;
12
+
13
+ export type ExportFormat = (typeof EXPORT_FORMATS)[number];
@@ -0,0 +1,7 @@
1
+ # Expected extraction for sample.ts — `emit: names` pins the facet (§3.5):
2
+ # member names, not the lowercase raw values.
3
+ kind: ts-enum
4
+ file: sample.ts
5
+ symbol: ColorSpace
6
+ emit: names
7
+ values: [SRGB, P3, LAB, LCH]
@@ -0,0 +1,11 @@
1
+ // D-009 extractor fixture — ts-enum. TWO legitimate facets (member NAMES vs
2
+ // raw string VALUES); the descriptor pins one with `emit:` (§3.5) — this
3
+ // pair pins `emit: names`, so the expected set is the uppercase names, not
4
+ // the lowercase raw values. Adversarial-but-extractable: string initializers,
5
+ // mixed quotes, interleaved comment, trailing comma. Pair: EXPECTED.yaml.
6
+ export enum ColorSpace {
7
+ SRGB = 'srgb',
8
+ P3 = "display-p3", // wide gamut
9
+ LAB = 'lab',
10
+ LCH = 'lch',
11
+ }
@@ -0,0 +1,6 @@
1
+ # Expected extraction for sample.tsx — top-level keys only: the nested
2
+ # appliesTo array's members and the JSX inline literal must not leak in.
3
+ kind: ts-object-keys
4
+ file: sample.tsx
5
+ symbol: PANELS
6
+ values: [layers-panel, inspector, assets-panel, comments]
@@ -0,0 +1,23 @@
1
+ // D-009 extractor fixture — ts-object-keys (facet: the TOP-LEVEL keys of an
2
+ // exported object literal; nested objects/arrays are values, never keys).
3
+ // The .tsx extension is deliberate (§5.1: kinds describe declaration shape,
4
+ // not file type) and the JSX below plants an inline object literal
5
+ // ({{ color: ... }}) OUTSIDE the anchored symbol's span — it must not match.
6
+ // Adversarial-but-extractable: quoted dashed keys, bare keys, nested object
7
+ // and nested array values. Pair: EXPECTED.yaml.
8
+ export const PANELS = {
9
+ 'layers-panel': { defaultWidth: 240 },
10
+ inspector: { defaultWidth: 280 },
11
+ "assets-panel": {
12
+ appliesTo: ['editor', 'whiteboard'], // nested array — not top-level keys
13
+ },
14
+ comments: { defaultWidth: 320 },
15
+ };
16
+
17
+ export function PanelTag({ id }: { id: keyof typeof PANELS }) {
18
+ return (
19
+ <span className="panel-tag" style={{ color: '#1db954' }}>
20
+ {id}
21
+ </span>
22
+ );
23
+ }
@@ -0,0 +1,5 @@
1
+ # Expected extraction for sample.ts (§3.5 set equality).
2
+ kind: ts-union
3
+ file: sample.ts
4
+ symbol: ReleaseStatus
5
+ values: [draft, in-review, published, deprecated]
@@ -0,0 +1,9 @@
1
+ // D-009 extractor fixture — ts-union (facet: the string-literal members of a
2
+ // type union). Adversarial-but-extractable: leading-pipe multi-line union
3
+ // with an interleaved comment. Pair: EXPECTED.yaml.
4
+ export type ReleaseStatus =
5
+ | 'draft'
6
+ | 'in-review'
7
+ // terminal states below
8
+ | 'published'
9
+ | 'deprecated';
@@ -0,0 +1,37 @@
1
+ #!/bin/sh
2
+ # unknown-knowledge pre-commit hook — blocking validation (UCS-1157).
3
+ #
4
+ # THIN BY CONSTRUCTION. This wrapper invokes one engine command and exits
5
+ # with its code, unchanged. It computes no verdict, suppresses no finding,
6
+ # and has no mode that makes it pass — there is deliberately no bypass
7
+ # variable to read, because a hook with an off switch enforces nothing.
8
+ # Protocol compliance is a property of the mechanism, not of agent
9
+ # obedience: the same validator CI runs, run before the commit exists.
10
+ #
11
+ # Not a test seam. The tested surface is the wrapped command
12
+ # (`engine/validate.js`, tests/validate.test.js); testing it IS testing
13
+ # this hook, because this file adds nothing to test. Wiring is reviewed
14
+ # the way the per-IDE wrappers are — read it once, confirm it is a
15
+ # pointer, and trust the command it points at.
16
+ #
17
+ # Wire it (the client's own git config — the kit never writes .git/):
18
+ # ln -s ../../unknown-knowledge/hooks/pre-commit .git/hooks/pre-commit
19
+ # or set core.hooksPath at the seeded directory. Either way the client
20
+ # opts in: seeding a hook is not installing one.
21
+ #
22
+ # Exit codes are the engine's, propagated verbatim (PRD §5):
23
+ # 0 — the store is structurally sound; the commit proceeds.
24
+ # 1 — the check ran and found something; the commit is refused.
25
+ # 2 — the check never ran; the commit is refused. A check that never
26
+ # ran is a blocking defect, never a silent pass.
27
+ #
28
+ # KIT_DIR names the seeded root when it is not the default; UK_ROOT names
29
+ # the repo root when the hook runs from elsewhere. Both are location
30
+ # arguments, never gate arguments — neither can turn the check off.
31
+ set -u
32
+
33
+ KIT_DIR="${KIT_DIR:-unknown-knowledge}"
34
+ UK_ROOT="${UK_ROOT:-.}"
35
+
36
+ node "$UK_ROOT/$KIT_DIR/engine/validate.js" --root "$UK_ROOT"
37
+ exit $?
@@ -0,0 +1,66 @@
1
+ #!/bin/sh
2
+ # unknown-knowledge reverse-lookup hook — automatic attribution (UCS-1157).
3
+ #
4
+ # THIN BY CONSTRUCTION, exactly like the pre-commit hook: it collects the
5
+ # touched paths git already knows about and hands them to one engine
6
+ # command, exiting with that command's code, unchanged. It reads no leaf,
7
+ # joins nothing, and decides nothing — `engine/resolve.js --paths` is what
8
+ # answers "which leaves and concepts govern this file", and the answer is
9
+ # its output, not this script's.
10
+ #
11
+ # This is the AGENTS.md ACT step (attribute before committing) made
12
+ # automatic. An agent can forget to run the reverse lookup; a hook cannot.
13
+ # That is the whole point: the protocol rides along invisibly rather than
14
+ # depending on anyone remembering it.
15
+ #
16
+ # Not a test seam. The tested surface is the wrapped command
17
+ # (`engine/resolve.js --paths`, tests/resolve.test.js and
18
+ # tests/typed-edges.test.js) — this file adds no behavior to test, and the
19
+ # wiring is reviewed like the per-IDE wrappers.
20
+ #
21
+ # Wire it with an EVENT-NAMED symlink — git runs a hook only if its
22
+ # filename is one of the events git fires, and `reverse-lookup` is not one
23
+ # of them. That matters most under `core.hooksPath` pointed at the seeded
24
+ # directory: git looks there for event names only, so this file would sit
25
+ # next to `pre-commit` and never fire. Give it an event:
26
+ #
27
+ # ln -s ../../unknown-knowledge/hooks/reverse-lookup .git/hooks/prepare-commit-msg
28
+ #
29
+ # (`prepare-commit-msg` runs after the index is staged and before the
30
+ # message editor opens, which is when attribution is still actionable. Git
31
+ # passes it the message file and source as arguments; this script ignores
32
+ # them and reads the staged diff itself.) Under `core.hooksPath` wiring,
33
+ # call it explicitly from your `pre-commit` instead. Either way, wiring it
34
+ # into git is the client's own act — the seeded artifact is the script.
35
+ #
36
+ # Exit codes are the engine's, propagated verbatim (PRD §5):
37
+ # 0 — the lookup ran (including a zero-hit lookup, which is a real
38
+ # answer: nothing in the store governs these files).
39
+ # 2 — the lookup never ran.
40
+ # `resolve.js` never exits 1: reporting what governs a path is not a
41
+ # finding, and this hook is attribution, never a gate. What it prints is
42
+ # what the ACT step obliges you to act on.
43
+ #
44
+ # With no staged changes there is nothing to attribute, so the hook exits
45
+ # 0 without invoking the engine — `--paths` with an empty list is a usage
46
+ # error (exit 2), and an empty diff is not a failure.
47
+ #
48
+ # git's own status is checked BEFORE the join. In a pipeline the shell
49
+ # reports the LAST command's status, so `git diff | paste` would report
50
+ # paste's success even when git failed — leaving PATHS empty and the hook
51
+ # exiting 0 on a lookup that never ran. That is the silent pass this whole
52
+ # design refuses, so the two steps are separate and git's code is read.
53
+ set -u
54
+
55
+ KIT_DIR="${KIT_DIR:-unknown-knowledge}"
56
+ UK_ROOT="${UK_ROOT:-.}"
57
+
58
+ STAGED=$(git diff --cached --name-only --diff-filter=ACMR) || {
59
+ echo "reverse-lookup: git diff failed — the staged paths could not be read, so the lookup never ran" >&2
60
+ exit 2
61
+ }
62
+ [ -z "$STAGED" ] && exit 0
63
+ PATHS=$(printf '%s' "$STAGED" | paste -sd, -)
64
+
65
+ node "$UK_ROOT/$KIT_DIR/engine/resolve.js" --paths "$PATHS" --root "$UK_ROOT"
66
+ exit $?
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
File without changes