@rayul/kordis 0.15.1 → 0.16.0
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/NOTICE +1 -1
- package/assets/AGENTS.md +108 -0
- package/assets/MEMGINEERING.md +3 -1
- package/assets/kordis-publishing/SKILL.md +115 -45
- package/assets/kordis-recommend/SKILL.md +2 -1
- package/assets/kordis-social/SKILL.md +19 -0
- package/assets/kordis-using/SKILL.md +7 -1
- package/assets/memgineering-recall/SKILL.md +85 -14
- package/assets/memgineering-rules/SKILL.md +59 -15
- package/assets/memgineering-setup/SKILL.md +76 -22
- package/assets/memgineering-writing/SKILL.md +68 -17
- package/dist/index.js +1427 -209
- package/package.json +2 -1
package/NOTICE
CHANGED
|
@@ -31,4 +31,4 @@ package and is not licensed with it.
|
|
|
31
31
|
where no keychain is available.
|
|
32
32
|
* `KORDIS_API_URL` points the CLI at a different host.
|
|
33
33
|
* Error telemetry is off unless turned on, carries no identity, and is
|
|
34
|
-
described in the repository's
|
|
34
|
+
described in the repository's `docs/security.md`, under "Error telemetry".
|
package/assets/AGENTS.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# packages/skills — the agent guidance both CLIs ship
|
|
2
|
+
|
|
3
|
+
Markdown that an agent on a user's machine reads and acts on. It is not a pnpm
|
|
4
|
+
package (no `package.json`, no scripts): the two CLIs copy it into their npm tarballs
|
|
5
|
+
at build time, and their `setup` commands install it into the user's agent tools.
|
|
6
|
+
These files are the product's user documentation; a reader who gets a wrong command
|
|
7
|
+
from them runs it in front of a user.
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- `MEMGINEERING.md` — the memgineering hub. `memgineering setup` strips its
|
|
12
|
+
frontmatter and injects the body between `<!-- memgineering-start -->` and
|
|
13
|
+
`<!-- memgineering-end -->` into `~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md` and
|
|
14
|
+
`~/.gemini/GEMINI.md` (and writes it as its own file under `~/.grok/rules/`). It is
|
|
15
|
+
in context for every session of every one of those tools.
|
|
16
|
+
- `memgineering-*` — seven sub-skills (`memory` is the map from question to verb;
|
|
17
|
+
`recall`, `writing`, `rules`, `setup`, `registry`, `installing` carry the detail),
|
|
18
|
+
installed into each tool's `skills/` directory and loaded by description match.
|
|
19
|
+
- `KORDIS.md` — the hub of the older `kordis` CLI, injected between
|
|
20
|
+
`<!-- kordis-start -->` and `<!-- kordis-end -->` by `kordis setup`.
|
|
21
|
+
- `kordis-*` — six sub-skills. `kordis setup` installs five; `kordis-memory` stays
|
|
22
|
+
in the repo and is drift-checked but is not installed, because its commands are
|
|
23
|
+
registered only under `KORDIS_EXPERIMENTAL_MEMORY=1`.
|
|
24
|
+
|
|
25
|
+
## Not in scope
|
|
26
|
+
|
|
27
|
+
- The behaviour these files describe and the code that installs them:
|
|
28
|
+
`apps/memgineering` (`src/brand.ts`, `src/commands/setup.ts`) and `apps/cli`
|
|
29
|
+
(`src/brand.ts`, `src/commands/setup.ts`). Change the code there, the words here,
|
|
30
|
+
in the same change.
|
|
31
|
+
- `apps/memgineering/assets/` and `apps/cli/assets/`: gitignored build output that
|
|
32
|
+
every build deletes and recopies. Never edit them.
|
|
33
|
+
- Contributor documentation; these files are written for users' agents.
|
|
34
|
+
|
|
35
|
+
## How the files ship
|
|
36
|
+
|
|
37
|
+
- `pnpm -F memgineering build` copies `MEMGINEERING.md` and every `memgineering-*`
|
|
38
|
+
directory into `apps/memgineering/assets/` (`apps/memgineering/scripts/copy-skills.mjs`).
|
|
39
|
+
`pnpm -F @rayul/kordis build` copies this whole directory into `apps/cli/assets/`.
|
|
40
|
+
- In both CLIs the hub file's presence in `assets/` is how the program tells a
|
|
41
|
+
published install from a source checkout; without it, `setup` reads this
|
|
42
|
+
directory directly.
|
|
43
|
+
- A user's installed copy changes only when they upgrade the CLI and `setup` runs
|
|
44
|
+
again. A fix here does not reach anyone until a release.
|
|
45
|
+
|
|
46
|
+
## Invariants
|
|
47
|
+
|
|
48
|
+
- Every command, subcommand and flag a file names exists in the CLI that ships it.
|
|
49
|
+
`memgineering <verb> [<subcommand>] --flag` is checked against the program
|
|
50
|
+
`apps/memgineering` builds; `kordis <verb> --flag` against `kordis <verb> --help`.
|
|
51
|
+
Every backticked `snake_case` identifier in a kordis file must exist as a key or
|
|
52
|
+
string literal in the source of `packages/contracts`, `packages/harness-schema`,
|
|
53
|
+
`packages/memory-engine`, `apps/mcp` or `apps/cli`.
|
|
54
|
+
- memgineering files spell the registry as `memgineering registry <verb>`. The flat
|
|
55
|
+
top-level aliases still work and are never taught.
|
|
56
|
+
- The set of `memgineering-*` directories equals `BRAND.subSkills` in
|
|
57
|
+
`apps/memgineering/src/brand.ts`, in both directions, and the hub names every one.
|
|
58
|
+
A new sub-skill is a directory, a `BRAND.subSkills` entry and a hub mention.
|
|
59
|
+
- Directory names are permanent. `setup` has no delete path, so a renamed sub-skill
|
|
60
|
+
leaves the old one on users' machines teaching the old surface.
|
|
61
|
+
- The `MEMGINEERING.md` body (after frontmatter) stays under 5,000 characters with no
|
|
62
|
+
fenced code blocks. It sits two characters under the cap, so any addition moves
|
|
63
|
+
text into a sub-skill; phrases already moved into `memgineering-writing` are pinned
|
|
64
|
+
by the drift test and may not disappear.
|
|
65
|
+
- `MEMGINEERING.md`'s `version:` frontmatter equals `apps/memgineering/package.json`
|
|
66
|
+
`version`; bumping the CLI means bumping this line. `KORDIS.md` carries its own
|
|
67
|
+
`version:` (0.2.0) that nothing ties to a package.
|
|
68
|
+
- memgineering files are English only (no Hangul anywhere, triggers included), and
|
|
69
|
+
no shipped file contains an absolute home path (`/Users/...`, `/home/...`) or a
|
|
70
|
+
real person's name or conversation. The kordis files' descriptions carry Korean
|
|
71
|
+
trigger phrases on purpose.
|
|
72
|
+
- The hosted connector URL in `memgineering-setup/SKILL.md` and in the hub equals the
|
|
73
|
+
one documented in `apps/mcp/README.md` and `HOSTED_CONNECTOR_URL` in the setup
|
|
74
|
+
command.
|
|
75
|
+
- The hub and `memgineering-writing` both keep the rule that a stored fact is one
|
|
76
|
+
that was checked, not worked out.
|
|
77
|
+
- A behaviour change in either CLI updates the matching file here in the same
|
|
78
|
+
change, and that release's changelog gets an `### Agent guidance` subsection: root
|
|
79
|
+
`CHANGELOG.md` (both language halves) for `KORDIS.md` and `kordis-*`,
|
|
80
|
+
`apps/memgineering/CHANGELOG.md` for the memgineering files.
|
|
81
|
+
|
|
82
|
+
## Writing patterns
|
|
83
|
+
|
|
84
|
+
- The hub routes; sub-skills explain. The hub holds only what must be true before
|
|
85
|
+
any skill loads, because it is paid for in every session.
|
|
86
|
+
- A sub-skill keeps its frontmatter (`name`, `description`, `type`,
|
|
87
|
+
`allowed-tools`). The description says when to load it, lists trigger phrases and
|
|
88
|
+
says what it is not for — tools pick skills by that text alone.
|
|
89
|
+
- When guidance has to override what a model assumes by default, state the negation
|
|
90
|
+
outright ("It does NOT wait for them") rather than only the fact.
|
|
91
|
+
- Commands are written for the agent to run on the user's behalf, not as
|
|
92
|
+
instructions for the user to type; the reader may be someone who has never opened
|
|
93
|
+
a terminal.
|
|
94
|
+
|
|
95
|
+
## Tests
|
|
96
|
+
|
|
97
|
+
There is no test runner here; the suites that check these files live in the CLIs.
|
|
98
|
+
|
|
99
|
+
- `pnpm -F memgineering test`, or `test:unit` (what CI's unit job runs) — both build
|
|
100
|
+
first, which recopies these files into `assets/`; `src/skill-drift.test.ts` covers
|
|
101
|
+
the memgineering files. Vitest run without that build checks whatever `assets/` an
|
|
102
|
+
earlier build left, not these files.
|
|
103
|
+
- `pnpm -F @rayul/kordis test` — `src/__tests__/skill-doc-drift.test.ts` spawns
|
|
104
|
+
`kordis <verb> --help` through tsx for every verb the kordis files mention; it is
|
|
105
|
+
slow by design and has a two-minute per-test ceiling.
|
|
106
|
+
- Read `Test Files N passed` for each package. A drift failure names the file and
|
|
107
|
+
the command or flag that does not exist; fix the guidance or the CLI, never the
|
|
108
|
+
test's verb list alone.
|
package/assets/MEMGINEERING.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: memgineering
|
|
3
3
|
description: Use whenever the user refers to something they told you before, asks what was decided, tells you something worth keeping, or settles something that should hold next time. The memory lives in their own folder and outlives this session; check it before answering from guesswork, and write to it when you learn something durable.
|
|
4
4
|
type: skill
|
|
5
|
-
version: 0.
|
|
5
|
+
version: 0.27.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# memgineering
|
|
@@ -83,6 +83,8 @@ at six skills, each of which loads on its own when its topic comes up:
|
|
|
83
83
|
- `memgineering-registry` — the public layer
|
|
84
84
|
- `memgineering-installing` — putting a package in their project, and updating it
|
|
85
85
|
|
|
86
|
+
Not shell-only: ChatGPT and Claude.ai reach a hosted brain via connector `https://mcp.memgineering.com/mcp`.
|
|
87
|
+
|
|
86
88
|
A host short on room lists a skill by NAME ONLY, no description — measured on
|
|
87
89
|
Claude Code. When you cannot see what it covers, READ
|
|
88
90
|
`<tool-home>/skills/memgineering-<name>/SKILL.md` before deciding it is empty.
|
|
@@ -20,19 +20,46 @@ Publish a valid, AI-review-passing version. ALWAYS dry-run first.
|
|
|
20
20
|
- `license` — SPDX (e.g. `MIT`, `Apache-2.0`, `CC-BY-4.0`).
|
|
21
21
|
- Optional: `homepage`, `tags`, `type`.
|
|
22
22
|
|
|
23
|
-
**`type`
|
|
24
|
-
|
|
25
|
-
`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
**`type` and `--type`:** A package is published as the type its
|
|
24
|
+
frontmatter's `type:` says, and nothing else. When the frontmatter has
|
|
25
|
+
no `type:` line, the CLI writes one in: `type: skill` for a directory
|
|
26
|
+
bundle, a `.skill` ZIP, or a single file named `SKILL.md` or
|
|
27
|
+
`*.skill.md` — so none of these needs `type:` written — or `type: <t>`
|
|
28
|
+
when you pass `--type <t>`, on any path. When the frontmatter names a
|
|
29
|
+
type, `--type` must say the same: a different value is refused before
|
|
30
|
+
anything is sent (`usage_error`, exit 2, in `--dry-run` too). Change the
|
|
31
|
+
frontmatter's `type:`, or drop `--type`.
|
|
32
|
+
|
|
33
|
+
Nothing is written over a `type:` line that is already there, or into a
|
|
34
|
+
file that begins with a byte-order mark. These fail instead, in
|
|
35
|
+
`--dry-run` too; write `type: <t>` in by hand:
|
|
36
|
+
|
|
37
|
+
- `type:` with no value (or `null`, a number, a list), and a file with a
|
|
38
|
+
byte-order mark and no `type:` line: `missing_required_frontmatter`
|
|
39
|
+
(exit 30), with or without `--type`.
|
|
40
|
+
- `type: ""`, an empty string: without `--type` it fails as
|
|
41
|
+
`unknown_type` (exit 30); with `--type` it disagrees, so it is refused
|
|
42
|
+
before anything is sent (`usage_error`, exit 2).
|
|
43
|
+
|
|
44
|
+
**Older CLIs (0.15.2 and earlier)** send `--type` only beside the
|
|
45
|
+
content and never write it in. They fill in `type: skill` themselves
|
|
46
|
+
when the frontmatter names no type: for a folder or `.skill` bundle
|
|
47
|
+
from 0.1.12, and for a single `SKILL.md` or `*.skill.md` from 0.6.4.
|
|
48
|
+
The registry refuses a `--type` that differs from the type it reads —
|
|
49
|
+
written or filled in — with `usage_error` (exit 2) and a hint naming
|
|
50
|
+
that type. From 0.2.2 their `--dry-run` checks the file locally and
|
|
51
|
+
sends no publish request (from 0.9.1, `--bump minor` or `major` makes
|
|
52
|
+
it look the package up), so it does not show this refusal; only a real
|
|
53
|
+
push does. 0.2.1 and earlier send the dry run to the registry, which
|
|
54
|
+
refuses it the same way as a real push. Writing `type:` in the
|
|
55
|
+
frontmatter works on every version.
|
|
29
56
|
|
|
30
57
|
**`version` field handling:**
|
|
31
58
|
|
|
32
59
|
- **First publish** — used as-is (else defaults to `0.1.0`).
|
|
33
60
|
- **Update** — the registry computes the next version from
|
|
34
61
|
`current_version + --bump <strategy>` (default `patch`). If the file's
|
|
35
|
-
`version` differs from that result, the API rejects with `
|
|
62
|
+
`version` differs from that result, the API rejects with `usage_error`. Either
|
|
36
63
|
drop the `version` field on updates, set `--bump` to match, or align
|
|
37
64
|
them.
|
|
38
65
|
- RECOMMENDED: **omit `version:` from frontmatter on update pushes** and
|
|
@@ -70,8 +97,11 @@ get rejected. Dry-run first like any push.
|
|
|
70
97
|
## Recording lineage (0.12.0+)
|
|
71
98
|
|
|
72
99
|
When a package descends from another (especially a judgment you adapted), record
|
|
73
|
-
the provenance on `push
|
|
74
|
-
|
|
100
|
+
the provenance on `push`. It shows up in the "Derived from / Adapted by" graph,
|
|
101
|
+
and when the derivative is another author's — public, with its current version
|
|
102
|
+
passed review — it also feeds the source's `community-adapted` trust tier and
|
|
103
|
+
gives the source a small trending boost. A derivative of a package you authored
|
|
104
|
+
yourself does neither. Record it with one of these flags:
|
|
75
105
|
|
|
76
106
|
| flag | edge kind | meaning |
|
|
77
107
|
| ----------------------- | ------------ | ----------------------------------------------- |
|
|
@@ -80,10 +110,13 @@ feeds the `community-adapted` trust tier, and gives a small trending boost:
|
|
|
80
110
|
| `--absorbs <slug>` | `absorption` | folds the source in as one part |
|
|
81
111
|
| `--remixes <slug>` | `remix` | recombines multiple sources |
|
|
82
112
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
the
|
|
113
|
+
A source that does not resolve — a typo'd slug, or a package that is
|
|
114
|
+
unpublished, deleted or private — **refuses the whole publish** with
|
|
115
|
+
`usage_error` (exit 2), and nothing is written. `--dry-run` does not look
|
|
116
|
+
sources up, so a typo first shows on the real push. Fix the slug, or publish
|
|
117
|
+
the source first, then push again. (Naming your own package as its source is
|
|
118
|
+
skipped instead, and listed in the response's `lineage.skipped`.) Declare
|
|
119
|
+
lineage honestly; it is the registry's trust signal, not decoration.
|
|
87
120
|
|
|
88
121
|
## Yanking a bad version (0.10.0+)
|
|
89
122
|
|
|
@@ -160,7 +193,7 @@ operator restores it.
|
|
|
160
193
|
| `--dry-run` | validate only; do not publish |
|
|
161
194
|
| `--bump <strategy>` | `patch` (default) / `minor` / `major` — only on update |
|
|
162
195
|
| `--slug <slug>` | override slug on first publish |
|
|
163
|
-
| `--type <type>` |
|
|
196
|
+
| `--type <type>` | fills a missing `type:`; must match an existing one |
|
|
164
197
|
| `--changelog <text>` | optional changelog entry attached to this version |
|
|
165
198
|
| `--no-wait` | return immediately without waiting for AI review |
|
|
166
199
|
| `--adapted-from <slug>` / `--forked-from` / `--absorbs` / `--remixes` | record lineage (see "Recording lineage") |
|
|
@@ -171,33 +204,66 @@ operator restores it.
|
|
|
171
204
|
|
|
172
205
|
### 1. Dry-run
|
|
173
206
|
|
|
174
|
-
`kordis push <file> --dry-run --json
|
|
175
|
-
and
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
`kordis push <file> --dry-run --json` runs on this machine (0.2.2+): it
|
|
208
|
+
sends no publish request and needs no sign-in. It validates the content
|
|
209
|
+
the real push would send — the frontmatter, including any `type:` the CLI
|
|
210
|
+
writes in, the body, and bundled files' paths and sizes — and answers
|
|
211
|
+
`{status, type, tier, capabilities, asset_count, flags, warnings, note}`
|
|
212
|
+
with `status` `dry_run_passed` (exit 0) or `dry_run_failed` (exit 30).
|
|
213
|
+
A pass can still list `flags` that do not block. `warnings` come from a
|
|
214
|
+
local scan for content that looks private — `ipv4_or_internal_host`,
|
|
215
|
+
`credential_like_string`, `absolute_home_path`,
|
|
216
|
+
`first_person_context_hint` — and never block.
|
|
217
|
+
|
|
218
|
+
It decides nothing the registry decides: no name conflict, no version (a
|
|
219
|
+
frontmatter `version` is not checked against the bump), no lineage
|
|
220
|
+
source, no declared-capability check, no rate limit, and no AI review.
|
|
221
|
+
Apart from finishing a pending `kordis login --emit-only`, as every
|
|
222
|
+
command does, its one registry call is a package lookup for
|
|
223
|
+
`--bump minor` or `--bump major` (0.9.1+), made when it can tell which
|
|
224
|
+
package: the frontmatter has a `name`, and you are signed in or `--slug`
|
|
225
|
+
names `<user>/<slug>`. A bump on a package that does not exist yet is
|
|
226
|
+
refused — `usage_error`, exit 2, from 0.9.2 (0.9.1 exits 1) — and if the
|
|
227
|
+
lookup fails any other way, the check is skipped. Only a real push gets
|
|
228
|
+
the registry's verdicts, including the AI review, which can land
|
|
229
|
+
`passed` / `rejected`, or leave the publish `status: "pending"` if the
|
|
230
|
+
worker hasn't decided within the wait window.
|
|
231
|
+
|
|
232
|
+
**Success criteria**: `status: "dry_run_passed"`.
|
|
233
|
+
|
|
234
|
+
### 2. Resolve what comes back
|
|
235
|
+
|
|
236
|
+
From the dry run:
|
|
237
|
+
|
|
238
|
+
- `dry_run_failed` (exit 30) — fix every listed flag, dry-run again.
|
|
239
|
+
- `usage_error` (exit 2) — a `--type` the frontmatter contradicts, or
|
|
240
|
+
`--bump minor` / `major` on a first publish; the message says which.
|
|
241
|
+
- `generic_failure` (exit 1) with a YAML hint — the frontmatter does not
|
|
242
|
+
parse; fix it as the hint says.
|
|
243
|
+
- `generic_failure` (exit 1) — the path is not a package the CLI can read:
|
|
244
|
+
it does not exist, a folder has no SKILL.md at its top, or a `.skill`
|
|
245
|
+
archive is broken or has no SKILL.md; the message says which.
|
|
246
|
+
|
|
247
|
+
Only from the real push (step 3), however clean the dry run was:
|
|
248
|
+
|
|
249
|
+
- `validation_failed` (exit 30) — the registry's checks: the dry run's,
|
|
250
|
+
plus ones it does not make, such as a `hook` or `mcp-server` that
|
|
251
|
+
declares `executable: false`; fix every listed flag.
|
|
252
|
+
- `usage_error` (exit 2) — for example a lineage source that does not
|
|
253
|
+
resolve, or a frontmatter `version` the bump does not produce; the
|
|
254
|
+
message says which. Nothing is written.
|
|
192
255
|
- `conflict` (exit 40) — slug taken; suggest a different slug (or pass
|
|
193
256
|
`--slug` if first publish).
|
|
194
|
-
-
|
|
195
|
-
|
|
196
|
-
`
|
|
257
|
+
- Review rejection — not an error: the push exits 0 and returns
|
|
258
|
+
`status: "rejected"` with the reasons in `review.flags`
|
|
259
|
+
(`ai_review_rejected`, exit 32, is defined but never sent). EXPLAIN the
|
|
260
|
+
rejection to the user. Do NOT silently retry. Includes deterministic
|
|
261
|
+
Stage-1 hits like `curl_pipe_shell`, `aws_access_key`,
|
|
262
|
+
`private_key_block`, etc.
|
|
197
263
|
- `rate_limited` (exit 31) — wait `retry_after_seconds`.
|
|
198
264
|
- `not_authenticated` (exit 10) — `kordis login`, then retry.
|
|
199
265
|
|
|
200
|
-
**Success criteria**: dry
|
|
266
|
+
**Success criteria**: the dry run passed.
|
|
201
267
|
|
|
202
268
|
### 3. Real push
|
|
203
269
|
|
|
@@ -212,9 +278,10 @@ yet — re-check with `kordis info <full_slug> --json` (or wait and re-run
|
|
|
212
278
|
## Versioning your push (0.9.0+)
|
|
213
279
|
|
|
214
280
|
- **First publish** derives the version from the frontmatter `version:`
|
|
215
|
-
field if present, else defaults to `0.1.0`. Passing `--bump`
|
|
216
|
-
first publish now returns a clear `usage_error`
|
|
217
|
-
ignored it)
|
|
281
|
+
field if present, else defaults to `0.1.0`. Passing `--bump minor` or
|
|
282
|
+
`--bump major` on a first publish now returns a clear `usage_error`
|
|
283
|
+
(pre-0.9 silently ignored it); `--bump patch`, the default, is ignored
|
|
284
|
+
there — drop `--bump` or set the frontmatter version explicitly.
|
|
218
285
|
- **Subsequent pushes** default to `--bump patch`. Explicit
|
|
219
286
|
`--bump minor` or `--bump major` ships the matching jump.
|
|
220
287
|
- **Frontmatter `version:` on an update** must match the result of
|
|
@@ -242,19 +309,21 @@ silently retry — explain why.
|
|
|
242
309
|
User (push-back after adapting a judgment): "that decision rule we adapted from
|
|
243
310
|
<upstream/slug> worked well — share our version back"
|
|
244
311
|
1. author the refitted judgment as a judgment-pattern file (structured
|
|
245
|
-
frontmatter
|
|
312
|
+
frontmatter with `type: judgment-pattern`, which the `--type` below
|
|
313
|
+
must match; see "Publishing a judgment-pattern")
|
|
246
314
|
2. kordis push ./judgment.md --type judgment-pattern --adapted-from <upstream/slug> --dry-run --json
|
|
247
315
|
3. clean → drop --dry-run for the real push
|
|
248
|
-
4. the response's `lineage.recorded` confirms the edge
|
|
249
|
-
|
|
250
|
-
|
|
316
|
+
4. the response's `lineage.recorded` confirms the edge. A wrong or unpublished
|
|
317
|
+
upstream slug is refused here, by the real push, with `usage_error` and
|
|
318
|
+
nothing written — the dry run in step 2 does not look sources up. Fix the
|
|
319
|
+
slug, or publish the source first. The edge gives the upstream
|
|
251
320
|
`community-adapted` credit and shows in its "Adapted by" graph.
|
|
252
321
|
</example>
|
|
253
322
|
|
|
254
323
|
<example>
|
|
255
324
|
User: "publish my new skill"
|
|
256
325
|
1. kordis push ./SKILL.md --dry-run --json
|
|
257
|
-
2.
|
|
326
|
+
2. dry_run_failed → list each flag, fix the file, re-run
|
|
258
327
|
3. clean → kordis push ./SKILL.md --json
|
|
259
328
|
4. show {full_slug, version, url}
|
|
260
329
|
</example>
|
|
@@ -264,7 +333,8 @@ User: "release v0.2.0 of <full_slug>"
|
|
|
264
333
|
- previous version was 0.1.x
|
|
265
334
|
1. drop or align the frontmatter `version` field — `--bump minor` from
|
|
266
335
|
0.1.x will yield 0.2.0; if the file says `0.2.0` that matches and is OK,
|
|
267
|
-
if it says anything else (e.g. `0.1.0`) the
|
|
336
|
+
if it says anything else (e.g. `0.1.0`) the real push is refused (the
|
|
337
|
+
dry run does not compare versions)
|
|
268
338
|
2. kordis push <file> --bump minor --dry-run --json
|
|
269
339
|
3. clean → kordis push <file> --bump minor --json
|
|
270
340
|
</example>
|
|
@@ -46,7 +46,8 @@ Anonymous: works without login. Personalized signal rides on an opt-in
|
|
|
46
46
|
`X-Kordis-Context` HTTP header (installed agent tools, top 3 CWD file
|
|
47
47
|
extensions, framework hints from package.json/pyproject.toml/Cargo.toml,
|
|
48
48
|
SHA-256-truncated hashes of installed slugs). Server uses it for in-flight
|
|
49
|
-
re-ranking ONLY — never persisted (see
|
|
49
|
+
re-ranking ONLY — never persisted (see `docs/security.md` in the Kordis
|
|
50
|
+
repository, "Search, context and addresses").
|
|
50
51
|
|
|
51
52
|
## Personalization opt-in
|
|
52
53
|
|
|
@@ -51,6 +51,23 @@ Post a top-level comment on a package. Auth required.
|
|
|
51
51
|
- `question` — explicit question expecting a reply (typically from the
|
|
52
52
|
author). Use when the user wants a response, not just to share thought.
|
|
53
53
|
|
|
54
|
+
**What the server refuses.** A comment's title and body get the same content
|
|
55
|
+
screen a published package gets: a download piped into a shell, an encoded
|
|
56
|
+
`eval`, API keys, tokens and private keys, and acceptable-use violations
|
|
57
|
+
(markets for stolen data, malware or attacks for hire, drug and weapon
|
|
58
|
+
brokering, abuse material, targeted harassment). A hit refuses the whole
|
|
59
|
+
comment with `usage_error` (exit 2) and nothing is posted, so there is nothing
|
|
60
|
+
to delete. The message names the field that matched (`comment title rejected …`
|
|
61
|
+
or `comment body rejected …`). Rewrite that field as the hint says and run the
|
|
62
|
+
command again; never resend the same text.
|
|
63
|
+
|
|
64
|
+
- **Reports: describe, do not quote.** A `report` that pastes the offending
|
|
65
|
+
line of a dangerous package (a `curl … | bash`, a key) is refused by the
|
|
66
|
+
same screen. Say what the step does and where it is instead.
|
|
67
|
+
- **Marker lines come back `[redacted]`.** A title or body line that imitates
|
|
68
|
+
the registry's untrusted-content markers is stored as `[redacted]`. Show the
|
|
69
|
+
user the `title` the response returns, not the one you sent.
|
|
70
|
+
|
|
54
71
|
Replies, edits, status flips (open/resolved on a `report`), listing
|
|
55
72
|
existing comments, and reading back your own comments are NOT yet exposed
|
|
56
73
|
in the CLI. Direct the user to `https://kordis.store/<full_slug>` for
|
|
@@ -140,6 +157,8 @@ User: "leave a tip on foo/bar saying it pairs well with baz/qux"
|
|
|
140
157
|
User: "report that the v0.3.0 release of foo/bar is broken on macOS"
|
|
141
158
|
- kordis comment foo/bar --kind report --title "v0.3.0 broken on macOS" \
|
|
142
159
|
--body "<reproducible details>" --json
|
|
160
|
+
- if it is refused (`usage_error`, exit 2), describe the problem without
|
|
161
|
+
quoting the offending text and post again
|
|
143
162
|
- mention that opening/resolving the report later requires the web UI
|
|
144
163
|
</example>
|
|
145
164
|
|
|
@@ -56,7 +56,13 @@ Returns the full body (Markdown) of a text-bearing package, plus an
|
|
|
56
56
|
`attribution` string. `--pin <semver>` overrides any `@suffix` on the slug.
|
|
57
57
|
**Context economy**: `--outline` returns just the section map (heading names);
|
|
58
58
|
then `--section <name>` returns one section's body. Read the outline first
|
|
59
|
-
when a body is large and you only need part of it.
|
|
59
|
+
when a body is large and you only need part of it. A section name the package
|
|
60
|
+
does not have exits 2 (`usage_error`): under `--json` the refusal is the error
|
|
61
|
+
envelope on stdout, and its `hint` lists the section names that do exist (or,
|
|
62
|
+
for a package with none, says to read the whole body); without `--json` it goes
|
|
63
|
+
to stderr only, so a body redirected into a file never captures it. Either way,
|
|
64
|
+
the `kordis read` command it prints keeps the version, `--pin` and
|
|
65
|
+
`--allow-pending` you read with, so it reaches the same body.
|
|
60
66
|
|
|
61
67
|
**Untrusted-content fence (all output modes, incl. `--json`)**: the body (and
|
|
62
68
|
outline description / section slice) arrives wrapped between exactly two lines
|
|
@@ -153,6 +153,11 @@ What you must not do is report what came back as everything the brain holds,
|
|
|
153
153
|
which is exactly what a short answer looks like to anyone who does not read the
|
|
154
154
|
line under it.
|
|
155
155
|
|
|
156
|
+
When every card with a project came from ONE project and the brain holds
|
|
157
|
+
others, recall says so (`scope_spread`: the project, and up to five others). If
|
|
158
|
+
the user meant one of those, ask again with `--scope <that project>` — the note
|
|
159
|
+
they want may be ranked just below a page full of the one the question named.
|
|
160
|
+
|
|
156
161
|
## Whether meaning was searched
|
|
157
162
|
|
|
158
163
|
A hosted brain can match on meaning as well as words — the same idea in other
|
|
@@ -177,28 +182,91 @@ anything about what the user knows.
|
|
|
177
182
|
If coverage says notes are missing entries, meaning was searched over part of
|
|
178
183
|
the brain. Do not report that as a complete search.
|
|
179
184
|
|
|
185
|
+
When meaning was used, each card also says what reached it — `matched`:
|
|
186
|
+
`"words"`, `"meaning"`, or `"both"`. A `"meaning"` card (printed as _matched by
|
|
187
|
+
meaning only_) shares no word with the question. That is right for a note in
|
|
188
|
+
another language and wrong for one the model merely found nearby, so read its
|
|
189
|
+
summary before you answer from it — never quote it back on the label alone.
|
|
190
|
+
|
|
180
191
|
## Two answers that are answers
|
|
181
192
|
|
|
182
193
|
**Nothing matched.** Say so, and do not go read their folder yourself to
|
|
183
|
-
compensate. At the default depth this has already searched
|
|
184
|
-
**the brain it searched**, so "nothing" is real
|
|
185
|
-
rather than a hint to search harder — read
|
|
186
|
-
words are still worth one retry;
|
|
187
|
-
less.
|
|
194
|
+
compensate. At the default depth this has already searched the body of every
|
|
195
|
+
note recall could read in **the brain it searched**, so "nothing" is real
|
|
196
|
+
information about those notes rather than a hint to search harder — read
|
|
197
|
+
`semantic` first, per above. Broader words are still worth one retry;
|
|
198
|
+
`--depth exact` is not — it looks at strictly less.
|
|
199
|
+
|
|
200
|
+
In a brain in a folder, that is not a promise about every file. Notes it left
|
|
201
|
+
out are counted below, but recall never looks inside a folder the user's own
|
|
202
|
+
rules exclude (`.gitignore`, `.memgignore`, the rules file): notes in one are
|
|
203
|
+
neither searched nor counted, and an answer where other notes were searched does
|
|
204
|
+
not mention them. So an empty answer is not proof that the user never wrote
|
|
205
|
+
something down. Say what was searched, and that folders their rules exclude
|
|
206
|
+
were not, rather than telling them they never wrote it. Do not open such a
|
|
207
|
+
folder yourself.
|
|
188
208
|
|
|
189
209
|
One brain is not the account. On a hosted account with more than one brain, an
|
|
190
|
-
empty answer
|
|
191
|
-
`--brain` command for each. Run it before you tell
|
|
192
|
-
written down — four testers reached that conclusion
|
|
193
|
-
next brain, and three of them said it out loud.
|
|
194
|
-
move the machine's pointer.
|
|
210
|
+
empty answer — or one of template cards only — names the brains that were NOT
|
|
211
|
+
read and prints a runnable `--brain` command for each. Run it before you tell
|
|
212
|
+
them the fact was never written down — four testers reached that conclusion
|
|
213
|
+
about a note sitting in the next brain, and three of them said it out loud.
|
|
214
|
+
Reading another brain does not move the machine's pointer.
|
|
215
|
+
|
|
216
|
+
With `--json`, an answer with nothing the user wrote in it carries `hint`: no
|
|
217
|
+
cards, or only template cards (`scaffolding: true`, below) — those are what
|
|
218
|
+
`init` wrote, not the user's notes. `hint` is the one next step, the most
|
|
219
|
+
specific that applies. First, the brain had nothing to search: it has no notes
|
|
220
|
+
yet (the `remember` command that writes the first one into that brain — or,
|
|
221
|
+
after `--brain` named a brain this machine does not point at, the
|
|
222
|
+
`memgineering use --brain "<name>"` that makes it the target, since `remember`
|
|
223
|
+
has no `--brain`), or it is a folder whose every note was left out (how many,
|
|
224
|
+
why, and the `memgineering reindex` command that names each one). Then: its
|
|
225
|
+
notes are in a script the question is not (ask again in that language), another
|
|
226
|
+
brain was not read (the `--brain` or `--vault` command that reads it), meaning
|
|
227
|
+
was not searched (and the server's reason), the hosted server's own advice, or
|
|
228
|
+
fewer and broader words. Read it before you conclude anything from
|
|
229
|
+
`cards: []` or from template cards. A `memgineering use --brain` in a hint
|
|
230
|
+
moves this machine's pointer for every later command, not just the next one:
|
|
231
|
+
offer it to the user and run it only on their yes. `hint` is absent whenever a
|
|
232
|
+
card they wrote came back.
|
|
233
|
+
|
|
234
|
+
**Held-back notes are counted in both modes.** When an answer has nothing the
|
|
235
|
+
user wrote in it, recall counts what a brain in a folder left out, says why,
|
|
236
|
+
and prints the `memgineering reindex` command that names each one: in the
|
|
237
|
+
terminal right under `_Nothing matched._` or under the template cards' header,
|
|
238
|
+
and at the front of `hint`. It opens with "Nothing in this brain could be
|
|
239
|
+
searched: …" when no note could be searched at all, and with "Not every note in
|
|
240
|
+
this brain was searched: …" when other notes were searched and at least one
|
|
241
|
+
note of the first kind below was left out. Recall itself never names or shows a
|
|
242
|
+
left-out note. The counts come in two kinds, and they mean different things:
|
|
243
|
+
|
|
244
|
+
- **Notes**: excluded by the user's rules (`.gitignore`, `.memgignore`, the
|
|
245
|
+
rules file), listed in `.memgdeny`, held back because the name looks private,
|
|
246
|
+
refused because the content looks like a credential, or behind a symlink. A
|
|
247
|
+
note the user wrote exists and was left out on purpose. Do NOT tell them the
|
|
248
|
+
brain is empty or that they never wrote it down: tell them such a note exists,
|
|
249
|
+
and why; to say where it is, run that `reindex` — it lists each path and
|
|
250
|
+
changes no note — and give them the path. Do not open, print or read a
|
|
251
|
+
held-back note into the conversation unless they ask what it says: it was
|
|
252
|
+
held back because it may be private.
|
|
253
|
+
- **Places nobody looked inside**: an excluded folder ("not looked inside"), or
|
|
254
|
+
another symlink, which is never followed. These are not evidence of a note —
|
|
255
|
+
an ignored `images/` or `.venv/` holds none. Say that recall could not look
|
|
256
|
+
inside them and that `reindex` names them; do not say a note was held back.
|
|
257
|
+
When "Nothing in this brain could be searched" lists only these, the brain may
|
|
258
|
+
hold no notes at all. Beside notes that were searched they are not counted at
|
|
259
|
+
all — see **Nothing matched** above.
|
|
195
260
|
|
|
196
261
|
**Cards that are not answers.** A card marked `not filled in yet` is one of the
|
|
197
|
-
five `01_BASE/` files, still
|
|
262
|
+
five `01_BASE/` files, still exactly what `init` wrote (line endings aside). Nobody has answered
|
|
198
263
|
it, so it is evidence of nothing — do not quote it back as what they think. When
|
|
199
264
|
every card carries that mark, recall says so above them (`--json`:
|
|
200
265
|
`scaffolding: true`), and that is the moment to offer to fill them in rather
|
|
201
|
-
than answer from them — see `memgineering-writing`.
|
|
266
|
+
than answer from them — see `memgineering-writing`. At most two such cards come
|
|
267
|
+
back per answer, plus any that is one side of a conflict, so both sides of a
|
|
268
|
+
conflict always show; the rest are counted (`templates_withheld`), never
|
|
269
|
+
silently dropped, and nothing anyone wrote is ever held back.
|
|
202
270
|
|
|
203
271
|
The mark disappears once the user writes in the file. A filled-in base note is
|
|
204
272
|
often the best answer in the brain: _who am I_, _what am I not allowed to do_,
|
|
@@ -219,8 +287,11 @@ On a hosted brain the folder counts too, as a name rather than a path: the CLI
|
|
|
219
287
|
sends the folder's project — `owner/repo` from the git remote, or whatever
|
|
220
288
|
`memgineering project` shows — and the server ranks what was asked about in
|
|
221
289
|
that project first. The response says so itself: `ranked_by` gains `asked about
|
|
222
|
-
in this project`, a card's reason reads `
|
|
223
|
-
|
|
290
|
+
in this project`, a card's reason reads `opened 1× · surfaced 2× in this project`
|
|
291
|
+
(or `surfaced 2× …, never opened`), and the footer names which project those
|
|
292
|
+
words mean. Only an open, or being the FIRST card of a recall, counts toward
|
|
293
|
+
the order; a card merely listed further down is counted in words but earns
|
|
294
|
+
nothing. Trust the footer over your
|
|
224
295
|
assumption in the other cases as well — it says when this folder names no
|
|
225
296
|
project (nothing was sent), and when the server does not rank by project yet
|
|
226
297
|
(it was sent and ignored). A path never leaves the machine either way.
|