@panaversity/ksor 0.0.39 → 0.0.41
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 +965 -0
- package/README.md +29 -9
- package/dist/checker/check-main.mjs +14049 -0
- package/dist/cli.mjs +11528 -5213
- package/dist/gateway-api-CF4ED9_g-BQusM_dK.mjs +10895 -0
- package/dist/gateway.d.mts +52 -13
- package/dist/gateway.mjs +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-pl4aOpVs.mjs → src-dqpI-p1a.mjs} +1 -0
- package/docs/authorization.md +8 -6
- package/docs/deploying.md +36 -25
- package/docs/index.md +26 -13
- package/docs/ingesting.md +70 -22
- package/docs/tool-surface.md +69 -16
- package/package.json +4 -3
- package/schema/migrations/2.4-2.5__okf-profile.sql +114 -0
- package/schema/schema.sql +77 -14
- package/templates/scaffold/.agents/skills/add-sources/SKILL.md +63 -18
- package/templates/scaffold/.agents/skills/format-checker/SKILL.md +42 -33
- package/templates/scaffold/.agents/skills/format-checker/check.mjs +13827 -1314
- package/templates/scaffold/.agents/skills/intake-interview/SKILL.md +65 -27
- package/templates/scaffold/.agents/skills/make-slides/SKILL.md +7 -5
- package/templates/scaffold/.agents/skills/make-summary/SKILL.md +13 -6
- package/templates/scaffold/.claude/skills/add-sources/SKILL.md +63 -18
- package/templates/scaffold/.claude/skills/format-checker/SKILL.md +42 -33
- package/templates/scaffold/.claude/skills/format-checker/check.mjs +13827 -1314
- package/templates/scaffold/.claude/skills/intake-interview/SKILL.md +65 -27
- package/templates/scaffold/.claude/skills/make-slides/SKILL.md +7 -5
- package/templates/scaffold/.claude/skills/make-summary/SKILL.md +13 -6
- package/templates/scaffold/.github/workflows/validate.yml +9 -1
- package/templates/scaffold/.ksor/governance.yaml +17 -0
- package/templates/scaffold/AGENTS.md +293 -119
- package/templates/scaffold/Dockerfile +5 -1
- package/templates/scaffold/README.md +160 -42
- package/templates/scaffold/env.example +37 -6
- package/templates/scaffold/gitignore +14 -6
- package/templates/scaffold/instance.md +21 -17
- package/templates/scaffold/knowledge/governance-ladder.md +11 -2
- package/templates/scaffold/knowledge/index.md +9 -0
- package/templates/scaffold/knowledge/surfaces/for-agents.md +13 -6
- package/templates/scaffold/knowledge/surfaces/for-people.md +7 -6
- package/templates/scaffold/knowledge/surfaces/index.md +4 -20
- package/templates/scaffold/knowledge/surfaces/overview.md +25 -0
- package/templates/scaffold/knowledge/what-is-a-ksor.md +6 -5
- package/templates/scaffold/knowledge/what-is-a-ksor.summary.md +4 -0
- package/templates/scaffold/package.json +3 -4
- package/templates/scaffold/pnpm-lock.yaml +3 -0
- package/templates/scaffold/system/gateways/content.ts +13 -0
- package/templates/scaffold/system/site/app/(home)/page.tsx +2 -2
- package/templates/scaffold/system/site/app/.well-known/mcp/server.json/route.ts +10 -0
- package/templates/scaffold/system/site/app/docs/[[...slug]]/page.tsx +134 -91
- package/templates/scaffold/system/site/app/global.css +198 -6
- package/templates/scaffold/system/site/app/layout.tsx +8 -3
- package/templates/scaffold/system/site/app/llms-full.txt/route.ts +13 -7
- package/templates/scaffold/system/site/app/llms.txt/route.ts +12 -7
- package/templates/scaffold/system/site/app/md/[[...slug]]/route.ts +26 -25
- package/templates/scaffold/system/site/components/code-block.tsx +87 -0
- package/templates/scaffold/system/site/components/embed.tsx +276 -0
- package/templates/scaffold/system/site/components/footer-mark.tsx +3 -2
- package/templates/scaffold/system/site/components/governance.tsx +219 -87
- package/templates/scaffold/system/site/components/mdx.tsx +10 -2
- package/templates/scaffold/system/site/components/record-index.tsx +5 -5
- package/templates/scaffold/system/site/components/record-stack.tsx +10 -9
- package/templates/scaffold/system/site/components/record-views.tsx +6 -17
- package/templates/scaffold/system/site/components/sidebar-status.tsx +19 -18
- package/templates/scaffold/system/site/lib/alert-rule.ts +214 -0
- package/templates/scaffold/system/site/lib/attachment-rule.ts +6 -1
- package/templates/scaffold/system/site/lib/attachments.ts +0 -28
- package/templates/scaffold/system/site/lib/audience-rule.ts +15 -21
- package/templates/scaffold/system/site/lib/audience.ts +42 -146
- package/templates/scaffold/system/site/lib/embed-rule.ts +255 -0
- package/templates/scaffold/system/site/lib/governance.ts +339 -225
- package/templates/scaffold/system/site/lib/index-routes.ts +125 -0
- package/templates/scaffold/system/site/lib/lifecycle-rule.ts +52 -0
- package/templates/scaffold/system/site/lib/lock.ts +282 -0
- package/templates/scaffold/system/site/lib/order-rule.ts +37 -0
- package/templates/scaffold/system/site/lib/record-href.ts +68 -0
- package/templates/scaffold/system/site/lib/record-link.tsx +26 -0
- package/templates/scaffold/system/site/lib/rules-version.ts +11 -0
- package/templates/scaffold/system/site/lib/shared.ts +67 -104
- package/templates/scaffold/system/site/lib/sim-rule.ts +49 -0
- package/templates/scaffold/system/site/lib/source.ts +256 -186
- package/templates/scaffold/system/site/lib/stage-knowledge.ts +638 -467
- package/templates/scaffold/system/site/lib/stage-manifest.ts +128 -0
- package/templates/scaffold/system/site/package.json +1 -0
- package/templates/scaffold/system/site/record/actor.ts +23 -0
- package/templates/scaffold/system/site/record/check.ts +571 -0
- package/templates/scaffold/system/site/record/citations.ts +312 -0
- package/templates/scaffold/system/site/record/frontmatter.ts +134 -0
- package/templates/scaffold/system/site/record/git-ledger.ts +171 -0
- package/templates/scaffold/system/site/record/hygiene.ts +320 -0
- package/templates/scaffold/system/site/record/index-file.ts +150 -0
- package/templates/scaffold/system/site/record/index.ts +103 -0
- package/templates/scaffold/system/site/record/instance.ts +257 -0
- package/templates/scaffold/system/site/record/instant.ts +43 -0
- package/templates/scaffold/system/site/record/ledger.ts +694 -0
- package/templates/scaffold/system/site/record/load.ts +129 -0
- package/templates/scaffold/system/site/record/lock.ts +306 -0
- package/templates/scaffold/system/site/record/near-miss.ts +37 -0
- package/templates/scaffold/system/site/record/policy.ts +414 -0
- package/templates/scaffold/system/site/record/profile.ts +535 -0
- package/templates/scaffold/system/site/record/refusal.ts +106 -0
- package/templates/scaffold/system/site/record/yaml-file.ts +103 -0
- package/templates/scaffold/system/site/source.config.ts +109 -23
- package/dist/gateway-api-CmIthmJS-IUA9qS-T.mjs +0 -3225
- package/templates/scaffold/system/site/lib/denial-rule.ts +0 -220
- package/templates/scaffold/system/site/lib/page-order.ts +0 -93
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { LifecycleBadge } from "./lifecycle-rule";
|
|
5
|
+
import { frontmatterText, splitFrontmatter } from "../record/frontmatter";
|
|
6
|
+
import { parseIndex, type IndexEntry } from "../record/index-file";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What staging decided, for the surfaces that read the stage: which pages the
|
|
10
|
+
* machine artefacts admit, the badge a human page shows, and the stamps every
|
|
11
|
+
* machine artefact carries (build spec §3). Written beside the stage by
|
|
12
|
+
* `stage-knowledge.ts` — the ONE place the §2.5 table is evaluated — so a
|
|
13
|
+
* route cannot re-derive admission with a second rule that drifts.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Both relative to the site directory — the directory every build runs from
|
|
17
|
+
// (`pnpm build` is `pnpm -C system/site build`), which is also how fumadocs
|
|
18
|
+
// resolves a collection's `dir`.
|
|
19
|
+
export const STAGE_DIR = "./.staged-knowledge";
|
|
20
|
+
/** Where staging writes the manifest, beside the stage. */
|
|
21
|
+
export const STAGE_MANIFEST = "./.staged-knowledge.json";
|
|
22
|
+
|
|
23
|
+
export interface StagePage {
|
|
24
|
+
/** Admitted to `llms.txt`, `llms-full.txt`, the `/md/` twin — the machine surfaces. */
|
|
25
|
+
readonly machine: boolean;
|
|
26
|
+
/** Why the machine surfaces declined, shown on the human page; null when they did not. */
|
|
27
|
+
readonly badge: LifecycleBadge | null;
|
|
28
|
+
readonly status: string;
|
|
29
|
+
/** The successor's concept id, as `ksor.superseded_by` names it. */
|
|
30
|
+
readonly supersededBy: string | null;
|
|
31
|
+
readonly audience: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface StageStamps {
|
|
35
|
+
readonly build_id: string | null;
|
|
36
|
+
readonly source_commit: string | null;
|
|
37
|
+
readonly dirty: boolean;
|
|
38
|
+
readonly ksor_version: string | null;
|
|
39
|
+
/** True in development, where no lock exists and nothing is published. */
|
|
40
|
+
readonly unstamped: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface StageManifest {
|
|
44
|
+
readonly format: 1;
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly title: string;
|
|
47
|
+
readonly description: string | null;
|
|
48
|
+
readonly viewer: readonly string[];
|
|
49
|
+
/** The instant every lifecycle decision in this build was taken at. */
|
|
50
|
+
readonly asOf: string;
|
|
51
|
+
readonly drafts: "hidden" | "shown";
|
|
52
|
+
readonly stamps: StageStamps;
|
|
53
|
+
/** Keyed by bundle-relative path (`policies/x.md`), the shape `page.path` carries. */
|
|
54
|
+
readonly pages: Readonly<Record<string, StagePage>>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let cached: StageManifest | null = null;
|
|
58
|
+
|
|
59
|
+
/** The manifest of the stage this build reads. Staging always runs first (`source.config.ts`). */
|
|
60
|
+
export function readStageManifest(): StageManifest {
|
|
61
|
+
if (cached === null) {
|
|
62
|
+
cached = JSON.parse(
|
|
63
|
+
readFileSync(path.resolve(process.cwd(), STAGE_MANIFEST), "utf8"),
|
|
64
|
+
) as StageManifest;
|
|
65
|
+
}
|
|
66
|
+
return cached;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Is this page admitted to the machine surfaces? Unknown pages are not. */
|
|
70
|
+
export function machineAdmits(pagePath: string): boolean {
|
|
71
|
+
return readStageManifest().pages[pagePath.replaceAll("\\", "/")]?.machine === true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The page's own staging decision, or null for a path the stage does not hold. */
|
|
75
|
+
export function stagePageOf(pagePath: string): StagePage | null {
|
|
76
|
+
return readStageManifest().pages[pagePath.replaceAll("\\", "/")] ?? null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The regenerated index of a bundle-relative directory (`""` for the root),
|
|
81
|
+
* parsed — or null for a directory this viewer's stage does not hold. The
|
|
82
|
+
* folder pages and the reading order read the stage's own indexes: what this
|
|
83
|
+
* viewer may see, in the generator's order, and nothing else.
|
|
84
|
+
*/
|
|
85
|
+
export function readStagedIndex(dir: string): IndexEntry[] | null {
|
|
86
|
+
const file = path.resolve(process.cwd(), STAGE_DIR, dir, "index.md");
|
|
87
|
+
if (!existsSync(file)) return null;
|
|
88
|
+
return parseIndex(readFileSync(file, "utf8"));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The staged concept's own frontmatter, verbatim — the bytes its markdown twin
|
|
93
|
+
* and its `llms-full.txt` block republish (build spec §3).
|
|
94
|
+
*
|
|
95
|
+
* Read from the STAGE rather than from `page.data`, because the stage holds
|
|
96
|
+
* the record's file byte-for-byte: re-serialising the parsed object could only
|
|
97
|
+
* emit the keys this shell knows about, and record spec §2.7 keeps the ones it
|
|
98
|
+
* does not. Empty string for a concept with no frontmatter — a checker refusal,
|
|
99
|
+
* so unreachable on a built record, but the twin must not crash on it.
|
|
100
|
+
*/
|
|
101
|
+
export function stagedFrontmatter(pagePath: string): string {
|
|
102
|
+
const file = path.resolve(process.cwd(), STAGE_DIR, pagePath.replaceAll("\\", "/"));
|
|
103
|
+
return frontmatterText(readFileSync(file, "utf8")) ?? "";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The staged concept's BODY, verbatim — the bytes its markdown twin and its
|
|
108
|
+
* `llms-full.txt` block republish under the frontmatter above.
|
|
109
|
+
*
|
|
110
|
+
* Read from the STAGE for the same reason the frontmatter is, and for one more:
|
|
111
|
+
* the twin used to be built from fumadocs' PROCESSED markdown, which is the
|
|
112
|
+
* mdast serialized after every remark plugin has run. `remarkImage` replaces a
|
|
113
|
+
* local image with a generated import binding, so `` reached
|
|
114
|
+
* `/md/` and `llms-full.txt` as `<img alt="pub" src="__img0" />` — a variable
|
|
115
|
+
* name no consumer can resolve, while the MCP door over the SAME build returned
|
|
116
|
+
* the record's own bytes. Two machine surfaces of one publication disagreeing
|
|
117
|
+
* about one document is product principle 2, and `lib/alert-rule.ts` records
|
|
118
|
+
* the same discipline for alerts: nothing of this shell's dialect reaches the
|
|
119
|
+
* agent surfaces.
|
|
120
|
+
*/
|
|
121
|
+
export function stagedBody(pagePath: string): string {
|
|
122
|
+
const rel = pagePath.replaceAll("\\", "/");
|
|
123
|
+
const file = path.resolve(process.cwd(), STAGE_DIR, rel);
|
|
124
|
+
const split = splitFrontmatter(readFileSync(file, "utf8"), rel);
|
|
125
|
+
// A concept with no frontmatter is a checker refusal, so unreachable on a
|
|
126
|
+
// built record — but the twin must not crash on it.
|
|
127
|
+
return split.ok ? split.body : "";
|
|
128
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The actor convention (record spec §2.3): `human:<id>`, `process:<id>`,
|
|
3
|
+
* `team:<id>`, or a producer/version pair. Trust tiers key on the `human:`
|
|
4
|
+
* prefix, which is why a team is refused everywhere but ownership and the
|
|
5
|
+
* policy: it would silently classify as machine-confirmed.
|
|
6
|
+
*/
|
|
7
|
+
export type ActorKind = "human" | "process" | "team" | "producer";
|
|
8
|
+
|
|
9
|
+
const PREFIXED = /^(human|process|team):(\S+)$/;
|
|
10
|
+
const PRODUCER = /^[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._+-]*$/;
|
|
11
|
+
|
|
12
|
+
export function actorKind(value: string): ActorKind | null {
|
|
13
|
+
const m = PREFIXED.exec(value);
|
|
14
|
+
if (m !== null) return m[1] as ActorKind;
|
|
15
|
+
return PRODUCER.test(value) ? "producer" : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The forms allowed in `verified`, `generated`, `approval` and `deprecated`: everything but a team. */
|
|
19
|
+
export function isIndividualActor(value: unknown): value is string {
|
|
20
|
+
if (typeof value !== "string") return false;
|
|
21
|
+
const kind = actorKind(value);
|
|
22
|
+
return kind !== null && kind !== "team";
|
|
23
|
+
}
|