@panaversity/ksor 0.0.56 → 0.0.58

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/CHANGELOG.md CHANGED
@@ -1,5 +1,61 @@
1
1
  # @panaversity/ksor
2
2
 
3
+ ## 0.0.58
4
+
5
+ ### Patch Changes
6
+
7
+ - 3807493: Twenty-six sentences that 0.0.44 through 0.0.57 had made false, found by a
8
+ sweep of every document against the tree and the published package, and fixed.
9
+
10
+ The two that ship on npm and would have stopped a reader: the package README
11
+ told `npx` users to run `pnpm install` — on the npm project `npx` emits, that
12
+ installs nothing under `system/site` and `pnpm dev` fails with `next: command
13
+ not found` (the tutorial had this exact fix; the README never got it) — and it
14
+ still advertised the two companion skills 0.0.56 removed. It also claimed its
15
+ abstention envelope was "pasted as it appeared" from a tutorial that never
16
+ reaches one; it now says what that block is.
17
+
18
+ The rest: `calibrate --check` was documented in three places (ingesting.md,
19
+ the CLI help, and by implication the scaffold) as "always exits 0" — a verdict
20
+ always does; an unreachable database exits 3 as for every verb, and the docs
21
+ now say so before anyone puts it in CI. `tool-surface.md` carried two copies of
22
+ one bullet, the stale one missing `audit`. `upgrading.md` gave `ksor init` a
23
+ path, which it refuses. Three documents said "two" authorization recipes where
24
+ `authorization.md` has four. The emitted `instance.md` still described "all
25
+ four study attachments" on a starter trimmed to one companion in 0.0.44;
26
+ `intake-interview` and `people.yaml` said add-sources writes display names (it
27
+ does not); the scaffold README counted two negated `.ksor/` paths where there
28
+ are three; two token figures in the emitted AGENTS.md predated their own
29
+ re-measurement; and a sentence about "this record's own seven" embeds
30
+ described a record that is not the one it is emitted into. Root AGENTS.md said
31
+ "three tiers" above a list of four. `docs/status.md` described the seed quiz
32
+ and deck as shipping (trimmed in 0.0.44), the kernel as "in progress" (released
33
+ in 0.0.8–0.0.18), and carried yesterday's date. The introduction tutorial's
34
+ "where to go next" now links the two tutorials that exist and numbers the rest
35
+ as the index does; hello world said "five skills"; make-it-yours said `pnpm dev`
36
+ in an npm project.
37
+
38
+ Every fix is a document catching up to code, except the CLI help line, which
39
+ is text.
40
+
41
+ ## 0.0.57
42
+
43
+ ### Patch Changes
44
+
45
+ - 07cddea: The tutorials are numbered in reading order, and the package README lists all
46
+ three.
47
+
48
+ The introduction is now `00`, hello world `01`, and _Make it yours_ stays `02`
49
+ — so the two hands-on tutorials that follow each other are no longer separated
50
+ by the 1,800-line introduction, and every existing cross-reference ("tutorial
51
+ 2", "tutorial 4") stays true. The introduction's title drops "Tutorial 1"; it is
52
+ the introduction. A one-line pointer stays at the old `00-hello-world.md` for
53
+ one release, because the README that shipped in 0.0.56 links it.
54
+
55
+ Both READMEs gain a three-row table keyed on who each tutorial is for, and a
56
+ test now holds every link into `docs/tutorials/` — relative or GitHub URL —
57
+ to a file that exists.
58
+
3
59
  ## 0.0.56
4
60
 
5
61
  ### Patch Changes
package/README.md CHANGED
@@ -12,17 +12,20 @@ when the corpus does not cover the question.
12
12
  ```bash
13
13
  npx @panaversity/ksor@latest init my-sor
14
14
  cd my-sor
15
- pnpm install
16
- pnpm dev # the site, live at http://localhost:3000
15
+ npm install
16
+ npm run dev # the site, live at http://localhost:3000
17
17
  ```
18
18
 
19
19
  Then write a document and publish it:
20
20
 
21
21
  ```console
22
- $ pnpm exec ksor build
22
+ $ npx ksor build
23
23
  ksor build: 6 document(s), 5 admitted to a machine surface
24
24
  ```
25
25
 
26
+ (`npx` emits an npm project; `pnpm dlx` or `bunx` emit that manager's, and
27
+ the README it writes speaks that manager throughout.)
28
+
26
29
  **Six documents, five admitted.** The one you just wrote is a `draft`, so it
27
30
  reaches nothing an AI agent reads — not `llms.txt`, not the markdown twins —
28
31
  until a human approves it. Approve it and the count moves. That is the whole
@@ -42,9 +45,19 @@ where it came from:
42
45
  { "ok": false, "abstained": true, "gate": { "floor": 0.622 } }
43
46
  ```
44
47
 
45
- **[Hello world](https://github.com/panaversity/ksor/blob/main/docs/tutorials/00-hello-world.md)**
48
+ **[Hello world](https://github.com/panaversity/ksor/blob/main/docs/tutorials/01-hello-world.md)**
46
49
  walks all of that in about fifteen minutes. Every command and output in it was
47
- run and pasted as it appeared including the ones above.
50
+ run and pasted as it appeared. The envelopes above show the SHAPE of an answer
51
+ and a refusal; the refusal needs a calibrated floor, which hello world defers
52
+ to its own tutorial.
53
+
54
+ The three so far, in reading order — pick by what you want from it:
55
+
56
+ | | read this if |
57
+ | --- | --- |
58
+ | [00 · Introduction](https://github.com/panaversity/ksor/blob/main/docs/tutorials/00-introduction-to-ksor.md) | you want to understand why this exists — no technical background needed |
59
+ | [01 · Hello world](https://github.com/panaversity/ksor/blob/main/docs/tutorials/01-hello-world.md) | you want to see it work in fifteen minutes — Node only, nothing else |
60
+ | [02 · Make it yours](https://github.com/panaversity/ksor/blob/main/docs/tutorials/02-make-it-yours.md) | you finished hello world and want a record that is only yours — a file in, a person's knowledge in, the samples out |
48
61
 
49
62
  One command emits a complete governed project: the record (`knowledge/`,
50
63
  plain CommonMark), a working documentation site with hot reload, offline
@@ -92,13 +105,9 @@ that document's page and nowhere else:
92
105
  | `<doc>.flashcards.yaml` | a recall deck, at the end |
93
106
  | `<doc>.quiz.yaml` | a multiple-choice check, at the end |
94
107
 
95
- Ask your coding agent `make slides for knowledge/expenses/approvals.md`, or
96
- `summarise knowledge/expenses/approvals.md` and the `make-slides` and
97
- `make-summary` skills write the attachment from the document, check every claim
98
- and number back against it, and report what they left out because the document
99
- did not support it. A summary is checked section by section, because one that
100
- covers the opening and trails off leaves a reader believing they have the whole
101
- document.
108
+ Companions are ordinary files beside the document. Write them yourself or ask
109
+ your coding agent for one, and hold it to the rule the emitted AGENTS.md
110
+ states: a companion may only say what its document says.
102
111
 
103
112
  An attachment is **part of its document**: no URL, no sidebar row, no
104
113
  `llms.txt` line, and no id an agent can cite. It takes its audience and any
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as resolveCommand, r as verbs, t as exitCodes } from "./src-dqpI-p1a.mjs";
3
- import { A as parseViewer, B as tallyHandlers, C as contentPoolMin, D as outlineHandler, E as keyRingFromEnv, F as recordIsUndescribed, G as z$1, H as validateViewer, I as runProbe$1, L as searchHandler, M as prewarmPool, N as providerKeyEnv$1, O as parseInstanceText$1, P as readHandler, R as servingPolicy$1, S as contentPool$1, T as instancePathOf$1, U as withPgRetry$1, V as tlsPosture, W as withProbeDeadline$1, _ as assertGovernanceServable$1, a as GovernanceGateError$1, b as checkEmbeddingSpace$1, c as McpServer$1, d as READ_ONLY, f as READ_OUTPUT, g as TextSearchConfigMismatch, h as TRUST_TIERS$1, i as FLOOR, j as pooledEndpointFor, k as parseTrustFloor, l as MissingProviderKeyError$1, m as SchemaVersionError, n as ContentStoreError$1, o as MAX_OUTLINE_LIMIT, p as SEARCH_OUTPUT, r as EmbeddingSpaceMismatch$1, t as AudienceError$1, u as OUTLINE_OUTPUT, v as assertSchemaCompatible, w as embedQueryVlit, x as composeInstructions, y as buildShippedProvider$1, z as storedTextSearchConfig } from "./gateway-api-C0vL3oOK-D24n786A.mjs";
3
+ import { A as parseViewer, B as tallyHandlers, C as contentPoolMin, D as outlineHandler, E as keyRingFromEnv, F as recordIsUndescribed, G as z$1, H as validateViewer, I as runProbe$1, L as searchHandler, M as prewarmPool, N as providerKeyEnv$1, O as parseInstanceText$1, P as readHandler, R as servingPolicy$1, S as contentPool$1, T as instancePathOf$1, U as withPgRetry$1, V as tlsPosture, W as withProbeDeadline$1, _ as assertGovernanceServable$1, a as GovernanceGateError$1, b as checkEmbeddingSpace$1, c as McpServer$1, d as READ_ONLY, f as READ_OUTPUT, g as TextSearchConfigMismatch, h as TRUST_TIERS$1, i as FLOOR, j as pooledEndpointFor, k as parseTrustFloor, l as MissingProviderKeyError$1, m as SchemaVersionError, n as ContentStoreError$1, o as MAX_OUTLINE_LIMIT, p as SEARCH_OUTPUT, r as EmbeddingSpaceMismatch$1, t as AudienceError$1, u as OUTLINE_OUTPUT, v as assertSchemaCompatible, w as embedQueryVlit, x as composeInstructions, y as buildShippedProvider$1, z as storedTextSearchConfig } from "./gateway-api-DvM2mVtD-BXmUS4T8.mjs";
4
4
  import { appendFileSync, chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { InMemoryTransport, LATEST_PROTOCOL_VERSION, createMcpHandler } from "@modelcontextprotocol/server";
@@ -17,7 +17,7 @@ import { Document, YAMLParseError, isCollection, isMap, isPair, isSeq, parseAllD
17
17
  import { parseArgs } from "node:util";
18
18
  import { readFile } from "node:fs/promises";
19
19
  import { execFileSync, spawnSync } from "node:child_process";
20
- //#region ../content-gateway/dist/main-BoKhKcP0.mjs
20
+ //#region ../content-gateway/dist/main-C9M1ZaXh.mjs
21
21
  /**
22
22
  * The default registration — and the ORIGINAL of the file `ksor init` emits.
23
23
  *
@@ -4710,7 +4710,7 @@ async function withPgRetry(op, options = {}) {
4710
4710
  throw lastError;
4711
4711
  }
4712
4712
  //#endregion
4713
- //#region ../content/dist/commands-CO9-bQnb.mjs
4713
+ //#region ../content/dist/commands-BvRSdIZA.mjs
4714
4714
  /**
4715
4715
  * EVAL-LOCKED constants, quarried verbatim from the oracle
4716
4716
  * (sor-agentfactory @ b554f91, config.py) — changing any of these is a
@@ -10285,7 +10285,8 @@ Usage:
10285
10285
  --check reads the record's OWN logged searches instead and reports how
10286
10286
  the declared floor is holding against them — no provider key, no
10287
10287
  embedding call, no LLM. A monitor, never a gate: it says what to
10288
- re-measure and always exits 0.
10288
+ re-measure, and a verdict always exits 0 — the environment exits 3, as
10289
+ for every verb.
10289
10290
  ksor grant --instance PATH [--revoke]
10290
10291
  Authorize ingest for the instance's tenant (the row row-level security
10291
10292
  requires), or withdraw it. Idempotent; reports the state it established.
@@ -6,7 +6,7 @@ import { z, z as z$1 } from "zod";
6
6
  import path, { join } from "node:path";
7
7
  import { createHash, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
8
8
  import pg from "pg";
9
- //#region ../content-gateway/dist/gateway-api-C0vL3oOK.mjs
9
+ //#region ../content-gateway/dist/gateway-api-DvM2mVtD.mjs
10
10
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
11
11
  var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
12
12
  /**
package/dist/gateway.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { D as outlineHandler, F as recordIsUndescribed, G as z$1, L as searchHandler, P as readHandler, c as McpServer$1, d as READ_ONLY, f as READ_OUTPUT, h as TRUST_TIERS, i as FLOOR, o as MAX_OUTLINE_LIMIT, p as SEARCH_OUTPUT, s as MAX_SEARCH_K, u as OUTLINE_OUTPUT, x as composeInstructions } from "./gateway-api-C0vL3oOK-D24n786A.mjs";
1
+ import { D as outlineHandler, F as recordIsUndescribed, G as z$1, L as searchHandler, P as readHandler, c as McpServer$1, d as READ_ONLY, f as READ_OUTPUT, h as TRUST_TIERS, i as FLOOR, o as MAX_OUTLINE_LIMIT, p as SEARCH_OUTPUT, s as MAX_SEARCH_K, u as OUTLINE_OUTPUT, x as composeInstructions } from "./gateway-api-DvM2mVtD-BXmUS4T8.mjs";
2
2
  export { FLOOR, MAX_OUTLINE_LIMIT, MAX_SEARCH_K, McpServer$1 as McpServer, OUTLINE_OUTPUT, READ_ONLY, READ_OUTPUT, SEARCH_OUTPUT, TRUST_TIERS, composeInstructions, outlineHandler, readHandler, recordIsUndescribed, searchHandler, z$1 as z };
package/docs/deploying.md CHANGED
@@ -314,8 +314,8 @@ correct for a genuinely public record or one behind your own gateway; it is not
314
314
  way to make a deploy go green.
315
315
 
316
316
  The alternative is a real authorization server — `KSOR_SSO_URL`,
317
- `KSOR_MCP_RESOURCE_URL`, `KSOR_JWT_ALLOWED_AUDIENCES`, with worked recipes for two
318
- of them in [authorization.md](./authorization.md).
317
+ `KSOR_MCP_RESOURCE_URL`, `KSOR_JWT_ALLOWED_AUDIENCES`, with worked recipes for
318
+ four of them in [authorization.md](./authorization.md).
319
319
 
320
320
  ### Set this on any container host
321
321
 
@@ -573,7 +573,7 @@ auth-off default, and that refusal is the last real step of a deployment. Two
573
573
  ways past it:
574
574
 
575
575
  - **Configure the SSO door** — `KSOR_SSO_URL`, `KSOR_MCP_RESOURCE_URL`,
576
- `KSOR_JWT_ALLOWED_AUDIENCES`. Worked recipes for two different authorization
576
+ `KSOR_JWT_ALLOWED_AUDIENCES`. Worked recipes for four different authorization
577
577
  servers: [authorization.md](./authorization.md).
578
578
  - **Set `KSOR_AUTH=disabled-public`** — a deliberate decision that
579
579
  serves your whole record to anyone who can reach the port. Correct for a
package/docs/index.md CHANGED
@@ -57,8 +57,8 @@ instead of their training memory. The corpus grows with each implemented verb.
57
57
  which a dependency bump reaches a project already scaffolded. Includes the
58
58
  list of files migrate does NOT carry, so you know what to diff by hand.
59
59
  - **[authorization.md](./authorization.md)** — putting the record behind an
60
- authorization server, with worked recipes for two of them, executed rather
61
- than written. `ksor serve` refuses to boot unauthenticated on a public bind,
60
+ authorization server, with worked recipes for four of them two self-hosted,
61
+ one hosted, one an organisation's own — executed rather than written. `ksor serve` refuses to boot unauthenticated on a public bind,
62
62
  so this is the last step of a deployment, not an optional hardening pass.
63
63
  - Exit codes are a contract: `1` refused (first stderr line is a stable
64
64
  slug such as `error: bad-name`, followed by a remedy), `2` designed but
package/docs/ingesting.md CHANGED
@@ -50,7 +50,7 @@ root**, where `instance.md` and `package.json` live.
50
50
 
51
51
  ```sh
52
52
  pnpm provision # ksor schema --apply, then ksor grant
53
- pnpm refresh # ksor ingest --flip, then ksor gc
53
+ pnpm refresh # ksor build, then ksor ingest --flip, then ksor gc
54
54
  ```
55
55
 
56
56
  `provision` is separate because applying DDL and granting ingest are acts an
@@ -289,9 +289,12 @@ decision in this project's own gold rather than a threshold somebody picked.
289
289
  Run it on a schedule, or in your own CI beside `ksor build`. Three things to
290
290
  know about what it is:
291
291
 
292
- - **It never fails a run.** It always exits 0. A stale floor wants
293
- re-measuring, and failing a build for one would make the shortest way out
294
- deleting `vector_floor` — turning the gate off entirely to clear the error.
292
+ - **A verdict never fails a run.** STEADY, WATCH and no-data all exit 0: a
293
+ stale floor wants re-measuring, and failing a build for one would make the
294
+ shortest way out deleting `vector_floor` — turning the gate off entirely to
295
+ clear the error. What does exit non-zero is the environment, the same way it
296
+ does for every verb: 3 when `KSOR_DB_URL` is unset or the database is
297
+ unreachable, 1 on a bad flag. Put it in CI knowing that.
295
298
  - **It reads traffic, so it needs traffic**, and it says so rather than
296
299
  reporting a healthy-looking nothing. It also cannot see questions nobody
297
300
  asked: it can tell you the floor has gone permissive, never that it is too
@@ -144,9 +144,6 @@ made it answer from.
144
144
  only things that can prove a passage came from the governed record. A
145
145
  hand-written one returning fabricated hits with plausible `stable_id`s would
146
146
  pass every shape check there is.
147
- - **The output schemas.** `SEARCH_OUTPUT`, `OUTLINE_OUTPUT`, `READ_OUTPUT` carry
148
- `provenance`, each hit's `governance`, the `snapshot` token and `gate`. A
149
- record that reshaped them would still look like a KSoR and no longer be one.
150
147
  - **The output schemas.** `SEARCH_OUTPUT`, `OUTLINE_OUTPUT`, `READ_OUTPUT` carry
151
148
  `provenance`, each hit's `governance`, the `snapshot` token, `gate`, and
152
149
  `audit`. A record that reshaped them would still look like a KSoR and no
package/docs/upgrading.md CHANGED
@@ -76,7 +76,7 @@ These are yours, and no release touches them. Diff them against a fresh
76
76
  - `pnpm-workspace.yaml` / `.npmrc` and any lockfile
77
77
 
78
78
  ```sh
79
- npx @panaversity/ksor@latest init /tmp/fresh
79
+ (cd /tmp && npx @panaversity/ksor@latest init fresh) # init takes a NAME, not a path
80
80
  diff -ru /tmp/fresh/vercel.json ./vercel.json
81
81
  ```
82
82
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panaversity/ksor",
3
- "version": "0.0.56",
3
+ "version": "0.0.58",
4
4
  "description": "Knowledge System of Record — compile governed markdown into a static site for people and an MCP server for AI agents, with citations and measured abstention.",
5
5
  "keywords": [
6
6
  "abstention",
@@ -72,8 +72,8 @@
72
72
  "tsdown": "0.22.14",
73
73
  "typescript": "7.0.2",
74
74
  "vitest": "^4.1.10",
75
- "@panaversity/ksor-content": "0.0.0",
76
- "@panaversity/ksor-content-gateway": "0.0.0"
75
+ "@panaversity/ksor-content-gateway": "0.0.0",
76
+ "@panaversity/ksor-content": "0.0.0"
77
77
  },
78
78
  "engines": {
79
79
  "node": ">=24"
@@ -146,11 +146,12 @@ never an email address.
146
146
  MAP from each actor to its natural name — `"human:bashiraziz": Bashir Aziz`.
147
147
  Keyed by the actor exactly as the record stores it, quoted because it
148
148
  contains a colon. Nothing else — the site looks the actor up at render time,
149
- so pages read "Owner · Bashir Aziz" instead of "Owner · human:bashiraziz". Every skill that records a governance
150
- act (this one, add-sources when it names a `ksor.owner`, `ksor takedown` for
151
- withdrawals) asks the owner for a natural name whenever it is about to write
152
- an actor that isn't in `people.yaml` yet the owner is the only source of a
153
- display name, never a convention-based guess.
149
+ so pages read "Owner · Bashir Aziz" instead of "Owner · human:bashiraziz". This
150
+ is the skill that writes actors into the policy, so it is the one that asks
151
+ the owner for a natural name for each — the owner is the only source of a
152
+ display name, never a convention-based guess. An actor that arrives later
153
+ (an owner named in a document, an approver added by hand) gets its entry
154
+ when the owner adds one; the site prints the identifier until then.
154
155
  - **Offer to start replacing the starter documents — they are already
155
156
  published.** All five ship `status: stable`, approved by
156
157
  `ksor-starter/KSOR-STAMP-VERSION`, so the site and `llms.txt` carry them from
@@ -146,11 +146,12 @@ never an email address.
146
146
  MAP from each actor to its natural name — `"human:bashiraziz": Bashir Aziz`.
147
147
  Keyed by the actor exactly as the record stores it, quoted because it
148
148
  contains a colon. Nothing else — the site looks the actor up at render time,
149
- so pages read "Owner · Bashir Aziz" instead of "Owner · human:bashiraziz". Every skill that records a governance
150
- act (this one, add-sources when it names a `ksor.owner`, `ksor takedown` for
151
- withdrawals) asks the owner for a natural name whenever it is about to write
152
- an actor that isn't in `people.yaml` yet the owner is the only source of a
153
- display name, never a convention-based guess.
149
+ so pages read "Owner · Bashir Aziz" instead of "Owner · human:bashiraziz". This
150
+ is the skill that writes actors into the policy, so it is the one that asks
151
+ the owner for a natural name for each — the owner is the only source of a
152
+ display name, never a convention-based guess. An actor that arrives later
153
+ (an owner named in a document, an approver added by hand) gets its entry
154
+ when the owner adds one; the site prints the identifier until then.
154
155
  - **Offer to start replacing the starter documents — they are already
155
156
  published.** All five ship `status: stable`, approved by
156
157
  `ksor-starter/KSOR-STAMP-VERSION`, so the site and `llms.txt` carry them from
@@ -26,7 +26,7 @@
26
26
  # name has to keep rendering on those acts.
27
27
  #
28
28
  # Optional. An actor with no entry renders exactly as stored, as it did before
29
- # this file existed. The intake and add-sources skills offer to add one; the
30
- # owner can also edit this file by hand — it is theirs.
29
+ # this file existed. The intake interview offers to add one; the owner can
30
+ # also edit this file by hand — it is theirs.
31
31
  version: "0.1"
32
32
  people: {}
@@ -423,7 +423,7 @@ governance block every hit now carries:
423
423
  Three edits pay for themselves:
424
424
 
425
425
  - **Delete a tool nothing calls.** Removing `outline` and `read` gives back
426
- ~2,152 tokens for the whole session.
426
+ ~2,310 tokens for the whole session.
427
427
  - **Say what this record covers**, above `FLOOR.search`. It is how an agent with
428
428
  several records attached picks yours; name the subject AND the boundary.
429
429
  - **Set `k`** in the input schema — it is the lever on reply size.
@@ -899,8 +899,7 @@ CI — and a first deploy without it serves an empty record. Full walkthrough:
899
899
  click is informed.
900
900
 
901
901
  **You do not state a height.** A page carried in the record is measured, so
902
- the frame is exactly as tall as what it holds on this record's own seven,
903
- to the pixel. A number written into a document would be a number some other
902
+ the frame is exactly as tall as what it holds, to the pixel. A number written into a document would be a number some other
904
903
  measure makes wrong.
905
904
 
906
905
  **Carry the page in where you can.** A file named `<name>.sim.html`, sitting
@@ -698,7 +698,7 @@ different coding agent's way of finding the same working contract.
698
698
  | `.gemini/settings.json` | points Gemini CLI at `AGENTS.md`; Gemini does not read that filename on its own. |
699
699
  | `.github/workflows/validate.yml` | your CI: runs the same checker on every pull request and push to main. |
700
700
  | `.gitattributes` | markdown is checked out byte-stable on every platform, so the same commit hashes the same everywhere. |
701
- | `.gitignore` | keeps build output, `node_modules/`, and `.env` out of the record's history — and negates two paths inside `.ksor/`, because the policy and the ledger ARE the record. |
701
+ | `.gitignore` | keeps build output, `node_modules/`, and `.env` out of the record's history — and negates three paths inside `.ksor/`, because the policy, the ledger and the phone book ARE the record. |
702
702
 
703
703
  `format-checker` deliberately contains a program, `check.mjs`, and not only
704
704
  prose: rules that are only written down cannot refuse anything.
@@ -41,9 +41,8 @@ record wins.
41
41
 
42
42
  Everything above describes KSoR itself. It ships filled in so that a fresh
43
43
  project has a real governed corpus on the first `pnpm dev` — five approved
44
- documents, three of them inside a folder, and one carrying all four study
45
- attachments (a summary, slides, flashcards and a quiz) — instead of an empty
46
- shelf and a placeholder.
44
+ documents, three of them inside a folder, and one carrying a summary
45
+ companion — instead of an empty shelf and a placeholder.
47
46
  The documents live in `knowledge/`; delete them as your own knowledge arrives.
48
47
 
49
48
  Be deliberate about replacing it, because a starter that describes the wrong