@panaversity/ksor 0.0.50 → 0.0.51
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 +73 -0
- package/dist/cli.mjs +57 -1
- package/docs/index.md +5 -0
- package/docs/upgrading.md +106 -0
- package/package.json +1 -1
- package/templates/scaffold/pnpm-lock.yaml +304 -262
- package/templates/scaffold/system/site/lib/record-href.ts +1 -1
- package/templates/scaffold/system/site/next.config.mjs +13 -0
- package/templates/scaffold/system/site/package.json +4 -4
- package/templates/scaffold/system/site/source.config.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# @panaversity/ksor
|
|
2
2
|
|
|
3
|
+
## 0.0.51
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6478ca4: Test infrastructure only — nothing an adopter installs behaves differently.
|
|
8
|
+
|
|
9
|
+
Every database-tier suite now bootstraps its scratch database under a name
|
|
10
|
+
unique to the run (`ksor_<slug>_<base36 ms>_<6 hex>`) instead of a fixed one.
|
|
11
|
+
Fixed names meant two runs against one Postgres — a second `pnpm test:db`, a CI
|
|
12
|
+
matrix job, an agent running the tier alongside a person — dropped each other's
|
|
13
|
+
database `WITH (FORCE)` mid-test, which surfaced as a missing table or a short
|
|
14
|
+
row count and read as flakiness. A new reaper (`scripts/db-reaper.ts`, the
|
|
15
|
+
tier's globalSetup) drops what an interrupted run leaks, and guard rule 12 keeps
|
|
16
|
+
the naming from drifting back.
|
|
17
|
+
|
|
18
|
+
- c466d4b: The scaffold moves to Fumadocs `16.15.4` (`fumadocs-core`, `fumadocs-ui`) and
|
|
19
|
+
`fumadocs-mdx` `15.4.0`.
|
|
20
|
+
|
|
21
|
+
Maintenance, not a fix — no advisory pushed it, and `npm audit` was already
|
|
22
|
+
clean. It is taken now because the four behaviours the scaffold cites BY VERSION
|
|
23
|
+
were re-verified against the new bytes rather than assumed, and each holds:
|
|
24
|
+
`CalloutType` is still the same six values (`fumadocs-ui/dist/components/callout.d.ts`);
|
|
25
|
+
`resolveHref` still resolves only the `./` and `../` forms and returns everything
|
|
26
|
+
else untouched, which is why the record keeps its own resolver; `remark-code-tab`
|
|
27
|
+
still honours `tab-group` on the `CodeBlockTabs` branch only, which is why the
|
|
28
|
+
scaffold picks that branch; and the search engine is still ZBSearch, so the
|
|
29
|
+
`language` option stays absent. Those citations now name `16.15.4`.
|
|
30
|
+
|
|
31
|
+
`fumadocs-ui` pins `fumadocs-core` exactly, so the two always move together;
|
|
32
|
+
`fumadocs-mdx@15.4.0` requires `fumadocs-core ^16.15.3`, which is what makes this
|
|
33
|
+
one change rather than three. Nothing else moves with it — Fumadocs peers Next as
|
|
34
|
+
a range (`16.x.x`). The committed pnpm lockfile is regenerated to match.
|
|
35
|
+
|
|
36
|
+
- 69d57f2: `ksor migrate --write-site` no longer deletes dependencies the adopter added to
|
|
37
|
+
their site.
|
|
38
|
+
|
|
39
|
+
Every file under `system/site` is offered as a whole-file replacement, which is
|
|
40
|
+
right for the copied rule modules and wrong for `system/site/package.json` — a
|
|
41
|
+
register ksor and the adopter both write in. Copying it whole removed anything
|
|
42
|
+
they had added, inside the same hunk that carried a pin bump, so a project could
|
|
43
|
+
stop building on the release meant to fix it. It is now merged per section: the
|
|
44
|
+
entries ksor ships move to this release's versions, the adopter's own survive,
|
|
45
|
+
and an entry ksor no longer ships is left alone rather than deleted (the tool
|
|
46
|
+
cannot tell one it retired from one they added).
|
|
47
|
+
|
|
48
|
+
Adds `docs/upgrading.md`, which ships in the tarball: the four-step path, the
|
|
49
|
+
table of what migrate carries, the list of files it does not — so an adopter
|
|
50
|
+
knows what to diff by hand — and the refusals to expect.
|
|
51
|
+
|
|
52
|
+
- 4b077aa: The scaffold pins Next `16.3.3`, clearing three high-severity advisories a
|
|
53
|
+
fresh `npm install` reported (#207).
|
|
54
|
+
|
|
55
|
+
`next@16.2.9` pulled `sharp@0.34.5` and `postcss@8.4.31`; the advisories are
|
|
56
|
+
against those, not against anything the scaffold declares, so the bump that
|
|
57
|
+
fixes them is Next's own. Measured on a fresh scaffold from the published CLI:
|
|
58
|
+
`npm audit` goes from **3 high to 0**, the static build takes 41.8s and emits
|
|
59
|
+
its 22 pages, and `llms.txt` carries its 5 entries unchanged. `16.3.3` is not
|
|
60
|
+
semver-major and Fumadocs peers Next as a range (`16.x.x`), so nothing else
|
|
61
|
+
moves with it. The committed pnpm lockfile is regenerated to match — the half
|
|
62
|
+
that would otherwise break an adopter whose CI installs frozen.
|
|
63
|
+
|
|
64
|
+
An existing project takes both across with
|
|
65
|
+
`ksor migrate --write-site`, which offers every file of `system/site` this
|
|
66
|
+
release emits — the pin and the config among them. It prints the diff and
|
|
67
|
+
changes nothing without `--write`.
|
|
68
|
+
|
|
69
|
+
The scaffold's `next.config.mjs` also sets `agentRules: false`. From Next 16.3,
|
|
70
|
+
a `next dev` that detects a coding agent writes `AGENTS.md` and `CLAUDE.md` into
|
|
71
|
+
the Next project root — which here is `system/site`, where the record's own
|
|
72
|
+
hygiene rule refuses markdown (`ksor-site-holds-content`: the site renders the
|
|
73
|
+
record, it never holds it). Left on, an adopter's `pnpm dev` turned their own
|
|
74
|
+
`pnpm check` red without their touching anything.
|
|
75
|
+
|
|
3
76
|
## 0.0.50
|
|
4
77
|
|
|
5
78
|
### Patch Changes
|
package/dist/cli.mjs
CHANGED
|
@@ -13059,9 +13059,10 @@ function siteChanges(root, templatesDir, stamps) {
|
|
|
13059
13059
|
continue;
|
|
13060
13060
|
}
|
|
13061
13061
|
if (!SITE_TEXT_EXTENSIONS.has(path.extname(entry.name))) continue;
|
|
13062
|
-
const
|
|
13062
|
+
const rendered = applyProse(readFileSync(abs, "utf8").replaceAll("KSOR-STAMP-NAME", stamps.name).replaceAll("KSOR-STAMP-VERSION", stamps.version), manager);
|
|
13063
13063
|
const target = path.join(root, child);
|
|
13064
13064
|
const before = existsSync(target) ? readFileSync(target, "utf8") : null;
|
|
13065
|
+
const after = child === "system/site/package.json" && before !== null ? mergeSiteManifest(before, rendered) : rendered;
|
|
13065
13066
|
if (before !== after) out.push({
|
|
13066
13067
|
path: child,
|
|
13067
13068
|
before,
|
|
@@ -13073,6 +13074,61 @@ function siteChanges(root, templatesDir, stamps) {
|
|
|
13073
13074
|
return out;
|
|
13074
13075
|
}
|
|
13075
13076
|
/**
|
|
13077
|
+
* The site manifest, merged: what ksor pins wins, what the adopter added stays.
|
|
13078
|
+
*
|
|
13079
|
+
* Applied per SECTION rather than per file. `dependencies`, `devDependencies`
|
|
13080
|
+
* and `scripts` are registers with two authors — ksor owns the entries it ships
|
|
13081
|
+
* (they are what the emitted site is built and tested against, and a security
|
|
13082
|
+
* bump reaches an existing project through exactly this path), and the adopter
|
|
13083
|
+
* owns everything else in them. A key ksor no longer ships is left alone rather
|
|
13084
|
+
* than deleted: this cannot tell one it retired from one the adopter added.
|
|
13085
|
+
*
|
|
13086
|
+
* Unparseable on either side falls back to the template, which is the same
|
|
13087
|
+
* whole-file offer every other site file gets — a diff, gated on `--write`.
|
|
13088
|
+
*/
|
|
13089
|
+
function mergeSiteManifest(before, template) {
|
|
13090
|
+
const parse = (text) => {
|
|
13091
|
+
try {
|
|
13092
|
+
const value = JSON.parse(text);
|
|
13093
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
13094
|
+
} catch {
|
|
13095
|
+
return null;
|
|
13096
|
+
}
|
|
13097
|
+
};
|
|
13098
|
+
const mine = parse(before);
|
|
13099
|
+
const theirs = parse(template);
|
|
13100
|
+
if (mine === null || theirs === null) return template;
|
|
13101
|
+
const section = (key) => {
|
|
13102
|
+
const a = mine[key];
|
|
13103
|
+
const b = theirs[key];
|
|
13104
|
+
const table = (v) => typeof v === "object" && v !== null && !Array.isArray(v) ? v : null;
|
|
13105
|
+
const ours = table(b);
|
|
13106
|
+
const adopters = table(a);
|
|
13107
|
+
if (ours === null) return adopters ?? void 0;
|
|
13108
|
+
if (adopters === null) return ours;
|
|
13109
|
+
const merged = {};
|
|
13110
|
+
for (const [name, version] of Object.entries(adopters)) merged[name] = name in ours ? ours[name] : version;
|
|
13111
|
+
for (const [name, version] of Object.entries(ours)) if (!(name in merged)) merged[name] = version;
|
|
13112
|
+
return merged;
|
|
13113
|
+
};
|
|
13114
|
+
const MERGED = [
|
|
13115
|
+
"dependencies",
|
|
13116
|
+
"devDependencies",
|
|
13117
|
+
"scripts"
|
|
13118
|
+
];
|
|
13119
|
+
const out = {
|
|
13120
|
+
...mine,
|
|
13121
|
+
...theirs
|
|
13122
|
+
};
|
|
13123
|
+
for (const key of MERGED) {
|
|
13124
|
+
const value = section(key);
|
|
13125
|
+
if (value === void 0) delete out[key];
|
|
13126
|
+
else out[key] = value;
|
|
13127
|
+
}
|
|
13128
|
+
const eol = before.includes("\r\n") ? "\r\n" : "\n";
|
|
13129
|
+
return `${JSON.stringify(out, null, indentOf(before)).replaceAll("\n", eol)}${/\r?\n$/.test(before) ? eol : ""}`;
|
|
13130
|
+
}
|
|
13131
|
+
/**
|
|
13076
13132
|
* Which manager this repository was scaffolded for, from what it committed.
|
|
13077
13133
|
* `ksor init` reads `npm_config_user_agent` — the run that scaffolds is the
|
|
13078
13134
|
* run that knows — but a migration is a different run, so it reads the tree.
|
package/docs/index.md
CHANGED
|
@@ -51,6 +51,11 @@ instead of their training memory. The corpus grows with each implemented verb.
|
|
|
51
51
|
current. Serving does not publish, so a first deploy with no ingest serves
|
|
52
52
|
an empty record; this is the page that explains why, where ingest belongs
|
|
53
53
|
(never inside the container), and how the abstention gate gets turned on.
|
|
54
|
+
- **[upgrading.md](./upgrading.md)** — moving an existing record onto a newer
|
|
55
|
+
ksor. `ksor migrate` offers a diff and changes nothing without `--write`;
|
|
56
|
+
`--write-site` is the one flag to remember, because it is the only path by
|
|
57
|
+
which a dependency bump reaches a project already scaffolded. Includes the
|
|
58
|
+
list of files migrate does NOT carry, so you know what to diff by hand.
|
|
54
59
|
- **[authorization.md](./authorization.md)** — putting the record behind an
|
|
55
60
|
authorization server, with worked recipes for two of them, executed rather
|
|
56
61
|
than written. `ksor serve` refuses to boot unauthenticated on a public bind,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Upgrading a record to a newer ksor
|
|
3
|
+
status: draft
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Upgrading a record to a newer ksor
|
|
7
|
+
|
|
8
|
+
Your repository is yours. `ksor init` copied files into it and stopped owning
|
|
9
|
+
them the moment it did (decision 4), so upgrading is never something a release
|
|
10
|
+
does to you — it is `ksor migrate` **offering** a diff you read and apply.
|
|
11
|
+
|
|
12
|
+
Nothing here changes a byte until you pass `--write`.
|
|
13
|
+
|
|
14
|
+
## The four steps
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
# 1. take the new tool
|
|
18
|
+
pnpm add -w @panaversity/ksor@latest # npm i / bun add — whichever scaffolded this
|
|
19
|
+
|
|
20
|
+
# 2. read what it would change
|
|
21
|
+
pnpm exec ksor migrate --instance instance.md --write-site
|
|
22
|
+
|
|
23
|
+
# 3. apply it
|
|
24
|
+
pnpm exec ksor migrate --instance instance.md --write-site --write --actor human:<your-id>
|
|
25
|
+
|
|
26
|
+
# 4. rebuild, and check
|
|
27
|
+
pnpm build && pnpm check
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`--actor` is required for step 3 whenever the migration touches governance, and
|
|
31
|
+
the tool will not guess one: a ledger entry that names a person who was never
|
|
32
|
+
there is worse than no entry (decision 21). Use the identifier your
|
|
33
|
+
`.ksor/governance.yaml` already knows you by.
|
|
34
|
+
|
|
35
|
+
Run step 2 on a clean working tree. The diff is the review, and it is much
|
|
36
|
+
easier to read when nothing else is uncommitted.
|
|
37
|
+
|
|
38
|
+
## What `migrate` carries
|
|
39
|
+
|
|
40
|
+
| | |
|
|
41
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
42
|
+
| `instance.md` | the format bump and the keys that moved |
|
|
43
|
+
| `knowledge/**` | frontmatter into the current profile — statuses, audiences, the trust block, instants |
|
|
44
|
+
| `.ksor/takedowns.yaml`, `.ksor/governance.yaml` | the ledger and the policy, including denials that lived only in a database |
|
|
45
|
+
| `.gitignore` | the entries a new release needs negated |
|
|
46
|
+
| `.agents/` and `.claude/` format-checker | the emitted checker, so your own `pnpm check` and your CI agree with the tool |
|
|
47
|
+
| root `package.json` **scripts** | scripts a release broke — a removed flag, a step that now needs `ksor build` in front of it |
|
|
48
|
+
| `system/site/**` | **only with `--write-site`** — every file of the site this release emits |
|
|
49
|
+
|
|
50
|
+
`--write-site` is the one to remember, because it is the only path by which a
|
|
51
|
+
security bump reaches an existing project: the site's `package.json` is where
|
|
52
|
+
`next`, `react` and the Fumadocs pins live, and nothing else updates them.
|
|
53
|
+
|
|
54
|
+
It is an **update, never a creation**. A record with no `system/site` of its own
|
|
55
|
+
is not given one.
|
|
56
|
+
|
|
57
|
+
### The site manifest is merged, not replaced
|
|
58
|
+
|
|
59
|
+
Every other file under `system/site` is reissued whole. `system/site/package.json`
|
|
60
|
+
is not, because it is a register with two authors: ksor owns the entries it
|
|
61
|
+
ships, you own everything else. So a dependency or script you added survives the
|
|
62
|
+
upgrade, and the pins ksor ships move to the new versions. An entry ksor no
|
|
63
|
+
longer ships is left alone rather than deleted — the tool cannot tell one it
|
|
64
|
+
retired from one you added.
|
|
65
|
+
|
|
66
|
+
## What `migrate` does not carry
|
|
67
|
+
|
|
68
|
+
These are yours, and no release touches them. Diff them against a fresh
|
|
69
|
+
`ksor init` in a scratch directory when a release note says they changed:
|
|
70
|
+
|
|
71
|
+
- `Dockerfile` and `.dockerignore`
|
|
72
|
+
- `vercel.json` (or whatever your host reads)
|
|
73
|
+
- `.github/workflows/validate.yml`
|
|
74
|
+
- `.env.example`
|
|
75
|
+
- `README.md`, `AGENTS.md`, `CLAUDE.md` at the repository root
|
|
76
|
+
- `pnpm-workspace.yaml` / `.npmrc` and any lockfile
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npx @panaversity/ksor@latest init /tmp/fresh
|
|
80
|
+
diff -ru /tmp/fresh/vercel.json ./vercel.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## What refuses, and why that is the point
|
|
84
|
+
|
|
85
|
+
`migrate` stops rather than inventing. `ksor-migrate-underivable` names the one
|
|
86
|
+
thing it cannot know — a title, a description, a `generated.at`, or the actor
|
|
87
|
+
behind a takedown it found in a database — and tells you the flag or the edit
|
|
88
|
+
that supplies it. Two you will meet often:
|
|
89
|
+
|
|
90
|
+
- **A record that declares `database:`** refuses until `KSOR_DB_URL` is
|
|
91
|
+
exported, because denials living only in that database would be republished by
|
|
92
|
+
a migration that never read them. Export it, or remove `database:` if the
|
|
93
|
+
record no longer has one.
|
|
94
|
+
- **`approved` documents become `draft`** unless `--approve-by <actor>` says who
|
|
95
|
+
approves them in the same act. Approval is a human act and a migration is not
|
|
96
|
+
a human.
|
|
97
|
+
|
|
98
|
+
## After it applies
|
|
99
|
+
|
|
100
|
+
`pnpm build` regenerates every index and rewrites `build.lock.json`; `pnpm check`
|
|
101
|
+
runs the record checker that shipped with the new tool. If you serve the record,
|
|
102
|
+
`ksor schema --apply` and then a full `pnpm refresh` publish a generation the new
|
|
103
|
+
door can read — and a calibrated `vector_floor` measured under an older serving
|
|
104
|
+
predicate must be re-measured with `ksor calibrate`, because a floor measured
|
|
105
|
+
against a different predicate is a declared-but-uncalibrated floor and the door
|
|
106
|
+
will refuse every search until it is replaced.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@panaversity/ksor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
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",
|