@panaversity/ksor 0.0.54 → 0.0.56
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 +369 -0
- package/dist/checker/check-main.mjs +5 -2
- package/dist/cli.mjs +56 -17
- package/dist/{gateway-api-uhx2l1kC-C2BAxISt.mjs → gateway-api-C0vL3oOK-D24n786A.mjs} +25 -4
- package/dist/gateway.d.mts +2 -2
- package/dist/gateway.mjs +1 -1
- package/docs/deploying.md +7 -1
- package/docs/ingesting.md +10 -5
- package/package.json +1 -1
- package/templates/scaffold/.agents/skills/add-sources/SKILL.md +129 -84
- package/templates/scaffold/.agents/skills/add-sources/verify.mjs +45 -0
- package/templates/scaffold/.agents/skills/format-checker/SKILL.md +18 -46
- package/templates/scaffold/.agents/skills/format-checker/check.mjs +3 -0
- package/templates/scaffold/.agents/skills/intake-interview/SKILL.md +16 -8
- package/templates/scaffold/.claude/skills/add-sources/SKILL.md +129 -84
- package/templates/scaffold/.claude/skills/add-sources/verify.mjs +45 -0
- package/templates/scaffold/.claude/skills/format-checker/SKILL.md +18 -46
- package/templates/scaffold/.claude/skills/format-checker/check.mjs +3 -0
- package/templates/scaffold/.claude/skills/intake-interview/SKILL.md +16 -8
- package/templates/scaffold/AGENTS.md +21 -10
- package/templates/scaffold/README.md +47 -16
- package/templates/scaffold/env.example +6 -1
- package/templates/scaffold/gitignore +4 -3
- package/templates/scaffold/system/site/lib/lock.ts +8 -1
- package/templates/scaffold/system/site/lib/people-rule.ts +56 -0
- package/templates/scaffold/system/site/lib/people.ts +5 -24
- package/templates/scaffold/system/site/lib/stage-knowledge.ts +2 -0
- package/templates/scaffold/system/site/record/load.ts +11 -1
- package/templates/scaffold/system/site/record/lock.ts +12 -0
- package/templates/scaffold/.agents/skills/make-slides/SKILL.md +0 -162
- package/templates/scaffold/.agents/skills/make-summary/SKILL.md +0 -153
- package/templates/scaffold/.claude/skills/make-slides/SKILL.md +0 -162
- package/templates/scaffold/.claude/skills/make-summary/SKILL.md +0 -153
|
@@ -1,91 +1,136 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: add-sources
|
|
3
|
-
description: Turn
|
|
3
|
+
description: Turn what the owner has into governed knowledge in knowledge/ — a document, a page, pasted text, notes, or something nobody ever wrote down that they tell you. Use when the owner shares material to add, says "add this to the knowledge base", asks how to get existing content in, or wants to write down what they know from memory with no source to hand. Not for editing the site.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "
|
|
5
|
+
version: "2.0.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Add sources
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
10
|
+
Getting knowledge into the record is the everyday work of this project. The
|
|
11
|
+
rules that make it _governed_ are in `AGENTS.md` → "Writing knowledge" (shape,
|
|
12
|
+
frontmatter, audience, `draft` until the owner approves, copy values exactly,
|
|
13
|
+
never invent). This file is the ACT: how a source becomes a document that
|
|
14
|
+
passes those rules, whatever kind of source it is.
|
|
15
|
+
|
|
16
|
+
## The source is one of two kinds — and usually both
|
|
17
|
+
|
|
18
|
+
**A file** — PDF, Word, slides, HTML, a Notion export, pasted text — is
|
|
19
|
+
knowledge that already exists somewhere. Your job is to move it without losing
|
|
20
|
+
anything: convert it, structure it, and prove every load-bearing value survived.
|
|
21
|
+
|
|
22
|
+
**A person** — "it's just how we do it" — is knowledge that exists nowhere
|
|
23
|
+
yet. Your job is to draw it out by asking, write it as the record and not as a
|
|
24
|
+
transcript, and record only what they confirm.
|
|
25
|
+
|
|
26
|
+
A real owner has both: the policy PDF, and the exception everyone knows that
|
|
27
|
+
the PDF never mentions. So the person step runs EVERY time, after the file:
|
|
28
|
+
"what does this not cover?" is the question that finds the pages nobody wrote.
|
|
29
|
+
|
|
30
|
+
## When the source is a file
|
|
31
|
+
|
|
32
|
+
1. **Extract the text first, into a scratch file outside `knowledge/`.** The
|
|
33
|
+
extraction is what you convert from and what you verify against, so it has
|
|
34
|
+
to be a file you can grep, not something you remember reading:
|
|
35
|
+
|
|
36
|
+
| format | extractor |
|
|
37
|
+
| ------------------------ | ------------------------------------------------------------------- |
|
|
38
|
+
| PDF | `pdftotext -layout in.pdf /tmp/in.txt` (poppler) |
|
|
39
|
+
| docx / odt / html / epub | `pandoc in.docx -t gfm -o /tmp/in.md` |
|
|
40
|
+
| docx on macOS | `textutil -convert txt in.docx -output /tmp/in.txt` (built in) |
|
|
41
|
+
| anything | `markitdown in.pdf > /tmp/in.md`, if installed |
|
|
42
|
+
| Notion / Obsidian export | already markdown — no extraction needed; the file IS the extraction |
|
|
43
|
+
|
|
44
|
+
None on `PATH`? Read the file directly (your Read tool opens PDFs) and say so
|
|
45
|
+
in your report — there is then no extraction to verify against, and step 5
|
|
46
|
+
degrades to re-reading the source by eye. That is a weaker check, and the
|
|
47
|
+
owner must be told it was the check that ran.
|
|
48
|
+
|
|
49
|
+
**Empty extraction — whitespace, form-feeds, nothing — means the PDF has no
|
|
50
|
+
text layer.** Stop and tell the owner: "This is a scanned image. I can read it
|
|
51
|
+
as a picture, but I cannot promise the numbers in it are right, and a wrong
|
|
52
|
+
threshold in a system of record is worse than a missing page. Give me a text
|
|
53
|
+
PDF, or paste the section you need." Do not OCR it and hope.
|
|
54
|
+
|
|
55
|
+
2. **Decide the shape of the RECORD, not of one file.** A 200-page manual is not
|
|
56
|
+
one document. One document per topic — the unit someone would ask a question
|
|
57
|
+
about — placed where its path is the identity it should have, with `order:`
|
|
58
|
+
set to reading order. Show the owner the proposed tree before writing it.
|
|
59
|
+
|
|
60
|
+
3. **Convert to CommonMark a person would have written.** Real headings from
|
|
61
|
+
the document's own structure (never an `# h1` — the title is the frontmatter),
|
|
62
|
+
real lists, real tables; images extracted and placed beside the document
|
|
63
|
+
with relative links. Strip page furniture: running headers and footers, page
|
|
64
|
+
numbers, "Page 4 of 12", the table of contents. Keep the source's own words
|
|
65
|
+
for anything load-bearing.
|
|
66
|
+
|
|
67
|
+
4. **Name the source precisely** in `sources` — a URL where one exists,
|
|
68
|
+
otherwise the descriptor that governs ("Finance policy manual §4.2, 2025
|
|
69
|
+
edition"; "internal docs" governs nothing) — and cite it from the claim with
|
|
70
|
+
a footnote whose label is that source's `id`.
|
|
71
|
+
|
|
72
|
+
5. **Verify — do not trust yourself.** Run the shipped check against the
|
|
73
|
+
extraction from step 1:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
node .agents/skills/add-sources/verify.mjs /tmp/in.txt knowledge/<path>.md
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
It lists every load-bearing token in the document's body — numbers, dates,
|
|
80
|
+
thresholds, codes, capitalised names — that does not appear in the
|
|
81
|
+
extraction. Each one is either a value you changed (fix it, verbatim) or a
|
|
82
|
+
value you introduced (delete it, or turn it into an `Open question:` line
|
|
83
|
+
for the owner). A value that passes was in the source; nothing more is
|
|
84
|
+
claimed. Frontmatter is exempt, because its title and description are your
|
|
85
|
+
words by design.
|
|
86
|
+
|
|
87
|
+
## When the source is a person
|
|
88
|
+
|
|
89
|
+
1. **Ask, one question at a time, in their words.** Who triggers this? What
|
|
90
|
+
happens first, then next? Who has to approve, and at what threshold? What
|
|
91
|
+
goes wrong, and what is the exception? Follow up until each answer is
|
|
92
|
+
concrete enough that someone who was not in the room could act on it —
|
|
93
|
+
"what would someone actually ask this?" gets further than "define the
|
|
94
|
+
boundary".
|
|
95
|
+
|
|
96
|
+
2. **Draft as the record, not as a transcript.** One document per topic. Their
|
|
97
|
+
sentences, tightened — never your inference about what they must have
|
|
98
|
+
meant. Anything they did not say, or said they were not sure of, becomes an
|
|
99
|
+
`Open question:` line in the document. It does not become prose.
|
|
100
|
+
|
|
101
|
+
3. **The source is the conversation, and it is named like any other.** No
|
|
102
|
+
`provenance:` key exists; the attestation goes in `sources`:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
sources:
|
|
106
|
+
- id: ops-interview-2026-08-21
|
|
107
|
+
title: Interview with J. Smith, Head of Operations
|
|
108
|
+
resource: "Interview with human:jsmith (Head of Operations), 2026-08-21T10:00:00Z, conducted by human:you"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Who, their role, the instant, and who asked. That is a claim nobody can
|
|
112
|
+
check against a file, and the pull request that adds it is the only thing
|
|
113
|
+
standing behind it — say so if the owner asks what "verified" would mean
|
|
114
|
+
here. No transcript is kept: raw unreviewed speech does not belong in a
|
|
115
|
+
governed record, and the checker refuses a `.txt` there anyway.
|
|
116
|
+
|
|
117
|
+
4. **Two people describe one process differently — surface it, never smooth
|
|
118
|
+
it.** Two cited statements, each with its own footnote, and the
|
|
119
|
+
disagreement flagged to the owner. Which one becomes `stable` is an
|
|
120
|
+
approval, not an edit.
|
|
121
|
+
|
|
122
|
+
## Finish — every batch, either kind
|
|
123
|
+
|
|
124
|
+
- `pnpm check`, and obey what it prints.
|
|
125
|
+
- `ksor build`: it regenerates every folder's `index.md` and writes the lock.
|
|
126
|
+
- **Read it back on the site.** `pnpm dev` renders the real page, drafts
|
|
127
|
+
marked; that page is what the owner confirms against, not a message in a
|
|
128
|
+
terminal. "Their words, tightened — never your invention" is the standard,
|
|
129
|
+
and it is theirs to say whether you met it.
|
|
130
|
+
- **Then ask them to approve it — and write down what they said.** A draft
|
|
131
|
+
reaches no machine surface: no `llms.txt`, no `/md/` twin, nothing for an
|
|
132
|
+
agent to cite. Until the owner says "approved" and you record
|
|
133
|
+
`ksor.approval: { by: <their handle>, at: <now> }` with `status: stable`,
|
|
134
|
+
the record still publishes nothing of theirs. Never record an approval
|
|
135
|
+
nobody gave.
|
|
136
|
+
- Commit the documents, the indexes and the lock together.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Did the document keep its source's load-bearing values?
|
|
3
|
+
//
|
|
4
|
+
// node verify.mjs <extraction.txt> <document.md>
|
|
5
|
+
//
|
|
6
|
+
// Exit 0 when every load-bearing token in the document's BODY appears in the
|
|
7
|
+
// extraction; exit 1 and print each one that does not, one per line.
|
|
8
|
+
//
|
|
9
|
+
// What "load-bearing" means here: numbers (with their separators — 10,000 and
|
|
10
|
+
// 10000 are different claims about the source), dates, codes, and runs of two
|
|
11
|
+
// or more capitalised words (a name). Matched case-folded and with whitespace
|
|
12
|
+
// collapsed, because an extraction shouts its headings and wraps its lines.
|
|
13
|
+
//
|
|
14
|
+
// What this proves, and no more: a token that PASSES is present in the source.
|
|
15
|
+
// A token that FAILS was changed or introduced — either way, look at it. It
|
|
16
|
+
// cannot tell a paraphrase from an invention, and it cannot see a value that
|
|
17
|
+
// was dropped. It is a floor under model-driven conversion, which is highest
|
|
18
|
+
// fidelity for layout and lowest for exact values (issue #31).
|
|
19
|
+
//
|
|
20
|
+
// Plain Node, no dependencies, safe to copy: `.agents/skills/` is the owner's.
|
|
21
|
+
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
|
|
24
|
+
const [, , extractionPath, documentPath] = process.argv;
|
|
25
|
+
if (!extractionPath || !documentPath) {
|
|
26
|
+
console.error("usage: node verify.mjs <extraction.txt> <document.md>");
|
|
27
|
+
process.exit(2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const fold = (s) => s.toLowerCase().replace(/\s+/g, " ");
|
|
31
|
+
|
|
32
|
+
const extraction = fold(readFileSync(extractionPath, "utf8"));
|
|
33
|
+
const raw = readFileSync(documentPath, "utf8");
|
|
34
|
+
|
|
35
|
+
// Body only: frontmatter is the agent's own words by design (title,
|
|
36
|
+
// description, ids). Footnote labels and definition prefixes are ids too.
|
|
37
|
+
const body = raw.replace(/^---\n[\s\S]*?\n---\n?/, "").replace(/\[\^[^\]]+\]:?/g, " ");
|
|
38
|
+
|
|
39
|
+
const tokens = new Set();
|
|
40
|
+
for (const m of body.matchAll(/\d[\d,.:/-]*\d|\d/g)) tokens.add(m[0]);
|
|
41
|
+
for (const m of body.matchAll(/\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)+\b/g)) tokens.add(m[0]);
|
|
42
|
+
|
|
43
|
+
const missing = [...tokens].filter((t) => !extraction.includes(fold(t))).sort();
|
|
44
|
+
for (const t of missing) console.log(t);
|
|
45
|
+
process.exit(missing.length === 0 ? 0 : 1);
|
|
@@ -2,54 +2,26 @@
|
|
|
2
2
|
name: format-checker
|
|
3
3
|
description: The record's format rules as a runnable check — frontmatter, filenames, links, structure. Use before handing off any change to knowledge/, when a check fails and you need to fix it, or when unsure whether a document is well-formed. Run with `pnpm check` (or node .agents/skills/format-checker/check.mjs).
|
|
4
4
|
metadata:
|
|
5
|
-
version: "
|
|
5
|
+
version: "3.0.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Format checker
|
|
9
9
|
|
|
10
|
-
`pnpm check` runs `check.mjs
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
record is. Do not edit it: `ksor init` writes it and `ksor migrate` rewrites
|
|
14
|
-
both copies of it when you upgrade the tool, so an edit is overwritten rather
|
|
15
|
-
than kept. It is read-only in the other direction too — it reports, and never
|
|
16
|
-
rewrites a file.
|
|
10
|
+
`pnpm check` runs `check.mjs`. The rules it holds the record to are the ones in
|
|
11
|
+
`AGENTS.md` → "Writing knowledge"; this file says only what that section does
|
|
12
|
+
not, which is how to relate to the program.
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
record
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- `.ksor/governance.yaml` exists and names approval and takedown authorities;
|
|
33
|
-
`.ksor/takedowns.yaml` is append-only, every entry by a takedown authority,
|
|
34
|
-
and never names a concept that no longer exists.
|
|
35
|
-
- `index.md` files are generated by `ksor build`, never authored — a stale or
|
|
36
|
-
missing one is refused (`ksor-index-stale`; run `ksor build`). `log.md` and
|
|
37
|
-
`README.md` are reserved names.
|
|
38
|
-
- Filenames are portable identities: lowercase ascii, no spaces, no
|
|
39
|
-
case-collisions, no `x.md` beside `x/`, no parentheses or leading
|
|
40
|
-
underscore. `knowledge/` holds `.md`, companions (`<doc>.summary.md`,
|
|
41
|
-
`<doc>.{flashcards,quiz,slides}.yaml`) and images only.
|
|
42
|
-
- Links resolve inside `knowledge/` — inline, `<angle-bracketed>` and
|
|
43
|
-
reference-style alike; code is never a link — and never reach a document
|
|
44
|
-
that not every reader of the source may read (the widening rule).
|
|
45
|
-
- `instance.md` is `format: 2` with the closed key set the profile defines.
|
|
46
|
-
- `CLAUDE.md` stays a one-line pointer; `.agents/skills/` and
|
|
47
|
-
`.claude/skills/` hold the same files byte for byte in both directions; the
|
|
48
|
-
site contains no content files.
|
|
49
|
-
|
|
50
|
-
Every failure prints where, the rule's slug (`problem: ksor-…`), why the rule
|
|
51
|
-
exists, and the fix — obey the printed fix literally; if it doesn't resolve
|
|
52
|
-
the problem, that is a bug worth reporting to ksor.
|
|
53
|
-
|
|
54
|
-
When you edit any skill under `.agents/skills/`, re-copy it to
|
|
55
|
-
`.claude/skills/` — the checker holds the two trees identical.
|
|
14
|
+
- **It is generated, and it is the same rule set** `ksor build` and
|
|
15
|
+
`ksor ingest` run, so the three can never disagree about a well-formed
|
|
16
|
+
record. Do not edit it: `ksor init` writes it and `ksor migrate` rewrites both
|
|
17
|
+
copies when you upgrade, so an edit is overwritten rather than kept. It
|
|
18
|
+
reports and never rewrites a file.
|
|
19
|
+
- **Obey the printed fix literally.** Every refusal prints where, the rule's
|
|
20
|
+
slug (`problem: ksor-…`), why the rule exists, and the fix. If the fix does
|
|
21
|
+
not resolve the problem, that is a bug worth reporting to ksor.
|
|
22
|
+
- **If its refusals contradict `AGENTS.md`, the checker is older than the
|
|
23
|
+
record**: upgrade `@panaversity/ksor` and re-run `ksor migrate`. Never "fix"
|
|
24
|
+
the record by undoing what a migration wrote.
|
|
25
|
+
- **When you edit any skill under `.agents/skills/`, re-copy it to
|
|
26
|
+
`.claude/skills/`** — the checker holds the two trees byte-identical in both
|
|
27
|
+
directions.
|
|
@@ -11971,6 +11971,7 @@ function changedFields(before, after) {
|
|
|
11971
11971
|
const CONTROL_FILES = [
|
|
11972
11972
|
"instance.md",
|
|
11973
11973
|
".ksor/governance.yaml",
|
|
11974
|
+
".ksor/people.yaml",
|
|
11974
11975
|
".ksor/takedowns.yaml"
|
|
11975
11976
|
];
|
|
11976
11977
|
/** Files the operating system writes behind the author's back: ignored, never reported. */
|
|
@@ -13551,6 +13552,7 @@ const lockSchema = object({
|
|
|
13551
13552
|
drafts: _enum(["hidden", "shown"]),
|
|
13552
13553
|
instance_sha256: hex64,
|
|
13553
13554
|
policy_sha256: hex64,
|
|
13555
|
+
people_sha256: hex64,
|
|
13554
13556
|
ledger_sha256: hex64,
|
|
13555
13557
|
ledger_entries: array(object({
|
|
13556
13558
|
id: string().min(1),
|
|
@@ -13745,6 +13747,7 @@ const INPUTS = [
|
|
|
13745
13747
|
"knowledge",
|
|
13746
13748
|
"instance.md",
|
|
13747
13749
|
".ksor/governance.yaml",
|
|
13750
|
+
".ksor/people.yaml",
|
|
13748
13751
|
".ksor/takedowns.yaml"
|
|
13749
13752
|
];
|
|
13750
13753
|
function gitFacts(root) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: intake-interview
|
|
3
|
-
description: The first conversation with the owner of this Knowledge System of Record —
|
|
3
|
+
description: The first conversation with the owner of this Knowledge System of Record — three questions that define what it is authoritative for, who may read it and who may approve it, then write instance.md together. Use when the owner asks to set up, configure, or "get started with" this project, when instance.md still contains its scaffold placeholder text, or when the scope of the corpus is unclear.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "1.
|
|
5
|
+
version: "1.6.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Intake interview
|
|
@@ -123,9 +123,10 @@ never an email address.
|
|
|
123
123
|
Leave `name:` and `toolchain:` alone. One block is added here only when
|
|
124
124
|
the owner stands up the served MCP rung — `database:`/`embedding:`/
|
|
125
125
|
`retrieval:` (see `AGENTS.md` → "Serving to agents"; that is a later
|
|
126
|
-
climb, not part of this interview). The
|
|
127
|
-
is the intent behind the `retrieval.vector_floor` on that
|
|
128
|
-
by `ksor calibrate` — capture it in the prose now so it is
|
|
126
|
+
climb, not part of this interview). The `declines` default above (or the owner's
|
|
127
|
+
correction to it) is the intent behind the `retrieval.vector_floor` on that
|
|
128
|
+
climb, measured by `ksor calibrate` — capture it in the prose now so it is
|
|
129
|
+
ready.
|
|
129
130
|
- Write `.ksor/governance.yaml` from question 3: `version: "0.1"`,
|
|
130
131
|
the `audiences:` registry if there is one, and the two authority sets with
|
|
131
132
|
real actors. That file is the root of authority — every approval, every
|
|
@@ -134,12 +135,19 @@ never an email address.
|
|
|
134
135
|
document is still in `knowledge/`.** Those five are approved by it, so a
|
|
135
136
|
policy rewritten without it refuses the next build by name
|
|
136
137
|
(`ksor-approver-unauthorised`). It leaves when the last sample does.
|
|
138
|
+
- **Re-attribute what `human:you` already did.** If any document carries
|
|
139
|
+
`human:you` as its approver, generator or deprecator — the hello-world
|
|
140
|
+
tutorial's own document does — rewrite those acts to the owner's handle in
|
|
141
|
+
the SAME change that retires the placeholder from the policy. It is the same
|
|
142
|
+
person. A policy that stops naming `human:you` beside a document that still
|
|
143
|
+
cites it turns a green record red (`ksor-approver-unauthorised`), and the
|
|
144
|
+
owner's first act after being interviewed should not be a refusal.
|
|
137
145
|
- Write `.ksor/people.yaml` from question 3: `version: "0.1"` and a `people:`
|
|
138
146
|
MAP from each actor to its natural name — `"human:bashiraziz": Bashir Aziz`.
|
|
139
147
|
Keyed by the actor exactly as the record stores it, quoted because it
|
|
140
148
|
contains a colon. Nothing else — the site looks the actor up at render time,
|
|
141
149
|
so pages read "Owner · Bashir Aziz" instead of "Owner · human:bashiraziz". Every skill that records a governance
|
|
142
|
-
act (this one, add-sources
|
|
150
|
+
act (this one, add-sources when it names a `ksor.owner`, `ksor takedown` for
|
|
143
151
|
withdrawals) asks the owner for a natural name whenever it is about to write
|
|
144
152
|
an actor that isn't in `people.yaml` yet — the owner is the only source of a
|
|
145
153
|
display name, never a convention-based guess.
|
|
@@ -162,7 +170,7 @@ never an email address.
|
|
|
162
170
|
the new title and refuses anything the profile does not accept.
|
|
163
171
|
- Restart `pnpm dev` afterwards so the site picks the new title up, and
|
|
164
172
|
show the owner their name on the page.
|
|
165
|
-
- Offer to
|
|
166
|
-
|
|
173
|
+
- Offer to start on the owner's own documents: the add-sources skill takes
|
|
174
|
+
whatever material they have from there.
|
|
167
175
|
- Read the result back to the owner and get an explicit yes before
|
|
168
176
|
finishing. Their words, tightened — never your invention.
|
|
@@ -118,7 +118,15 @@ text-embedding-3-small`, `dim: 1536`, key in `OPENAI_API_KEY` — and each
|
|
|
118
118
|
Turning it on is step 4, AFTER the record is serving.
|
|
119
119
|
|
|
120
120
|
2. **Get the database — your agent can do this one.** `.mcp.json` at the repo
|
|
121
|
-
root declares the MCP servers this project may reach
|
|
121
|
+
root declares the MCP servers this project may reach. It ships with two:
|
|
122
|
+
`Neon`, which provisions the Postgres this step needs, and
|
|
123
|
+
`agentfactory-system-of-record`, a read-only KSoR record Panaversity operates
|
|
124
|
+
as an example of the surface being built here — not this project's record,
|
|
125
|
+
and not needed by anything below. Either can be deleted; the file is the
|
|
126
|
+
adopter's.
|
|
127
|
+
|
|
128
|
+
The Neon server acts on the whole Neon ACCOUNT, not on one database: it can
|
|
129
|
+
create and delete projects and branches. Show the plan before running it.
|
|
122
130
|
With it connected, ask:
|
|
123
131
|
|
|
124
132
|
> Using the Neon MCP server, create a project called `<your-record>` and
|
|
@@ -793,9 +801,9 @@ CI — and a first deploy without it serves an empty record. Full walkthrough:
|
|
|
793
801
|
quiz had every correct answer in the same position across 451 questions.
|
|
794
802
|
|
|
795
803
|
A **presentation** is slides the record owns. Ask your coding agent for one
|
|
796
|
-
rather than writing it by hand
|
|
797
|
-
|
|
798
|
-
|
|
804
|
+
rather than writing it by hand: it reads the document whole, writes the
|
|
805
|
+
deck, checks every claim and every number back against the document, and
|
|
806
|
+
tells you what it left out because the document did not support it:
|
|
799
807
|
|
|
800
808
|
```yaml
|
|
801
809
|
slides:
|
|
@@ -910,6 +918,11 @@ SAMEORIGIN`, which forbids any other site from framing them, and a browser
|
|
|
910
918
|
- Copy load-bearing values (numbers, thresholds, dates) exactly from their
|
|
911
919
|
source, name the source in `sources`, and cite it from the claim with a GFM
|
|
912
920
|
footnote whose label is that source's `id`.
|
|
921
|
+
- **The record says only what its source says.** A gap is an open question
|
|
922
|
+
written into the document — never filled from general knowledge — and two
|
|
923
|
+
sources that disagree stay two cited statements: flag the disagreement to
|
|
924
|
+
the owner rather than choosing. That boundary is the product; a record that
|
|
925
|
+
quietly knows more than its sources is a chatbot with a sidebar.
|
|
913
926
|
|
|
914
927
|
### Structuring the record
|
|
915
928
|
|
|
@@ -932,12 +945,10 @@ SAMEORIGIN`, which forbids any other site from framing them, and a browser
|
|
|
932
945
|
|
|
933
946
|
- `.agents/skills/intake-interview/` — first run: interview the owner and
|
|
934
947
|
write `instance.md` together.
|
|
935
|
-
- `.agents/skills/add-sources/` — turn
|
|
936
|
-
notes
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
- `.agents/skills/make-summary/` — write a document's summary and attach it,
|
|
940
|
-
so it renders as a second tab on that document's page.
|
|
948
|
+
- `.agents/skills/add-sources/` — turn what the owner has into governed
|
|
949
|
+
knowledge: a document, a page, notes, or what they tell you that nobody
|
|
950
|
+
wrote down. Converts files with a verified extraction, interviews a person
|
|
951
|
+
for the rest, and ends with the owner's approval.
|
|
941
952
|
- `.agents/skills/format-checker/` — the rules above, as a program;
|
|
942
953
|
`pnpm check` runs it and its errors explain how to fix themselves.
|
|
943
954
|
|