@panaversity/ksor 0.0.3 → 0.0.5
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 +95 -0
- package/README.md +6 -4
- package/dist/cli.mjs +6375 -9
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +1 -36
- package/dist/src-CpDIVudJ.mjs +43 -0
- package/docs/index.md +4 -2
- package/package.json +18 -5
- package/schema/schema.sql +316 -0
- package/templates/scaffold/.agents/skills/format-checker/check.mjs +23 -0
- package/templates/scaffold/.agents/skills/intake-interview/SKILL.md +13 -8
- package/templates/scaffold/.claude/skills/format-checker/check.mjs +23 -0
- package/templates/scaffold/.claude/skills/intake-interview/SKILL.md +13 -8
- package/templates/scaffold/AGENTS.md +142 -10
- package/templates/scaffold/README.md +37 -4
- package/templates/scaffold/env.example +23 -0
- package/templates/scaffold/gitignore +1 -0
- package/templates/scaffold/instance.md +3 -2
- package/templates/scaffold/package.json +9 -1
- package/templates/scaffold/pnpm-workspace.yaml +21 -5
- package/templates/scaffold/vercel.json +1 -1
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
name: intake-interview
|
|
3
3
|
description: The first conversation with the owner of this Knowledge System of Record — six questions that define what it is authoritative for and who may read 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.3.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Intake interview
|
|
9
9
|
|
|
10
10
|
`instance.md` is the identity of this Knowledge System of Record, and its
|
|
11
|
-
prose
|
|
12
|
-
guesses — interview the owner, one
|
|
13
|
-
they actually say.
|
|
11
|
+
prose IS the agent surface's system prompt (`ksor serve` wires it into the MCP
|
|
12
|
+
server's instructions). Do not draft it from guesses — interview the owner, one
|
|
13
|
+
question at a time, and write down what they actually say.
|
|
14
14
|
|
|
15
15
|
## The six questions
|
|
16
16
|
|
|
@@ -49,10 +49,15 @@ act on:
|
|
|
49
49
|
record's **display title**, the human name every page will lead with
|
|
50
50
|
("Acme Operations Handbook", not the slug) — then the authority sentence,
|
|
51
51
|
boundary, audience, and strictness — plain prose, written for a reader
|
|
52
|
-
who must act on it. Leave the frontmatter keys alone
|
|
53
|
-
an audience model from question 6
|
|
54
|
-
list) and `default_visibility
|
|
55
|
-
it from that moment on
|
|
52
|
+
who must act on it. Leave the identity frontmatter keys alone; two things
|
|
53
|
+
are written there when they apply: an audience model from question 6, as
|
|
54
|
+
`audiences:` (a list) and `default_visibility:` (`pnpm check` holds the
|
|
55
|
+
record to it from that moment on); and — only when the owner stands up the
|
|
56
|
+
served MCP rung — the `database:`/`embedding:`/`retrieval:` blocks (see
|
|
57
|
+
`AGENTS.md` → "Serving to agents"; that is a later climb, not part of this
|
|
58
|
+
interview). The strictness answer from question 5 is the intent behind the
|
|
59
|
+
`retrieval.vector_floor` on that climb, measured by `ksor calibrate` — capture
|
|
60
|
+
it in the prose now so it is ready.
|
|
56
61
|
- Restart `pnpm dev` afterwards so the site picks the new title up, and
|
|
57
62
|
show the owner their name on the page.
|
|
58
63
|
- Offer to capture the source list from question 4 as the first real
|
|
@@ -5,22 +5,25 @@ here; every coding agent reads this file first.
|
|
|
5
5
|
|
|
6
6
|
## The two worlds
|
|
7
7
|
|
|
8
|
-
| Path | What it is
|
|
9
|
-
| ------------- |
|
|
10
|
-
| `knowledge/` | **the record** — governed markdown, the owner's world, the product
|
|
11
|
-
| `system/` | **the system** — all code that serves the record
|
|
12
|
-
| `instance.md` | what this SoR is authoritative for; its prose
|
|
8
|
+
| Path | What it is |
|
|
9
|
+
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
10
|
+
| `knowledge/` | **the record** — governed markdown, the owner's world, the product |
|
|
11
|
+
| `system/` | **the system** — all code that serves the record |
|
|
12
|
+
| `instance.md` | what this SoR is authoritative for; its prose IS the agent surface's system prompt (`ksor serve` wires the body into the MCP server's instructions). Its `name:` is the machine identity (llms.txt, citations) and its body `# H1` is the DISPLAY TITLE every page leads with — both read when the server or build STARTS, so restart `pnpm dev` after changing either (found live 2026-08-18) |
|
|
13
13
|
|
|
14
14
|
The record survives the system: `knowledge/` must stay readable and complete
|
|
15
15
|
even if `system/` is deleted. Dependency flows one way — the system reads the
|
|
16
16
|
record; the record never references the system.
|
|
17
17
|
|
|
18
18
|
`instance.md` carries a closed key set — `format`, `name`, `ksor`, `site`,
|
|
19
|
-
|
|
19
|
+
the optional pair `audiences` + `default_visibility` (the record's reader
|
|
20
20
|
audiences, ordered least- to most-restricted with `public` first, and the one
|
|
21
|
-
a document takes when it names none — declared together or not at all)
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
a document takes when it names none — declared together or not at all), and
|
|
22
|
+
the four serve-config blocks `database` / `embedding` / `retrieval` / `budgets`
|
|
23
|
+
(present only once you climb to the served MCP rung — see "Serving to agents"
|
|
24
|
+
below; a `pnpm dev`-only project declares none). Everything else that matters
|
|
25
|
+
about the instance is the prose below the frontmatter; `pnpm check` names any
|
|
26
|
+
other key rather than ignoring it.
|
|
24
27
|
|
|
25
28
|
## Critical rules
|
|
26
29
|
|
|
@@ -37,12 +40,141 @@ everything that matters about it is the prose below that frontmatter;
|
|
|
37
40
|
## Commands (run at the repo root)
|
|
38
41
|
|
|
39
42
|
```sh
|
|
40
|
-
pnpm install # once, after cloning or scaffolding
|
|
43
|
+
pnpm install # once, after cloning or scaffolding (also fetches the pinned `ksor` tool)
|
|
41
44
|
pnpm dev # the site, hot-reloading, at http://localhost:3000
|
|
42
45
|
pnpm build # static site into system/site/out/
|
|
43
46
|
pnpm check # the format checker — run before handing off any knowledge change
|
|
44
47
|
```
|
|
45
48
|
|
|
49
|
+
## Serving to agents — the MCP rung (needs Postgres + a provider key)
|
|
50
|
+
|
|
51
|
+
`ksor serve` runs an MCP server over the record so agents get cited retrieval
|
|
52
|
+
with honest abstention. It is the climbed rung — not required for `pnpm dev`.
|
|
53
|
+
Stand it up in this order (each step's errors explain how to fix themselves):
|
|
54
|
+
|
|
55
|
+
1. **Configure `instance.md`.** One block is required — the name of the
|
|
56
|
+
environment variable holding your DSN (never the DSN itself):
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
database:
|
|
60
|
+
dsn_env: KSOR_DB_URL
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
That is enough. `embedding:` is optional and already defaults to
|
|
64
|
+
`provider: gemini`, `model: gemini-embedding-001`, `dim: 1536`; write it out
|
|
65
|
+
only to pin the space explicitly or to change it — and note that model and
|
|
66
|
+
dim are the PERSISTED identity of the embedding space, so changing either
|
|
67
|
+
later means re-embedding the whole corpus. Keep `dim` at or below 2000: the
|
|
68
|
+
pgvector HNSW index refuses more, and `gemini-embedding-001` can emit 3072.
|
|
69
|
+
|
|
70
|
+
Leave `retrieval:` out for now — the gate is off and the server says so.
|
|
71
|
+
Turning it on is step 4, AFTER the record is serving.
|
|
72
|
+
|
|
73
|
+
2. **Copy `.env.example` to `.env`** and fill it in — `ksor` reads it
|
|
74
|
+
automatically, so nothing needs exporting, and `.env` is already gitignored.
|
|
75
|
+
A real environment variable still wins over the file, so CI and production
|
|
76
|
+
overrides behave normally.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
cp .env.example .env
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Three values matter:
|
|
83
|
+
|
|
84
|
+
- `KSOR_DB_URL` — the Postgres store named by `instance.md`'s `dsn_env`. It
|
|
85
|
+
needs the pgvector extension: `CREATE EXTENSION vector;`
|
|
86
|
+
- `GEMINI_API_KEY` — the embedding provider key.
|
|
87
|
+
- `KSOR_AUTH_DISABLED=1` — **required for a local run.** `ksor serve`
|
|
88
|
+
refuses to boot unauthenticated without it, deliberately, so a server is
|
|
89
|
+
never left open by accident. It binds loopback, where auth off is the
|
|
90
|
+
intended dev shape. A PUBLIC deployment configures the SSO door instead —
|
|
91
|
+
see the comments in `.env.example` and "Serving safely" below.
|
|
92
|
+
|
|
93
|
+
3. **Bring it up — one command:**
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
pnpm up # schema → grant → ingest → serve
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Every step is re-runnable, so this is also how you **refresh after editing
|
|
100
|
+
`knowledge/`**: an applied schema reports "already applied", an existing
|
|
101
|
+
grant reports "already granted", and ingest builds a fresh generation.
|
|
102
|
+
|
|
103
|
+
**`pnpm up` ingests every time — but it re-EMBEDS nothing that has not
|
|
104
|
+
changed.** Chunks carry forward by content hash, so a rerun on an untouched
|
|
105
|
+
corpus makes zero provider calls (`embedded 0, carried N` in the output).
|
|
106
|
+
What it does spend is a generation: each run creates and activates a new one,
|
|
107
|
+
and they accumulate. So:
|
|
108
|
+
|
|
109
|
+
| You want to | Run |
|
|
110
|
+
| -------------------------------- | ------------------------------------------ |
|
|
111
|
+
| set up, or refresh after an edit | `pnpm up` |
|
|
112
|
+
| just restart the server | `pnpm serve` — no new generation |
|
|
113
|
+
| reap superseded generations | `pnpm exec ksor gc --instance instance.md` |
|
|
114
|
+
|
|
115
|
+
Run the steps individually (`pnpm schema`, `pnpm grant`, `pnpm ingest`)
|
|
116
|
+
when the acts belong to different people — a DBA holding the credentials
|
|
117
|
+
that authorize ingest, for instance.
|
|
118
|
+
|
|
119
|
+
4. **Turn the abstention gate on — deliberately, once it serves.** This is the
|
|
120
|
+
step that makes "not in this corpus" a real answer, and it is measured, never
|
|
121
|
+
guessed:
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
pnpm exec ksor calibrate --instance instance.md
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
It prints a recommended `vector_floor` for THIS corpus in THIS embedding
|
|
128
|
+
space. Paste the number in and restart:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
retrieval:
|
|
132
|
+
vector_floor: 0.55 # measured by ksor calibrate on <date>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Never copy a floor from another corpus — recalibrate, and record the
|
|
136
|
+
measurement beside the number. Writing `vector_floor: uncalibrated` declares
|
|
137
|
+
the intent to gate WITHOUT a measurement, and every serve refuses until a
|
|
138
|
+
number replaces it; that is the fail-closed posture, not a starting point.
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
pnpm schema # apply the DDL (once)
|
|
142
|
+
pnpm grant # authorize ingest for this corpus (once)
|
|
143
|
+
pnpm ingest # embed knowledge/ into a generation and activate it
|
|
144
|
+
pnpm serve # run the MCP server; any other verb: pnpm exec ksor <verb>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### How serving updates work (the generation model)
|
|
148
|
+
|
|
149
|
+
Each `ksor ingest` builds a **fresh generation** (invisible until activated) and
|
|
150
|
+
carries every unchanged embedding forward from the last complete generation —
|
|
151
|
+
so **re-ingest is safe and cheap**; only changed or failed chunks re-embed.
|
|
152
|
+
`--flip` swaps the active pointer, guarded by a catastrophic-shrink check
|
|
153
|
+
(`KSOR_MAX_SHRINK`, default `0.15` — a flip that drops more than 15% of nodes
|
|
154
|
+
refuses; override with `KSOR_ALLOW_SHRINK=1` when the shrink is intended). The
|
|
155
|
+
previous generation stays as a rollback target; `pnpm exec ksor gc` collects
|
|
156
|
+
abandoned ones.
|
|
157
|
+
|
|
158
|
+
### Serving safely (fail-closed posture)
|
|
159
|
+
|
|
160
|
+
`pnpm serve` binds **loopback with auth off** — safe for local use. A **public**
|
|
161
|
+
bind refuses to boot unless auth is configured (`KSOR_SSO_URL` +
|
|
162
|
+
`KSOR_MCP_RESOURCE_URL` + `KSOR_JWT_ALLOWED_AUDIENCES`, making it an OAuth
|
|
163
|
+
Resource Server) OR you deliberately set `KSOR_ALLOW_PUBLIC_UNAUTHENTICATED=1`.
|
|
164
|
+
Never let a dropped auth variable silently ship an open door. On a non-loopback
|
|
165
|
+
bind, set `KSOR_ALLOWED_HOSTS` / `KSOR_ALLOWED_ORIGINS`; on more than one
|
|
166
|
+
replica, set a shared `KSOR_SNAPSHOT_KEYS` (unset ⇒ a per-process key, so a
|
|
167
|
+
search token minted by one replica fails on another).
|
|
168
|
+
|
|
169
|
+
Two things worth being deliberate about:
|
|
170
|
+
|
|
171
|
+
- **`KSOR_ALLOW_PUBLIC_UNAUTHENTICATED=1` serves your whole record to anyone
|
|
172
|
+
who can reach the port.** It exists for deployments fronted by your own
|
|
173
|
+
gateway or network policy. If nothing else is in front, do not set it.
|
|
174
|
+
- **Set `KSOR_SSO_ISSUER` when your SSO stamps a stable `iss`.** Audience is
|
|
175
|
+
always enforced against `KSOR_JWT_ALLOWED_AUDIENCES`; naming the issuer adds
|
|
176
|
+
one more check for the cost of one variable.
|
|
177
|
+
|
|
46
178
|
## Publishing
|
|
47
179
|
|
|
48
180
|
`pnpm build` emits a fully static site (`system/site/out/`) deployable to
|
|
@@ -18,7 +18,39 @@ pnpm dev # browse the knowledge at http://localhost:3000
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
No pnpm? Run `npm install -g pnpm` — or `corepack enable pnpm` on Node
|
|
21
|
-
versions that bundle corepack.
|
|
21
|
+
versions that bundle corepack. The first `pnpm install` also fetches the
|
|
22
|
+
`ksor` tool (pinned in `package.json`) and writes it into your lockfile —
|
|
23
|
+
commit the updated lockfile.
|
|
24
|
+
|
|
25
|
+
### Serving to agents
|
|
26
|
+
|
|
27
|
+
The record's other surface is an MCP server for AI agents — the same
|
|
28
|
+
knowledge, cited, with honest abstention. It is the climbed rung: it needs a
|
|
29
|
+
Postgres store (with pgvector) and an embedding provider key, so it is not
|
|
30
|
+
part of `pnpm dev`. The ordered path is:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
cp .env.example .env # fill in KSOR_DB_URL, GEMINI_API_KEY, KSOR_AUTH_DISABLED=1
|
|
34
|
+
pnpm up # schema → grant → ingest → serve
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`ksor` reads `.env` automatically — nothing to export. `KSOR_AUTH_DISABLED=1`
|
|
38
|
+
is required for a local run: serve refuses to boot unauthenticated on purpose,
|
|
39
|
+
so a server is never open by accident.
|
|
40
|
+
|
|
41
|
+
Add one block to `instance.md` first — `database: { dsn_env: KSOR_DB_URL }`,
|
|
42
|
+
the NAME of the variable, never the DSN. That is the whole required config:
|
|
43
|
+
`embedding:` already defaults to Gemini at 1536 dimensions, and leaving
|
|
44
|
+
`retrieval:` out starts you with the abstention gate off and honest about it
|
|
45
|
+
(turn it on afterwards with `ksor calibrate`, once the record is serving).
|
|
46
|
+
|
|
47
|
+
`pnpm up` is re-runnable — it is also how you refresh after editing
|
|
48
|
+
`knowledge/`. It re-ingests each time but re-embeds only what changed, so an
|
|
49
|
+
untouched corpus costs no provider calls; to simply restart the server without
|
|
50
|
+
building a new generation, run `pnpm serve` on its own. `AGENTS.md` → "Serving to agents" is the
|
|
51
|
+
full runbook; your coding agent reads it first. `pnpm serve` binds loopback
|
|
52
|
+
with auth off for local use; a public bind fails closed unless auth is
|
|
53
|
+
configured. Any other operation is `pnpm exec ksor <verb>`.
|
|
22
54
|
|
|
23
55
|
Then talk to your coding agent — `AGENTS.md` carries the working rules, and
|
|
24
56
|
the agent kit in `.agents/skills/` knows how to interview you
|
|
@@ -34,7 +66,7 @@ different coding agent's way of finding the same working contract.
|
|
|
34
66
|
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
67
|
| `knowledge/` | **the record** — your governed markdown. The product; everything else serves it. |
|
|
36
68
|
| `system/` | the code that serves the record: the site today, more as you need it. |
|
|
37
|
-
| `instance.md` | what this record is authoritative for; its `name:` is the identity every surface publishes (read at server/build start — restart `pnpm dev` after renaming).
|
|
69
|
+
| `instance.md` | what this record is authoritative for; its `name:` is the identity every surface publishes (read at server/build start — restart `pnpm dev` after renaming). This prose IS the agent surface's system prompt — `ksor serve` wires it into the MCP server's instructions. |
|
|
38
70
|
| `AGENTS.md` | the working contract every coding agent reads first — the rules for writing knowledge here. |
|
|
39
71
|
| `CLAUDE.md` | one line, pointing at `AGENTS.md`. Claude Code looks for this filename, not that one. |
|
|
40
72
|
| `.agents/skills/` | the agent kit: `intake-interview` (define the record with you), `add-sources` (turn source material into governed documents), `format-checker` (the rules, as a program). |
|
|
@@ -42,8 +74,9 @@ different coding agent's way of finding the same working contract.
|
|
|
42
74
|
| `.gemini/settings.json` | points Gemini CLI at `AGENTS.md`; Gemini does not read that filename on its own. |
|
|
43
75
|
| `.github/workflows/validate.yml` | your CI: runs the same checker on every pull request and push to main. |
|
|
44
76
|
| `.gitattributes` | markdown is checked out byte-stable on every platform, so the same commit hashes the same everywhere. |
|
|
45
|
-
| `.
|
|
46
|
-
| `
|
|
77
|
+
| `.env.example` | the variables the served rung needs; copy to `.env` (gitignored) and fill in. |
|
|
78
|
+
| `.gitignore` | keeps build output, `node_modules/`, and `.env` out of the record's history. |
|
|
79
|
+
| `package.json` | the `pnpm dev` / `pnpm build` / `pnpm check` commands and the served rung's `pnpm up` (schema → grant → ingest → serve, or run them separately), the pinned `@panaversity/ksor` tool, and the pnpm version this project pins. |
|
|
47
80
|
| `pnpm-workspace.yaml` | where the workspace looks for code (`system/site`, plus reserved `system/gateways/*` and `system/packages/*`), and the supply-chain policy for installs. |
|
|
48
81
|
| `pnpm-lock.yaml` | the exact dependency versions — the reason two machines build the same site. |
|
|
49
82
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copy to .env — ksor reads it automatically, and .env is gitignored.
|
|
2
|
+
# A real environment variable always wins over this file, so CI and production
|
|
3
|
+
# keep their own values.
|
|
4
|
+
|
|
5
|
+
# The Postgres store, named by instance.md's database.dsn_env.
|
|
6
|
+
# Needs the pgvector extension: CREATE EXTENSION vector;
|
|
7
|
+
KSOR_DB_URL=postgresql://user:password@host:5432/dbname
|
|
8
|
+
|
|
9
|
+
# The embedding provider key. instance.md defaults to gemini-embedding-001.
|
|
10
|
+
GEMINI_API_KEY=
|
|
11
|
+
|
|
12
|
+
# Local development posture. `ksor serve` REFUSES to boot unauthenticated
|
|
13
|
+
# without this — deliberately, so a server is never open by accident. It binds
|
|
14
|
+
# loopback, where auth off is the intended dev shape.
|
|
15
|
+
#
|
|
16
|
+
# For a PUBLIC deployment, delete this line and configure the SSO door instead:
|
|
17
|
+
# KSOR_SSO_URL=https://your-sso.example.com
|
|
18
|
+
# KSOR_MCP_RESOURCE_URL=https://your-host.example.com/mcp
|
|
19
|
+
# KSOR_JWT_ALLOWED_AUDIENCES=https://your-host.example.com/mcp
|
|
20
|
+
# Serving a public bind with auth off additionally requires
|
|
21
|
+
# KSOR_ALLOW_PUBLIC_UNAUTHENTICATED=1, which serves your whole record to anyone
|
|
22
|
+
# who can reach the port.
|
|
23
|
+
KSOR_AUTH_DISABLED=1
|
|
@@ -18,8 +18,9 @@ the single most important sentence in the project._
|
|
|
18
18
|
|
|
19
19
|
Everything below this frontmatter is the identity of this instance: what the
|
|
20
20
|
corpus covers, who it serves, and how strictly it should decline questions it
|
|
21
|
-
does not cover.
|
|
22
|
-
|
|
21
|
+
does not cover. This prose IS the agent surface's system prompt — `ksor serve`
|
|
22
|
+
wires it into the MCP server's instructions — so write it for a reader who must
|
|
23
|
+
act on it.
|
|
23
24
|
|
|
24
25
|
Ask your coding agent to run the **intake interview** (it knows how — see
|
|
25
26
|
`.agents/skills/intake-interview/`), answer its questions, and let it write
|
|
@@ -6,7 +6,15 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "pnpm -C system/site dev",
|
|
8
8
|
"build": "pnpm -C system/site build",
|
|
9
|
-
"check": "node .agents/skills/format-checker/check.mjs"
|
|
9
|
+
"check": "node .agents/skills/format-checker/check.mjs",
|
|
10
|
+
"up": "pnpm schema && pnpm grant && pnpm ingest && pnpm serve",
|
|
11
|
+
"schema": "ksor schema --instance instance.md --apply",
|
|
12
|
+
"grant": "ksor grant --instance instance.md",
|
|
13
|
+
"ingest": "ksor ingest --instance instance.md --knowledge knowledge --flip",
|
|
14
|
+
"serve": "ksor serve"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@panaversity/ksor": "KSOR-STAMP-VERSION"
|
|
10
18
|
},
|
|
11
19
|
"engines": {
|
|
12
20
|
"node": ">=24"
|
|
@@ -8,12 +8,28 @@ packages:
|
|
|
8
8
|
# `pnpm install` here never picks up a day-zero compromised release.
|
|
9
9
|
minimumReleaseAge: 2880
|
|
10
10
|
|
|
11
|
+
# The one exception is the tool that scaffolded this project: `ksor init` pins
|
|
12
|
+
# `@panaversity/ksor` to the EXACT version the adopter deliberately ran, so the
|
|
13
|
+
# quarantine (a defense against unknown third-party releases) must not block the
|
|
14
|
+
# first install for 48 hours after every ksor release. Remove this line only if
|
|
15
|
+
# you unpin the dependency.
|
|
16
|
+
minimumReleaseAgeExclude:
|
|
17
|
+
- "@panaversity/ksor"
|
|
18
|
+
|
|
11
19
|
# Dependency install scripts are denied by default. Flip an entry to true
|
|
12
|
-
# only with a comment naming what breaks without it.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
20
|
+
# only with a comment naming what breaks without it. pnpm 11 exits 1 on every
|
|
21
|
+
# install until each build script is explicitly decided (found live:
|
|
22
|
+
# fresh-scaffold pnpm dev, 2026-08-18). All four below are reviewed and stay
|
|
23
|
+
# denied:
|
|
24
|
+
# esbuild, sharp — prebuilt platform binaries ship as optionalDependencies,
|
|
25
|
+
# so their install scripts are download fallbacks the site never needs.
|
|
26
|
+
# @google/genai, protobufjs — pulled in by the `@panaversity/ksor` serve
|
|
27
|
+
# tool. genai's flagged script is its own dev `prepare` (nothing the
|
|
28
|
+
# published tarball needs built); protobufjs's postinstall is a
|
|
29
|
+
# version-compat warning, nothing built. (Same review as the root
|
|
30
|
+
# workspace, 2026-08-19; serve works with both denied — verified live.)
|
|
17
31
|
allowBuilds:
|
|
18
32
|
esbuild: false
|
|
19
33
|
sharp: false
|
|
34
|
+
"@google/genai": false
|
|
35
|
+
protobufjs: false
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
3
3
|
"framework": null,
|
|
4
|
-
"installCommand": "pnpm install --frozen-lockfile",
|
|
4
|
+
"installCommand": "pnpm install --no-frozen-lockfile",
|
|
5
5
|
"buildCommand": "pnpm build",
|
|
6
6
|
"outputDirectory": "system/site/out",
|
|
7
7
|
"trailingSlash": true
|