@north-light/cli 0.3.462 → 0.3.464
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/dist/builtin-memory/crouter-concepts/scopes-and-trust.md +2 -2
- package/dist/builtin-memory/crouter-plugin/bundles-and-memory.md +22 -1
- package/dist/builtin-memory/crouter-plugin/deploying.md +12 -0
- package/dist/builtin-memory/internal/agent-shaping.md +2 -2
- package/dist/builtin-memory/internal/memory-loading.md +5 -5
- package/dist/clients/attach/viewer.js +548 -548
- package/dist/commands/doc/shared.js +2 -2
- package/dist/commands/profile/list.js +1 -1
- package/dist/commands/profile/new.js +1 -1
- package/dist/commands/profile/project.js +1 -1
- package/dist/commands/profile/show.js +1 -1
- package/dist/core/feed/feed.js +3 -3
- package/dist/core/graph/access.d.ts +4 -0
- package/dist/core/graph/access.js +3 -3
- package/dist/core/graph/documents.d.ts +5 -2
- package/dist/core/graph/documents.js +7 -7
- package/dist/core/graph/names.d.ts +1 -1
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/reader.d.ts +8 -0
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/repo-sync/exchange.d.ts +8 -2
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/repo-sync/ref-format.d.ts +2 -2
- package/dist/core/graph/repo-sync/ref-format.js +2 -2
- package/dist/core/graph/repo-sync/sync.js +2 -2
- package/dist/core/graph/spaces/app.js +1 -1
- package/dist/core/graph/spaces/own-memory.d.ts +18 -0
- package/dist/core/graph/spaces/own-memory.js +1 -0
- package/dist/core/graph/spaces/repo.d.ts +2 -1
- package/dist/core/graph/spaces/repo.js +1 -1
- package/dist/core/graph/types.d.ts +10 -1
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/roadmap.js +3 -3
- package/dist/core/scopes.d.ts +3 -0
- package/dist/core/scopes.js +1 -1
- package/dist/core/substrate/delivery/corpus.d.ts +1 -1
- package/dist/core/substrate/delivery/corpus.js +1 -1
- package/dist/core/substrate/delivery/deliver.js +3 -3
- package/dist/core/substrate/subject-fields.d.ts +4 -2
- package/dist/core/substrate/subject.js +1 -1
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/profiles.d.ts +3 -0
- package/dist/daemon/api/handlers/profiles.js +1 -1
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/cron/authority.js +1 -1
- package/docs/concepts/scopes-and-trust.md +2 -2
- package/docs/plugin/bundles-and-memory.md +23 -1
- package/docs/plugin/deploying.md +12 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -17,14 +17,14 @@ Scope strings are prefixed with `crtr:`. These are the ones the daemon and CLI c
|
|
|
17
17
|
| `crtr:act` | Creating, forking, reviving, closing and messaging nodes; `bash` and `files`; creating a human request or review (the `crtr human` commands are hidden from a run without it) |
|
|
18
18
|
| `crtr:schedule` | Creating, pausing, resuming, running and deleting crons (the `crtr cron` commands are hidden without it) |
|
|
19
19
|
| `crtr:memory:read:user[:path]`, `crtr:memory:rw:user[:path]`, `crtr:memory:manage:user` | The person's documents: reading, writing (`crtr doc`), and `manage` for every privacy level and every document |
|
|
20
|
-
| `crtr:memory:read:app:<id>`, `crtr:memory:rw:app:<id>` |
|
|
20
|
+
| `crtr:memory:read:app:<id>`, `crtr:memory:rw:app:<id>` | An app's documents; `…:profile:<profile>` narrows to one of its profiles. A run with no `scopes` list, and an app's own server, reads and writes its own app's space freely; a run started with a `scopes` list needs these for its own app too |
|
|
21
21
|
| `crtr:files:read\|rw:user:<dir>`, `crtr:files:read\|rw:app:<id>:<dir>`, `crtr:files:share` | Host files the run may mount, and sharing files beyond the app's own space |
|
|
22
22
|
| `crtr:conversations:read:app:<id>`, `crtr:objects:read:app:<id>` | Reading another app's conversations or node objects |
|
|
23
23
|
| `<provider>:<group>` | One tool group of a provider |
|
|
24
24
|
|
|
25
25
|
The `memory` in `crtr:memory:*` is the scope family's name for access to **documents** (see [[crouter-concepts/documents]]); there is no separate memory store. The older short names (`ask`, `act`, `schedule`, `memory:read`, `memory:write`, `llm`) are not accepted by `crtr sys connect --scopes`. A node's own documents, and an app's documents for its own nodes, need no `crtr:memory` scope.
|
|
26
26
|
|
|
27
|
-
This is an allow-list, not a claim that code will behave. The daemon checks the scope at the route that performs the action and rejects an unavailable one. The SDK’s [[crouter-sdk/nodes]] `scopes` field narrows a run: a run's list must stay inside what its creator and grant hold, and `crtr:act` requires `crtr:llm`. `client.memory` is not scope-gated: it lists and reads the person's `knowledge` and `preference` documents, and the answer is filtered by privacy — an app sees `public` documents, and a grant holding `crtr:memory:manage:user` also sees `friends` and `private` ones. Who may read any document is the owner-and-privacy model, not a per-call scope.
|
|
27
|
+
This is an allow-list, not a claim that code will behave. The daemon checks the scope at the route that performs the action and rejects an unavailable one. The SDK’s [[crouter-sdk/nodes]] `scopes` field narrows a run: a run's list must stay inside what its creator and grant hold, and `crtr:act` requires `crtr:llm`. `client.memory` is not scope-gated: it lists and reads the person's `knowledge` and `preference` documents, and the answer is filtered by privacy — an app sees `public` documents, and a grant holding `crtr:memory:manage:user` also sees `friends` and `private` ones. Who may read any document is the owner-and-privacy model, not a per-call scope. The exception is a run started with a `scopes` list: it reads its own app's documents (including automatic delivery of them at boot) only with `crtr:memory:read:app:<id>` and writes or edits them only with `crtr:memory:rw:app:<id>`; a refused write answers `scope_missing` naming the scope. Such a run still publishes its own reports with `crtr push` and its promoted node still gets a roadmap, but cannot edit any other document through that path, and a child never regains a scope its parent's list dropped.
|
|
28
28
|
|
|
29
29
|
```mermaid
|
|
30
30
|
flowchart LR
|
|
@@ -25,6 +25,27 @@ The tar has exactly `bundle.json`, `commands.json`, and `memory/<name>.md` membe
|
|
|
25
25
|
|
|
26
26
|
## Documents in the `memory` array
|
|
27
27
|
|
|
28
|
-
Add a `memory` array to `definePlugin` when the app needs to give agents reusable operating knowledge. Each entry has `name`, `kind`, `whenAndWhyToRead`, `body`, and optional `unlisted`. `name` is a safe relative path without the `.md` suffix. The package writes the frontmatter required by the archive installer, so the author supplies no YAML.
|
|
28
|
+
Add a `memory` array to `definePlugin` when the app needs to give agents reusable operating knowledge. Each entry has `name`, `kind`, `whenAndWhyToRead`, `body`, and optional `unlisted` and `rules`. `name` is a safe relative path without the `.md` suffix. The package writes the frontmatter required by the archive installer, so the author supplies no YAML.
|
|
29
29
|
|
|
30
30
|
`whenAndWhyToRead` is one routing sentence in the form `When <circumstance>, this <kind> should be read because <payoff>.` Keep the body to knowledge the agent needs to use the application. When the plugin is installed, crouter imports each entry as a public, read-only document owned by an app named after the plugin (an installed plugin is an app on the canvas), together with the generated commands. An agent reads it with `crtr canvas read <plugin>/<name>`, and `whenAndWhyToRead` becomes the document's preview. The `memory` array and `whenAndWhyToRead` are the plugin API's names; the result is an ordinary canvas document.
|
|
31
|
+
|
|
32
|
+
## Loading a document on its own
|
|
33
|
+
|
|
34
|
+
A document without `rules` loads nowhere on its own: an agent reaches it only through a listing, `crtr canvas search`, or a read it was pointed at. Add `rules` when the document must reach an agent because of what that agent is doing. Each rule has the shape of a `crtr doc write --rule` rule:
|
|
35
|
+
|
|
36
|
+
- `on` — `boot` (every session start), `file-read`, `document-read`, `command` or `pre-command`.
|
|
37
|
+
- `deliver` — `name`, `preview` (the `whenAndWhyToRead` line) or `content` (the whole body).
|
|
38
|
+
- `match` — globs the activity must match. It is required on every event except `boot`, which takes none. A `file-read` rule may give `matchFrontmatter` instead.
|
|
39
|
+
- `if` — an optional condition on the receiving node over `kind`, `mode`, `lifecycle`, `cwd`, `repo`, `profile` and `depth`, in the matcher language `crtr doc write --rule -h` describes.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
memory: [{
|
|
43
|
+
name: 'texting',
|
|
44
|
+
kind: 'knowledge',
|
|
45
|
+
whenAndWhyToRead: 'When replying to a text conversation, this knowledge should be read because a reply that leaks a message label confuses the person reading it.',
|
|
46
|
+
body: '# Texting\n\nNever put a message label such as `[m3]` in a text.\n',
|
|
47
|
+
rules: [{ on: 'boot', deliver: 'content', if: { cwd: { matches: '^/apps/acme/' } } }],
|
|
48
|
+
}],
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`definePlugin` rejects a rule the installer would drop. Every rule costs context in every node it reaches, so prefer the narrowest trigger, and keep a `boot` rule at `content` for short, always-relevant guidance. An installation's profile can lower what a plugin's documents deliver at `boot`.
|
|
@@ -55,6 +55,18 @@ const node = createNodeHandler(handler, { bodyLimit: 65536 });
|
|
|
55
55
|
|
|
56
56
|
A definition with `version: N`, or a list of definitions with one per supported major, is served per major. Each major N is mounted under `<mount>/v<N>/`, and its archive at `GET <mount>/v<N>/` declares `/v<N>` routes. `GET <mount>/versions` answers `{latest, supported}`. An unversioned single definition keeps the unversioned paths above. With `baseUrl`, pass the endpoint without any `/v<N>` segment.
|
|
57
57
|
|
|
58
|
+
### What needs a new major
|
|
59
|
+
|
|
60
|
+
`compareManifests(previous, next)` returns every change to a leaf that can break a caller written against the previous archive; the directory runs it against each major's stored archive. A leaf is breaking when it:
|
|
61
|
+
|
|
62
|
+
- is removed or renamed, or changes its tool group;
|
|
63
|
+
- removes a parameter, changes its type, makes it required, or adds a required one; removes an enum choice from a flag; or changes the environment variable it defaults from; or moves an existing positional;
|
|
64
|
+
- gains paging where it returned everything: a limit flag whose constraint states a default page size ("default N"), or a cursor input together with a `next_cursor`-style output. The answer keeps its shape, so callers that do not page silently get a partial list. A changed stated page size is breaking too. A new `--cursor`, `--limit` with no stated default, or `next_cursor` output alone is additive, and so is a declared `default`, which crtr applies while parsing and does not send;
|
|
65
|
+
- changes how the request is built: method, route (apart from the `/v<N>` segment), body root, constant body fields, a parameter's placement or wire name, or streaming;
|
|
66
|
+
- removes an output field, changes its type, makes it optional, drops an enum value, or adds a `file` output.
|
|
67
|
+
|
|
68
|
+
A new optional flag, a new leaf, a new optional output field and changed prose are additive.
|
|
69
|
+
|
|
58
70
|
## Archive response
|
|
59
71
|
|
|
60
72
|
The install response is an uncompressed tar with `Content-Type: application/x-tar`. Do not configure a proxy, CDN, or framework middleware to gzip or otherwise compress it. Crtr rejects compressed archive bytes. The handler sends an ETag and supports conditional `If-None-Match` requests automatically.
|
|
@@ -63,7 +63,7 @@ Every kind has both a `base` and an `orchestrator` persona; mode picks which one
|
|
|
63
63
|
|
|
64
64
|
A profile is a stable **agent identity** — itself an owner object: a fixed id, a display name, the documents it owns, and a **purview** of project directories it resolves documents and config from. Select it at spawn with `crtr node new --profile <id-or-name>`; omit and a child inherits the caller's profile. Pin a directory's default profile with `crtr profile default` so the startup chooser stops asking. Manage the identity and purview with `crtr profile new/show/project/rename/delete` (see `crtr profile -h`). `profile rename` changes the name and the profile's canvas handle together (the id stays), so `[[name/x]]` links and `owner=` listings follow it; it refuses when another live profile already holds the new name.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Every project path in the purview puts the repos enclosing it into the view of every node under the profile, whatever directory that node works in: their documents are listed and readable, and are delivered at boot and workspace-open when a rule of theirs matches, after the repos enclosing the node's own cwd. A rule's `if: {repo}` holds for any of those repos, so a repo-conditioned rule fires for every node of the profile; use `cwd` to condition on where the node works. `crtr profile project add` starts the added repos at a `preview` limit. The profile's delivery limit per owner caps how much of a repo's documents reach automatic boot and workspace-open context, whether the repo is in view through the cwd or the project list: give `content` to the repos whose front doors the profile's nodes should operate inside, `preview` or `name` to a project the profile must know exists but rarely enters, and `none` to purview held for config, plugins, and deliberate reads alone. Key a limit by repo handle, or `repo:<handle>` when another owner (such as a profile) shares that handle; the profile's own documents are never capped. It is a delivery dial, not an access one: `crtr canvas read` and `file-read`/`command` rules still reach those documents.
|
|
67
67
|
|
|
68
68
|
Reach for a **new** profile when a distinct body of work has its own set of directories and its own conventions worth dedicated documents — not for every repo. **The profile as owner** is exactly where cross-repo conventions and your stance toward that body of work belong (see the owners below); a profile spanning several related dirs lets one document reach every node working anywhere in that bundle.
|
|
69
69
|
|
|
@@ -73,7 +73,7 @@ An owner is itself an object (a node, the person, a profile, an app, a repo), an
|
|
|
73
73
|
|
|
74
74
|
- **node** — the default owner of what a node writes. Only this node's view includes it; it is deleted with the node unless a kept document links to it. One goal's cross-refresh state.
|
|
75
75
|
- **profile** (`--owner profile`) — every node running under that profile, across all the dirs in its purview. Cross-repo conventions and the user's stance toward that bundle of work.
|
|
76
|
-
- **repo** (`--owner repo`) — any agent operating in that one repo. Facts and procedures tied to that codebase. Every clone and worktree shares one set, synced over the repo's git ref `refs/crtr/docs`; a repo owns only public documents.
|
|
76
|
+
- **repo** (`--owner repo`) — any agent operating in that one repo, and any node whose profile lists the repo as a project. Facts and procedures tied to that codebase. Every clone and worktree shares one set, synced over the repo's git ref `refs/crtr/docs`; a repo owns only public documents.
|
|
77
77
|
- **user** (`--owner user`) — person-wide facts and preferences that follow the user everywhere, regardless of repo or profile.
|
|
78
78
|
- **crtr's own documents** (owned by the app `crtr`; markdown files in `src/builtin-memory/` of the crouter repo, imported as read-only documents) — ships inside crtr, so *every crtr user on every host* carries it. This owner holds the runtime's own self-documentation (this document lives here); a change here is a change to the product. Write here only for guidance every crouter user needs, never for anything person- or repo-specific.
|
|
79
79
|
|
|
@@ -18,7 +18,7 @@ A document is an object on the canvas ([[internal]] has the model): it has an ow
|
|
|
18
18
|
A document with no rules does exactly one thing: appears in the listing of the names above it. Everything beyond that is an explicit rule — in `--rule` JSON, `{"on": <event>, "match"?, "match_frontmatter"?, "if"?, "deliver": <level>}` (package frontmatter spells the key `match-frontmatter`). A rule's event constraints and optional `if` over the receiving node must both match; matching rules OR across and fold to their highest delivery (`content` > `preview` > `name`), with no cross-rule deny precedence. Multiple rules per event are legal. The events:
|
|
19
19
|
|
|
20
20
|
- **boot** — the frozen preference system snapshot and first-message knowledge catalog assembled when a context begins. No match; the rule's presence is the match.
|
|
21
|
-
- **workspace-open** — first-message context
|
|
21
|
+
- **workspace-open** — first-message context for a repo the node is eligible for (it works in the repo, or the repo is one of its profile's projects), capped by the profile's delivery limit for that repo. Repo-owned documents only.
|
|
22
22
|
- **file-read** — a `read` tool call returned a matching file: path globs vs the file's absolute path and basename, `./`-anchored globs vs its path relative to the owning repo's checkout, `match_frontmatter` predicates over the read file's own YAML frontmatter.
|
|
23
23
|
- **document-read** — another document's full body entered context, including `crtr canvas read`: name globs vs its name, `./` anchored to this document's own name.
|
|
24
24
|
- **command** — a matching shell command ran: globs vs the whole command string, `*` crossing `/`. Delivery is post-execution — right for "you are now in this territory"; when the point is "don't run this at all," use `pre-command` instead.
|
|
@@ -39,7 +39,7 @@ Silence is the absence of a rule; there is no `none` level. `summary` is **not**
|
|
|
39
39
|
|
|
40
40
|
## Conditions
|
|
41
41
|
|
|
42
|
-
A rule's `if` is the eligibility predicate over the receiving node — kind, mode, lifecycle, orchestration depth, cwd, the
|
|
42
|
+
A rule's `if` is the eligibility predicate over the receiving node — kind, mode, lifecycle, orchestration depth, cwd, the repos it is eligible for (`repo`: those enclosing its cwd and those of its profile's project paths; use `cwd` for location), profile — using the standard matcher vocabulary (`crtr doc write --rule -h`). When it fails, that rule delivers nothing; there is no document-level condition, so one document can choose a different level by node kind with two rules. No `if` means always eligible. Persona prose is just boot-content documents with an `if` (`if: {kind: developer, mode: base}`); guidance that should scale with effort is one predicate (`orchestration.depth: {gte: 2}`), not a mechanism.
|
|
43
43
|
|
|
44
44
|
## Listings and dedup
|
|
45
45
|
|
|
@@ -49,15 +49,15 @@ Every delivery registers the document or listing and its level in the loaded con
|
|
|
49
49
|
|
|
50
50
|
## The reader's view
|
|
51
51
|
|
|
52
|
-
A rule applies to every node whose view includes the document's owner. A node's view is: its own node, the repos it works in (nearest first), its profile, its app, the user, and installed plugins (each an app that owns its shipped documents), with crtr's own documents (owned by the app `crtr`) last. A bare name resolves in that same order, which is what lets a repo's document shadow one of crtr's own. A node's own documents are in no other node's view, so their rules apply only to that node.
|
|
52
|
+
A rule applies to every node whose view includes the document's owner. A node's view is: its own node, the repos it works in (those enclosing its cwd, nearest first), the repos enclosing each project path of its profile (in manifest order; a path that is gone or is not in a repo adds nothing, and a Linux node sandbox sees none), its profile, its app, the user, and installed plugins (each an app that owns its shipped documents), with crtr's own documents (owned by the app `crtr`) last. A bare name resolves in that same order, which is what lets a repo's document shadow one of crtr's own. A rule's `if: {repo}` condition holds when that repo is among the node's eligible repos (cwd repos plus project repos), so a rule on any document, including a user- or profile-owned one, can target a repo the profile covers; match `cwd` to condition on where the node works. `--owner repo` and write access follow only the repos enclosing the cwd, and a repo-relative `./` `file-read` glob stays anchored to the checkout of the repo that owns the rule. A node's own documents are in no other node's view, so their rules apply only to that node.
|
|
53
53
|
|
|
54
|
-
Each owner the selected profile manages carries a delivery limit — `none`, `name`, `preview`, or `content` — and that value is the maximum level anything that owner holds delivers at `boot` and `workspace-open`, whatever directory the node is working in. It only lowers: a rule authored below the maximum delivers at its authored level. `none` contributes nothing to either automatic event, so a `none` owner cannot shadow a same-named document from a wider owner — that wider document becomes the winner. An owner with no limit set delivers exactly what it authored.
|
|
54
|
+
Each owner the selected profile manages carries a delivery limit — `none`, `name`, `preview`, or `content` — and that value is the maximum level anything that owner holds delivers at `boot` and `workspace-open`, whatever directory the node is working in and whether the repo is in view through its cwd or the profile's project list. `crtr profile project add` starts the added repos at `preview`. It only lowers: a rule authored below the maximum delivers at its authored level. `none` contributes nothing to either automatic event, so a `none` owner cannot shadow a same-named document from a wider owner — that wider document becomes the winner. An owner with no limit set delivers exactly what it authored.
|
|
55
55
|
|
|
56
56
|
A limit is keyed by owner handle. A bare key (`crouter`) matches an owner of any type holding that handle, and handles are unique per type, not across types — so a repo and a profile can both be `crouter`. `<type>:<handle>` (`repo:crouter`, `profile:work`, `app:terminal`, `person:user`; the typed form `resolveName` accepts) names one owner exactly and wins over a bare key. A node's own documents and its own profile's documents are never capped, whichever key matches.
|
|
57
57
|
|
|
58
58
|
The limit reaches those two events and nothing else. `file-read`, `document-read`, `command`, and `pre-command` rules fire at their authored levels; listings, `crtr canvas read`, `crtr canvas search`, config resolution, and plugin discovery all see every document the reader may read. An explicit `crtr canvas read` is itself a content delivery, so reading a capped document returns its whole body and records content — the upgrade path for a document the automatic events disclosed only by name or preview. `if` conditions apply to companion documents delivered by the `document-read` event, not to the deliberate read or its listings.
|
|
59
59
|
|
|
60
|
-
A workspace's front door is an ordinary repo-owned document carrying the rule pair `{on: workspace-open, deliver: content}` + `{on: file-read, match: "./**", deliver: content}` — the operating guide loads when a node works in that repo or reads its files, not in every boot catalog. `crtr doc lint` requires exactly one `workspace-open` content document per repo the profile manages. Several repos render broad-to-specific.
|
|
60
|
+
A workspace's front door is an ordinary repo-owned document carrying the rule pair `{on: workspace-open, deliver: content}` + `{on: file-read, match: "./**", deliver: content}` — the operating guide loads when a node works in that repo or reads its files, and for a node whose profile lists the repo as a project it loads under that repo's delivery limit; it is not in every boot catalog. `crtr doc lint` requires exactly one `workspace-open` content document per repo the profile manages. Several repos render broad-to-specific.
|
|
61
61
|
|
|
62
62
|
A repo's documents about one package or subsystem are named under its folder (for example `packages/api/…`) and keep their `file-read` rules: reading any file beneath that folder delivers them, filtered against what the loaded context already contains.
|
|
63
63
|
|