@plurnk/plurnk-service 0.52.0 → 0.53.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/SPEC.md +14 -8
- package/dist/core/Engine.d.ts.map +1 -1
- package/dist/core/Engine.js +82 -32
- package/dist/core/Engine.js.map +1 -1
- package/dist/core/Engine.sql +39 -7
- package/dist/core/SchemeRegistry.d.ts.map +1 -1
- package/dist/core/SchemeRegistry.js +1 -2
- package/dist/core/SchemeRegistry.js.map +1 -1
- package/dist/core/packet-wire.d.ts +1 -2
- package/dist/core/packet-wire.d.ts.map +1 -1
- package/dist/core/packet-wire.js +111 -138
- package/dist/core/packet-wire.js.map +1 -1
- package/dist/core/teaching.d.ts +1 -1
- package/dist/core/teaching.d.ts.map +1 -1
- package/dist/core/teaching.js +6 -4
- package/dist/core/teaching.js.map +1 -1
- package/dist/schemes/Exec.d.ts.map +1 -1
- package/dist/schemes/Exec.js +11 -24
- package/dist/schemes/Exec.js.map +1 -1
- package/dist/schemes/Log.d.ts.map +1 -1
- package/dist/schemes/Log.js +3 -2
- package/dist/schemes/Log.js.map +1 -1
- package/dist/schemes/Run.js +1 -1
- package/dist/schemes/Run.js.map +1 -1
- package/dist/schemes/_entry-find.d.ts +1 -0
- package/dist/schemes/_entry-find.d.ts.map +1 -1
- package/dist/schemes/_entry-find.js +8 -2
- package/dist/schemes/_entry-find.js.map +1 -1
- package/dist/server/Daemon.d.ts.map +1 -1
- package/dist/server/Daemon.js +5 -8
- package/dist/server/Daemon.js.map +1 -1
- package/docs/log.md +1 -1
- package/package.json +16 -15
- package/requirements.md +3 -9
- package/dist/schemes/exec-receipt.d.ts +0 -4
- package/dist/schemes/exec-receipt.d.ts.map +0 -1
- package/dist/schemes/exec-receipt.js +0 -25
- package/dist/schemes/exec-receipt.js.map +0 -1
package/SPEC.md
CHANGED
|
@@ -573,7 +573,9 @@ Engine routes unconditionally to `exec` scheme (path slot is `cwd`, not a URI).
|
|
|
573
573
|
|
|
574
574
|
**Effect-gating.** Each executor declares an `effect` (`pure` | `read` | `host`); the service maps it to policy (`EffectPolicy`). A `host` runtime (subprocess; file-backed sqlite) mutates the host → **propose** (lifecycle §proposal): the run waits for a human gate, then spawns and writes stdout/stderr to channels of an `exec:///<runtime>/<loop>/<turn>/<seq>` entry (the executor is the URI authority; the coordinate that follows matches the op's log-row coordinate, e.g. `exec:///sh/1/1/2`), returning `102 Processing` immediately. Channel state transitions (`active` → `closed`/`errored`) drive what the model sees at subsequent turn boundaries (§channel-state). {§exec-host-proposes}
|
|
575
575
|
|
|
576
|
-
A `read` runtime (observes external state, e.g. search) or `pure` runtime (no observable effect, e.g. `:memory:` sqlite) is side-effect-free → **auto-run
|
|
576
|
+
A `read` runtime (observes external state, e.g. search) or `pure` runtime (no observable effect, e.g. `:memory:` sqlite) is side-effect-free → **auto-run**: no proposal, no human gate, no notification. It skips the gate a host command faces, but it does NOT resolve in-band — like every exec it backgrounds and streams, its output reaching the model through the environment-observation injector (a foisted READ of the stream's new bytes each turn, §exec-stream), never a same-turn receipt. {§exec-readpure-ungated}
|
|
577
|
+
|
|
578
|
+
**Stream surfacing.** An exec's output is *observed, not fetched*. Each turn the environment-observation injector — the same machine §env-delta rides — reads each of the run's open channels from a per-channel byte cursor and foists the new bytes as an `origin=plurnk` READ at `<runtime>:///<coord>#<channel>`, then advances the cursor — each delta carries the `startLine` that cursor implies, so a stream spanning turns numbers into one continuous sequence (lines 1–k, then k+1–m), not a fresh `1:` each turn. The delta is **folded** while the channel streams and auto-**opened** on the terminal one (the channel closed): a model ignores a chatty background run but always SEES a finished one. It never types these READs — it consumes them. The EXEC row itself renders the *command* it ran, `:::`-fenced and line-numbered per §render-rule so the model can line-reference its own code — the input, distinct from the stream above (the output). This is exec as an instance of one ambient machine, env-delta as another (sibling edits, timestamp cursor, always folded). {§exec-stream}
|
|
577
579
|
|
|
578
580
|
`SEND[499](exec:///<runtime>/<loop>/<turn>/<seq>)` cancels in-flight subprocess via subscription registry's stored AbortController (§stream-control).
|
|
579
581
|
|
|
@@ -1185,7 +1187,7 @@ The CAS is the **hard backstop**, at the moment of writing, on every accept path
|
|
|
1185
1187
|
type PacketSection = {
|
|
1186
1188
|
name: string; // stable id: definition, tools, schemes, log, prompt, budget, errors, git, requirements — or a plugin's own
|
|
1187
1189
|
slot: "system" | "user"; // the prompt-cache boundary; system-slot sections build the cache-stable system message
|
|
1188
|
-
header: string | null; // "
|
|
1190
|
+
header: string | null; // "## Plurnk System X", or null (definition renders verbatim)
|
|
1189
1191
|
content: string; // rendered markdown — what the model saw
|
|
1190
1192
|
tokens: number; // measured render-weight
|
|
1191
1193
|
};
|
|
@@ -1217,7 +1219,7 @@ Telemetry the model MUST react to immediately. Errors render in their own `error
|
|
|
1217
1219
|
|
|
1218
1220
|
- `budget` per §tokenomics: turn-weight and heaviest-entries tables with `tokenCeiling`/`tokenUsage`/`tokensFree`.
|
|
1219
1221
|
- `errors[]` from previous turn's dispatch. Required: `kind` discriminator. Additional kind-specific fields are flat on the element — NO nested `detail`. Canonical-JSON serialization sorts keys for prefix-cache friendliness.
|
|
1220
|
-
- Wire: one `* {canonical-JSON}` line per error under
|
|
1222
|
+
- Wire: one `* {canonical-JSON}` line per error under `## Plurnk System Errors`, push order. Buffer drains on read. {§telemetry-drain-on-read}
|
|
1221
1223
|
- **No prose `message` field.** Errors carry structured facts. The `kind` is the alert; the named fields are the data. Guidance, advice, hints, and exhortation MUST NOT appear in telemetry. Letting the model infer what to do from facts (and the log) beats handing it instructions it will second-guess.
|
|
1222
1224
|
- **Gamification policy (rummy precedent, plugins/error/error.js).** The model sees errors that **happened** — its actions failed, its emission didn't parse, its ops were truncated. The model does NOT see the engine's accounting *about* errors: strike streaks, cycle detection, sudden-death thresholds, no-ops bookkeeping. Surfacing internal state creates a gamification surface where the model optimizes for engine metrics (manufacturing a clean turn to reset the strike counter, e.g.) instead of the task. Engine bookkeeping drives abandonment silently; the model just sees its actual failures.
|
|
1223
1225
|
|
|
@@ -1240,23 +1242,23 @@ Strike accounting, cycle detection, sudden-death thresholds, and no-ops bookkeep
|
|
|
1240
1242
|
|
|
1241
1243
|
### §tools user.tools — the capability sheet
|
|
1242
1244
|
|
|
1243
|
-
The tools capability lines render **titleless**, directly under the `definition` (plurnk.md) section — the examples flow on from plurnk.md with no separate header — and **above**
|
|
1245
|
+
The tools capability lines render **titleless**, directly under the `definition` (plurnk.md) section — the examples flow on from plurnk.md with no separate header — and **above** `## Plurnk System Requirements`, so the model sees what it can *do* before the rules it must follow. Each enabled capability contributes one line via `Engine.#collectTools`; the section is omitted when nothing is enabled. {§tools-capability-sheet}
|
|
1244
1246
|
|
|
1245
|
-
**Contributors: the wired executor tags.** Each available executor tag *with an example* contributes ONE line — its canonical usage —
|
|
1247
|
+
**Contributors: the wired executor tags.** Each available executor tag *with an example* contributes ONE line — its canonical usage — via the shared `teachingLine` (identical shape to the scheme directory, §schemes); its doc is materialized at `plurnk://docs/<tag>.md` and discovered via the turn-1 `FIND(plurnk://docs/**)` foist, not linked inline (#270). A tag with no example contributes nothing; `PLURNK_DOCS_EXCLUDE` drops a named tag's line + doc. The boot `ExecutorRegistry` probes availability per tag, retiring the model's blind `<<EXEC[sh]…`.
|
|
1246
1248
|
|
|
1247
1249
|
### §schemes user.schemes — the scheme directory
|
|
1248
1250
|
|
|
1249
|
-
A
|
|
1251
|
+
A `## Plurnk System Schemes` section renders in the system slot **after the definition (plurnk.md — grammar + imperatives) and the tools sheet** — a terse directory of the scheme families available this session, so the model knows what URI schemes exist before it acts. Each scheme that ships a `manifest.example` contributes ONE line — its canonical usage (no scheme prefix; the example self-documents). The doc is NOT linked inline (#270) — it is materialized at `plurnk://docs/<scheme>.md` and discovered via the turn-1 `FIND(plurnk://docs/**)` foist, keeping the raw packet free of doc links. The in-tree core schemes author their depth in `docs/<name>.md` (loaded at boot, shipped with the package); daughter schemes ship `manifest.documentation`. The verbose semantics live in that pull doc (materialized like any entry, READ on demand), not the hot path — terse pushes, depth pulls, via the same `teachingLine` as the tools sheet (§tools). A scheme with no example (provisional) is omitted; `PLURNK_DOCS_EXCLUDE` drops a named scheme's line + doc. {§schemes-directory}
|
|
1250
1252
|
|
|
1251
1253
|
### §inject system.inject — the operator injection
|
|
1252
1254
|
|
|
1253
|
-
When `PLURNK_PACKET_INJECT` names a readable markdown file, its content renders as a
|
|
1255
|
+
When `PLURNK_PACKET_INJECT` names a readable markdown file, its content renders as a `## Plurnk Operator Notes` section in the system slot **right after the teaching** (definition → tools → schemes → inject), before the log — part of the cached prefix. Read per-turn so the operator's edits take effect live; a set-but-unreadable path fails the turn hard (a deliberate setting with a broken path is a misconfig, surfaced not hidden). `~/` expands to home. It's the operator-side complement to the plugin section hook — a pressure valve so reshaping the packet edits operator content, never the core. Unset → no section. {§packet-inject}
|
|
1254
1256
|
|
|
1255
1257
|
**The scheme self-doc contract.** `example` is the hot-path one-liner; `documentation` is the deep doc — the exact shape execs already use (`example` + `documentation`). `SchemeRegistry.teach()` renders the directory; `docEntries()` materializes the docs (per loop.run, alongside the operator docs). `documentation` rides a service-side `SchemeManifest` extension until plurnk-schemes#25 lands it in the contract.
|
|
1256
1258
|
|
|
1257
1259
|
### §requirements The requirements section — static per-turn rules
|
|
1258
1260
|
|
|
1259
|
-
Rendered at the END of the user packet under
|
|
1261
|
+
Rendered at the END of the user packet under `## Plurnk System Requirements` {§requirements-requirements-render-last} — closest to the assistant turn so the contract the model has to honor is the most recent text it sees. The header is omitted entirely when the requirements string is empty. {§requirements-requirements-omitted-when-empty} Contains rules the grammar block doesn't cover (canonical example: "Conclude the loop with `<<SEND[200]:answer:SEND`"). The op syntax leads the section. PLAN is mandated unconditionally by plurnk.md §Imperatives (grammar 0.70 requires every turn to lead with `<<PLAN`), so the service injects no separate plan directive here.
|
|
1260
1262
|
|
|
1261
1263
|
**Sourcing:** caller supplies the string via `runLoop({ requirements })` / `runTurn({ requirements })`. Plurnk-service exposes `PATHS.defaultRequirements` (resolves `PLURNK_REQUIREMENTS` env → in-package `requirements.md`). No DB cascade — same string every turn.
|
|
1262
1264
|
|
|
@@ -1376,6 +1378,10 @@ Same rule applies across Known, Unknown, Skill, Plurnk, File. Effective mimetype
|
|
|
1376
1378
|
- **Line-navigable** (text/markdown, text/plain, csv, source code, yaml, toml) → `N:\t` line-number prefix per line {§render-rule-line-navigable-prefix}
|
|
1377
1379
|
- **Tree-navigable** (application/json, application/xml, text/html, +json/+xml suffixes) → verbatim body (no `N:\t` — outer line numbers would collide with structural navigation like jsonpath/xpath) {§render-rule-tree-navigable-verbatim}
|
|
1378
1380
|
|
|
1381
|
+
A log row renders its **result body** for the content-returning ops — `READ@200` (the content it pulled) and `FIND@200` (the catalog rows / matched entries it returned) — under the query's fence, mimetype-driven per the rules above; every other op re-emits its statement. FIND included: the model must see what a find *returned*, not just its echoed query, and the turn-0 foisted `FIND(scheme:///**)` reaches the packet through this branch — without it the catalog preview is invisible. {§render-rule-find-renders-result}
|
|
1382
|
+
|
|
1383
|
+
An `EDIT` log row renders its **resulting span** — the edited area as it looks now (`rx.span`), under the target's fence — not the input statement: the log reads "and here's X now," so the model sees its edit's effect. The meta line still carries op + target; the model's own EDITs and the system delta-EDITs (§env-delta) render identically; an emptied span → meta line only. With no span stored, the row falls back to re-emitting the statement (the heredoc the model wrote). {§edit-result-render}
|
|
1384
|
+
|
|
1379
1385
|
The `N:\t` prefix is presentation/reference per plurnk.md ("not part of the source"); stripped before any matcher operation on the log entry.
|
|
1380
1386
|
|
|
1381
1387
|
### §markdown-primitive Mimetype primitive: text/markdown
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../../src/core/Engine.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Engine.js
CHANGED
|
@@ -616,15 +616,33 @@ class Engine {
|
|
|
616
616
|
// one row per scheme that has entries (scheme=null → file). log:// is absent —
|
|
617
617
|
// it lives in log_entries, not the catalog (present-mode, the # Log section).
|
|
618
618
|
const catalogSchemes = await this.#db.engine_scheme_catalog_summary.all({ session_id: sessionId });
|
|
619
|
-
|
|
619
|
+
// known:/// + unknown:/// ALWAYS foist, even at zero entries — else the model
|
|
620
|
+
// burns a turn running FIND(known:///**) itself, assuming its memory is merely
|
|
621
|
+
// being withheld. Every other scheme keeps the with-entries default (an empty
|
|
622
|
+
// catalog foist is noise for schemes the model isn't expected to pre-populate).
|
|
623
|
+
const foistSchemes = [...catalogSchemes];
|
|
624
|
+
for (const always of ["known", "unknown"]) {
|
|
625
|
+
if (!foistSchemes.some((c) => c.scheme === always))
|
|
626
|
+
foistSchemes.push({ scheme: always, entries: 0 });
|
|
627
|
+
}
|
|
628
|
+
for (const { scheme, entries } of foistSchemes) {
|
|
620
629
|
const schemeName = scheme ?? "file";
|
|
621
|
-
|
|
630
|
+
// plurnk → its docs subtree (FIND(plurnk://docs/**), uncapped) — the self-
|
|
631
|
+
// documenting surface. The prompt is shown in # Prompt, so the plurnk catalog
|
|
632
|
+
// the model orients on IS the docs; doc links are no longer rendered inline (#270).
|
|
633
|
+
const isPlurnk = schemeName === "plurnk";
|
|
634
|
+
// entries===0 (an always-foisted empty known/unknown) → uncapped: nothing to
|
|
635
|
+
// clamp, and Math.min(items, 0)=0 would emit a degenerate <1,0> marker.
|
|
636
|
+
const cap = isPlurnk || manifestItems < 0 || entries === 0 ? null : Math.min(manifestItems, entries);
|
|
622
637
|
const catalogFind = {
|
|
623
638
|
op: "FIND", suffix: "", signal: null,
|
|
624
639
|
target: {
|
|
625
|
-
kind: "url",
|
|
640
|
+
kind: "url",
|
|
641
|
+
raw: isPlurnk ? "plurnk://docs/**" : `${schemeName}:///**`,
|
|
642
|
+
scheme: schemeName,
|
|
626
643
|
username: null, password: null, hostname: null, port: null,
|
|
627
|
-
pathname: ""
|
|
644
|
+
pathname: isPlurnk ? "/docs/**" : "/**",
|
|
645
|
+
params: {}, fragment: null,
|
|
628
646
|
},
|
|
629
647
|
body: null,
|
|
630
648
|
lineMarker: cap === null ? null : { marks: [1, cap] },
|
|
@@ -686,10 +704,13 @@ class Engine {
|
|
|
686
704
|
nextActionIndex++;
|
|
687
705
|
}
|
|
688
706
|
}
|
|
689
|
-
// §
|
|
690
|
-
//
|
|
691
|
-
//
|
|
707
|
+
// §environment-observation — pre-seed the run's ambient observations (what changed since
|
|
708
|
+
// it last looked) as foisted rows before the packet composes; advance the action index
|
|
709
|
+
// past them so model ops continue after. Two instances of one machine: env-delta (sibling
|
|
710
|
+
// edits · timestamp cursor · always folded) and exec streams (channel bytes · byte cursor ·
|
|
711
|
+
// terminal delta opens). §env-delta §exec-stream
|
|
692
712
|
nextActionIndex += await this.#materializeEnvironmentDeltas({ sessionId, runId, loopId, turnId, fromSequence: nextActionIndex });
|
|
713
|
+
nextActionIndex += await this.#materializeStreamDeltas({ runId, loopId, turnId, fromSequence: nextActionIndex });
|
|
693
714
|
// SPEC §telemetry — git working-tree state for the telemetry section, read once
|
|
694
715
|
// (a service-side `git status` shell-out) and threaded into the budget
|
|
695
716
|
// rebuild too so it isn't re-shelled on overflow.
|
|
@@ -952,11 +973,11 @@ class Engine {
|
|
|
952
973
|
// requirements). Read Paths.defaultRequirements (PLURNK_REQUIREMENTS env →
|
|
953
974
|
// requirements.md) fresh each build so edits take effect; a non-empty param wins.
|
|
954
975
|
const baseRequirements = requirements.length > 0 ? requirements : await readFile(Paths.defaultRequirements, "utf8");
|
|
955
|
-
//
|
|
956
|
-
//
|
|
957
|
-
//
|
|
958
|
-
//
|
|
959
|
-
|
|
976
|
+
// No injected syntax line: the grammar already headlines the system definition (§Syntax) and
|
|
977
|
+
// leads requirements.md, so a third copy here was pure duplication in the model's packet. PLAN
|
|
978
|
+
// is mandated unconditionally by plurnk.md §Imperatives (grammar 0.70 requires every turn to
|
|
979
|
+
// lead with PLAN), so the service injects no separate plan directive either (the former
|
|
980
|
+
// PLURNK_PLAN gating is retired — PLURNK_PLAN is no longer a flag).
|
|
960
981
|
const log = await this.#buildLog(runId);
|
|
961
982
|
const telemetryErrors = presetTelemetry ?? await this.#buildTelemetryErrors(loopId, currentTurnSeq);
|
|
962
983
|
const countTokens = (t) => provider.countTokens(t); // §provider-surface-counttokens
|
|
@@ -970,9 +991,6 @@ class Engine {
|
|
|
970
991
|
// omitted, section lines still shown). §tokenomics-render-weight-budget
|
|
971
992
|
const ceiling = _a.computeCeiling(provider.contextSize, this.#budgetCeiling);
|
|
972
993
|
const budgetReadout = this.#renderBudget(PacketWire.measureLogBudget(log, countTokens), ceiling);
|
|
973
|
-
// Per-scheme tally (§packet) so the model sees which schemes hold content without
|
|
974
|
-
// probing e.g. FIND(known://**) every turn. "" when empty → the section is omitted.
|
|
975
|
-
const catalogSummary = await this.#db.engine_scheme_catalog_summary.all({ session_id: sessionId });
|
|
976
994
|
// The default packet: an ordered list of sections, each addressable state
|
|
977
995
|
// (§packet-construction). `slot` is the prompt-cache boundary; the STATIC
|
|
978
996
|
// sections (definition, tools) lead the system slot so they form the cached
|
|
@@ -986,13 +1004,12 @@ class Engine {
|
|
|
986
1004
|
{ name: "tools", slot: "system", header: null, content: tools.join("\n"), tokens: 0 }, // titleless — the examples flow on from plurnk.md (definition) directly above
|
|
987
1005
|
{ name: "schemes", slot: "system", header: "Plurnk System Schemes", content: this.#schemes.teach(), tokens: 0 },
|
|
988
1006
|
...(inject !== null ? [{ name: "inject", slot: "system", header: "Plurnk Operator Notes", content: inject, tokens: 0 }] : []),
|
|
989
|
-
{ name: "log", slot: "system", header: "Plurnk System Log", content: PacketWire.renderLog(log), tokens: 0 },
|
|
1007
|
+
{ name: "log", slot: "system", header: "Plurnk System Log", content: PacketWire.renderLog(log, countTokens), tokens: 0 },
|
|
990
1008
|
{ name: "prompt", slot: "user", header: "Plurnk System User Prompt", content: prompt, tokens: 0 },
|
|
991
1009
|
{ name: "budget", slot: "user", header: "Plurnk System Budget", content: budgetReadout, tokens: 0 },
|
|
992
1010
|
{ name: "errors", slot: "user", header: "Plurnk System Errors", content: PacketWire.renderErrors(telemetryErrors), tokens: 0 },
|
|
993
1011
|
{ name: "git", slot: "user", header: "Plurnk System Git Status", content: PacketWire.renderGit(gitStatus), tokens: 0 },
|
|
994
|
-
{ name: "
|
|
995
|
-
{ name: "requirements", slot: "user", header: "Plurnk System Requirements", content: requirementsText, tokens: 0 },
|
|
1012
|
+
{ name: "requirements", slot: "user", header: "Plurnk System Requirements", content: baseRequirements, tokens: 0 },
|
|
996
1013
|
];
|
|
997
1014
|
// Plugin packet control (§packet-construction): trusted schemes rewrite the
|
|
998
1015
|
// default list — add, remove, reorder — in-process, before measurement.
|
|
@@ -1018,20 +1035,22 @@ class Engine {
|
|
|
1018
1035
|
const packetTokens = countTokens(PacketWire.renderSlot(sections, "system")) + countTokens(PacketWire.renderSlot(sections, "user"));
|
|
1019
1036
|
return { tokens: packetTokens, sections, telemetryErrors };
|
|
1020
1037
|
}
|
|
1021
|
-
// Budget readout body, rendered into the
|
|
1038
|
+
// Budget readout body, rendered into the `## Plurnk System Budget` section.
|
|
1022
1039
|
// Headline `ceiling/free` only when a ceiling exists; section lines for the
|
|
1023
1040
|
// curatable index/log weight the model can FOLD back. tokensFree is a
|
|
1024
1041
|
// placeholder here — buildSystem substitutes it after measuring the packet.
|
|
1025
1042
|
#renderBudget(log, ceiling) {
|
|
1026
1043
|
const lines = [];
|
|
1027
1044
|
if (ceiling !== null)
|
|
1028
|
-
lines.push(`
|
|
1045
|
+
lines.push(`Token Ceiling ${ceiling} · Token Usage ${TOKEN_USAGE_PLACEHOLDER} (${TOKEN_PERCENT_PLACEHOLDER}%) · Tokens Free ${TOKENS_FREE_PLACEHOLDER}`);
|
|
1029
1046
|
if (log.entries > 0) {
|
|
1047
|
+
if (lines.length > 0)
|
|
1048
|
+
lines.push("");
|
|
1030
1049
|
lines.push(`Log entries: ${log.entries} entries, ${log.tokens} tokens`);
|
|
1031
1050
|
// Per-turn weight — the grinder's rollback unit, oldest first: the
|
|
1032
1051
|
// model sees what's first to go (§tokenomics {§tokenomics-turn-totals}).
|
|
1033
1052
|
if (log.byTurn.length > 0) {
|
|
1034
|
-
lines.push("Turns:", "| turn | tokens |", "|---|--:|");
|
|
1053
|
+
lines.push("", "Turns:", "| turn | tokens |", "|---|--:|");
|
|
1035
1054
|
for (const t of log.byTurn)
|
|
1036
1055
|
lines.push(`| ${t.turn} | ${t.tokens} |`);
|
|
1037
1056
|
}
|
|
@@ -1040,14 +1059,14 @@ class Engine {
|
|
|
1040
1059
|
// lists log:/// rows (log items), distinct from catalog entries (plurnk.md: "EDIT
|
|
1041
1060
|
// is only for entries. Do not attempt to edit log items.").
|
|
1042
1061
|
if (log.largest.length > 0) {
|
|
1043
|
-
lines.push("Heaviest items:", "| item | tokens |", "|---|--:|");
|
|
1062
|
+
lines.push("", "Heaviest items:", "| item | tokens |", "|---|--:|");
|
|
1044
1063
|
for (const e of log.largest)
|
|
1045
1064
|
lines.push(`| ${e.path} | ${e.tokens} |`);
|
|
1046
1065
|
}
|
|
1047
1066
|
}
|
|
1048
1067
|
return lines.join("\n");
|
|
1049
1068
|
}
|
|
1050
|
-
// The
|
|
1069
|
+
// The ## Plurnk System Tools capability sheet (SPEC §tools). A hook: each enabled
|
|
1051
1070
|
// capability contributes one line, rendered above Requirements so the model sees what
|
|
1052
1071
|
// it can do before the rules. Each available executor tag contributes its self-documenting
|
|
1053
1072
|
// example (plurnk-execs#7), retiring the blind EXEC.
|
|
@@ -1070,7 +1089,7 @@ class Engine {
|
|
|
1070
1089
|
// the fuller doc (materialized at plurnk://docs/<tag>.md) rides an inline link whose
|
|
1071
1090
|
// token cost lives on that manifest entry. No example → no line (like a provisional scheme).
|
|
1072
1091
|
if (entry?.example)
|
|
1073
|
-
tools.push(teachingLine(entry.example
|
|
1092
|
+
tools.push(teachingLine(entry.example));
|
|
1074
1093
|
}
|
|
1075
1094
|
}
|
|
1076
1095
|
return tools;
|
|
@@ -1221,6 +1240,7 @@ class Engine {
|
|
|
1221
1240
|
mimetype_tx: r.mimetype_tx,
|
|
1222
1241
|
folded: r.expanded === 0,
|
|
1223
1242
|
source: r.source,
|
|
1243
|
+
attrs: r.attrs === null ? null : JSON.parse(r.attrs),
|
|
1224
1244
|
}));
|
|
1225
1245
|
}
|
|
1226
1246
|
// §env-delta (§actor-boundary-no-mutex: runs share without locks; a conflict surfaces as a delta, never prevented) — at pre-turn build, surface what changed in the shared world since this
|
|
@@ -1261,6 +1281,37 @@ class Engine {
|
|
|
1261
1281
|
}
|
|
1262
1282
|
return written;
|
|
1263
1283
|
}
|
|
1284
|
+
// §environment-observation — exec streams as an instance of the ambient-observe machine:
|
|
1285
|
+
// each turn, emit each owned channel's unshown byte-delta as a foisted READ@200 row. Folded
|
|
1286
|
+
// while the channel streams; the terminal delta (channel closed) auto-OPENs. The cursor is the
|
|
1287
|
+
// streamEnd recorded on the channel's prior delta — no exec-specific surfacing, just the
|
|
1288
|
+
// env-observe loop with a byte cursor where env-delta uses a timestamp. §exec-stream
|
|
1289
|
+
async #materializeStreamDeltas(args) {
|
|
1290
|
+
const { runId, loopId, turnId, fromSequence } = args;
|
|
1291
|
+
const channels = await this.#db.engine_run_stream_channels.all({ run_id: runId });
|
|
1292
|
+
let written = 0;
|
|
1293
|
+
for (const ch of channels) {
|
|
1294
|
+
const prior = await this.#db.engine_stream_cursor.get({
|
|
1295
|
+
run_id: runId, scheme: ch.runtime, pathname: ch.coord, fragment: ch.channel,
|
|
1296
|
+
});
|
|
1297
|
+
const cursor = prior !== undefined ? (JSON.parse(prior.attrs).streamEnd ?? 0) : 0;
|
|
1298
|
+
if (ch.content.length <= cursor)
|
|
1299
|
+
continue; // nothing new to show this turn
|
|
1300
|
+
const closed = ch.state === "closed" || ch.state === "errored";
|
|
1301
|
+
// startLine continues the line count across turns: a multi-turn stream's deltas number
|
|
1302
|
+
// into one sequence (lines N..M, then M+1..), not N independent "1:" restarts. §exec-stream
|
|
1303
|
+
const startLine = (ch.content.slice(0, cursor).match(/\n/g)?.length ?? 0) + 1;
|
|
1304
|
+
await this.#db.engine_insert_stream_delta.run({
|
|
1305
|
+
run_id: runId, loop_id: loopId, turn_id: turnId, sequence: fromSequence + written,
|
|
1306
|
+
scheme: ch.runtime, pathname: ch.coord, fragment: ch.channel,
|
|
1307
|
+
rx: JSON.stringify({ status: 200, content: ch.content.slice(cursor), mimetype: "text/stream", startLine }),
|
|
1308
|
+
attrs: JSON.stringify({ streamEnd: ch.content.length }),
|
|
1309
|
+
expanded: closed ? 1 : 0, // §exec-stream — terminal delta auto-OPENs; ongoing folds
|
|
1310
|
+
});
|
|
1311
|
+
written++;
|
|
1312
|
+
}
|
|
1313
|
+
return written;
|
|
1314
|
+
}
|
|
1264
1315
|
// §env-delta — the filesystem as an actor. Ambient disk divergences detected at
|
|
1265
1316
|
// pre-turn (git membership re-read) are logged as the plurnk run's source=file EDIT
|
|
1266
1317
|
// "fictions": no op happened, but EDIT is the only grammar the model has for "your
|
|
@@ -1996,12 +2047,12 @@ class Engine {
|
|
|
1996
2047
|
let attrsObj = (result.attrs !== undefined && result.attrs !== null)
|
|
1997
2048
|
? { ...result.attrs }
|
|
1998
2049
|
: {};
|
|
1999
|
-
// EXEC stream entry
|
|
2000
|
-
// <runtime>:///<loop_seq>/<turn_seq>/<sequence> (e.g. sh:///1/1/2)
|
|
2001
|
-
//
|
|
2002
|
-
//
|
|
2003
|
-
// <loop>/<turn>/<seq>, so the
|
|
2004
|
-
// from statement.signal (EXEC's runtime slot)
|
|
2050
|
+
// EXEC produces a stream entry addressed by RUNTIME TAG as authority (§exec): it lives
|
|
2051
|
+
// at <runtime>:///<loop_seq>/<turn_seq>/<sequence> (e.g. sh:///1/1/2). That address is a
|
|
2052
|
+
// SEPARATE `stream` link in attrs — NOT an overload of `target`, which stays faithful to
|
|
2053
|
+
// the EXEC's own slot (the cwd, or the path to the executable). The log:/// coordinate
|
|
2054
|
+
// shares the trailing <loop>/<turn>/<seq>, so the op still correlates to its stream.
|
|
2055
|
+
// Runtime comes from statement.signal (EXEC's runtime slot), resolvable for failed execs
|
|
2005
2056
|
// too; empty/absent = the default shell.
|
|
2006
2057
|
if (statement.op === "EXEC") {
|
|
2007
2058
|
const seqs = await this.#db.engine_loop_turn_seqs.get({
|
|
@@ -2011,9 +2062,8 @@ class Engine {
|
|
|
2011
2062
|
throw new Error(`Engine.#writeLog: loop_turn_seqs returned no row for loop=${loopId} turn=${turnId}`);
|
|
2012
2063
|
const runtime = (typeof statement.signal === "string" && statement.signal.length > 0) ? statement.signal : "sh";
|
|
2013
2064
|
const coordPathname = `/${seqs.loop_seq}/${seqs.turn_seq}/${sequence}`;
|
|
2014
|
-
target.scheme = runtime;
|
|
2015
|
-
target.pathname = coordPathname;
|
|
2016
2065
|
attrsObj.pathname = coordPathname;
|
|
2066
|
+
attrsObj.stream = `${runtime}://${coordPathname}`;
|
|
2017
2067
|
// Mutate the in-memory result.attrs too: the dispatch path
|
|
2018
2068
|
// hands originalResult.attrs to handler.applyResolution after
|
|
2019
2069
|
// proposal accept (see #acceptResolution). Both views — the
|