@muretai/agent-entry 1.9.0 → 1.11.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.
@@ -0,0 +1,219 @@
1
+ # Agent Entry — Episode-to-Skill (site side)
2
+
3
+ Status: **local loop shipped** (`scripts/distill/`). Does not change the v1
4
+ HTTP contract (`spec/v1.md`).
5
+ Method: Repo-To-Skill (arXiv 2609.02749) — distill, verify, load only what
6
+ the task needs. Source: outcome-labeled knocks at **this** door, not a
7
+ GitHub crawl and not a network-wide catalog.
8
+
9
+ This repository stays the door. Distillation is an **owner-side, offline**
10
+ loop. Nothing here is added to `muretai-agent-entry.mjs` at request time.
11
+
12
+ ---
13
+
14
+ ## 1. What is missing today
15
+
16
+ A visiting agent reads the card before it knocks. If `skills[]` is empty or
17
+ wrong, it guesses and learns the menu from refusals. The README already
18
+ states the two owner duties:
19
+
20
+ - every `examples[]` entry must be answerable by the responder
21
+ - declare only what the responder actually does
22
+
23
+ Those duties are still hand-written. The paper's claim is that this
24
+ operating knowledge already exists in **grounded outcomes** — signed
25
+ envelopes plus what the door did — and can be distilled into the menu the
26
+ next visitor sees.
27
+
28
+ The door already emits the labels, without changing a verdict:
29
+
30
+ - `observer(env)` runs **after** the reply; its return is discarded
31
+ - `stats()` / `clientStats()` count family and stage, including refusals
32
+ - JSON-RPC refusals teach (`-32004` over-rate, unsigned, replay, wrong
33
+ recipient); the recipe already rides in the refusal
34
+ - the responder's own result (answered / asked for a missing field /
35
+ handed off) is the site-specific outcome
36
+
37
+ User-Agent never affects `verified`, a ledger row, a rate lane, or any
38
+ refusal. Distillation must not reopen that. UA is a counting hint, not a
39
+ training label for "who to trust".
40
+
41
+ ---
42
+
43
+ ## 2. What to steal, what to refuse
44
+
45
+ Steal: four-stage distillation (scope → ground → construct → verify);
46
+ skills as operating context, not a new control loop; environment-grounded
47
+ admission (a transcript-only gate cannot improve uniformly); withhold-the-
48
+ skill measurement.
49
+
50
+ Refuse:
51
+
52
+ - Distiller inside the one-file runtime (zero dependencies, no database)
53
+ - a hosted catalog of every site's skills
54
+ - FOLLOW of visitor-authored text (`env.text` stays untrusted data)
55
+ - stamping a third-party `howToUrl` (empty means omitted; only a URL the
56
+ owner operates)
57
+ - changing any wire byte or verdict because a skill exists
58
+
59
+ ---
60
+
61
+ ## 3. Mapping
62
+
63
+ | Paper | This repo |
64
+ |---|---|
65
+ | Declarative source | Signed inbound `text` + door outcome (verify / refuse code / responder result) |
66
+ | Skill | A2A `skills[]` on the **signed** card; optional owner `howToUrl`; optional `SKILL.md` the owner hosts |
67
+ | Skill graph | One entry skill (what this door answers) → component skills per declared capability |
68
+ | Router | The card itself. Visitors read `skills[]` before POST. Agent Web Router finds the door; it does not write this menu |
69
+ | Verification | Card signature still covers the menu. Examples are driven through the responder in tests (already required) |
70
+ | Creator / researcher | Owner Distiller writes a proposed menu; the running entry only **serves** what the owner published |
71
+
72
+ ```
73
+ visitor --probe--> card.skills[] (menu; signed)
74
+ visitor --knock--> POST door (unchanged contract)
75
+ observer --trace--> local log (after verdict)
76
+ Distiller (offline) --> proposed skills[] / how-to
77
+ owner publishes --> card resigns
78
+ ```
79
+
80
+ ---
81
+
82
+ ## 4. Distiller pipeline (offline, this repo or a sibling package)
83
+
84
+ Anchor is this origin's door, not a task on the open web.
85
+
86
+ 1. **Scope.** One capability the responder already implements (hours,
87
+ quote, book, …). Do not invent a skill the responder cannot keep.
88
+ 2. **Ground.** Read owner-local traces only: `observer` rows the owner
89
+ chose to keep, plus the door's refuse reason. A row is
90
+ `{text, verified, refuse_code?, responder_tag, ts}`. No operator
91
+ aggregation across sites.
92
+ 3. **Construct.** Propose:
93
+ - `skills[]` id / name / description / tags / **answerable** examples
94
+ - optional how-to prose at a URL the owner operates
95
+ - construction record `R`: evidence (trace ids), checks, remaining gaps
96
+ 4. **Verify (M0).** Before publish:
97
+ - the new card still signs
98
+ - every example POSTed to the local entry gets a signed reply the
99
+ visitor could accept (existing "examples are promises" rule)
100
+ - refuse rate on a frozen visitor suite does not rise
101
+ - remaining gaps stay in `R`
102
+
103
+ The running entry never imports the Distiller. Shipped layout (not
104
+ imported by the one-file runtime):
105
+
106
+ ```
107
+ scripts/distill/ # owner CLI
108
+ record.mjs # fileSink() for observer → var/traces.jsonl
109
+ distill.mjs # traces → generated/skills.json
110
+ measure.mjs # M2 with/without the proposed menu
111
+ loop.mjs # distill → measure → mutation
112
+ ```
113
+
114
+ `npm run distill`. Proposed `skills[]` is never written onto the running
115
+ card. `--m0` also runs the door conformance suite.
116
+
117
+ `createAgentEntry({ observer })` already exists. Recording is an owner
118
+ choice. Default remains no disk.
119
+
120
+ ---
121
+
122
+ ## 5. Measurement
123
+
124
+ A skill cannot be graded by reading it (ACES, arXiv 2608.20614).
125
+
126
+ - **M0 admission** — signed card; examples answerable; contract suite
127
+ (`conformance/`) still green. Fail-closed.
128
+ - **M2 lift** — freeze responder, rates, and a held-out visitor prompt
129
+ set. Arm A: current `skills[]` / how-to. Arm B: proposed menu. Score
130
+ only what a visitor observes: first-knock useful answer, refuse-for-
131
+ missing-field, handoff that the card still names. Not token count.
132
+ - **Producer mutation** — Distiller emits empty `skills[]`. Lift must
133
+ fall to ~0. If it stays green, the test was scoring the responder.
134
+ - **No leaderboard.** One site, that site's traces, that site's reader.
135
+
136
+ Publish rule: M0 holds, M2 first-knock success rises or refuse-for-guess
137
+ falls, mutation kills the lift.
138
+
139
+ ---
140
+
141
+ ## 6. First dojo (this repo, no production traffic)
142
+
143
+ Frozen visitor prompts against `examples/server.mjs` (or a fixture
144
+ responder) that requires a missing field the naive visitor omits.
145
+
146
+ - Train traces: naive knocks that the responder rejects with a teachable
147
+ reason, plus one complete knock.
148
+ - Distiller writes a skill example that includes the field.
149
+ - Holdout: a new wording of the same need.
150
+ - Naive visitor still omits the field; skill-equipped visitor includes it.
151
+ - Mutation: empty Distiller, both arms omit, lift 0.
152
+
153
+ Do not use live `muretai.com` traffic for the first number.
154
+
155
+ ---
156
+
157
+ ## 7. What this does not change
158
+
159
+ v1 HTTP surface, Ed25519 envelope, account-from-first-signature, rate
160
+ lanes, Web Bot Auth as recognition-only, `Link` signpost, path mounts,
161
+ `domains`. Agent Web Router remains a **visitor** of this door. It may
162
+ read the distilled menu; it must not write it.
163
+
164
+ ## 8. Relation to `muretai-skill-distill`
165
+
166
+ That sibling app proved withhold-the-skill lift on a fail-closed parse
167
+ dojo. This design is the same method with a different source: **door
168
+ outcomes**, not `x-rlds` lines. Do not vendor-copy core crypto. The entry
169
+ already verifies signatures.
170
+
171
+ ---
172
+
173
+ ## 9. Live loop — two rails (we never see installer traffic)
174
+
175
+ This package is installed by other people, on origins we do not operate.
176
+ Their visitors' messages, accounts, and `observer` rows are **not ours**
177
+ and MUST NOT be fetched, phoned home, or scraped. There is no telemetry
178
+ channel. Evolution therefore splits.
179
+
180
+ ### Rail A — this package (what we can update)
181
+
182
+ We improve the **door machinery and the refusal recipe**, not a site's
183
+ menu. Labels come only from sources we already own or that someone
184
+ chose to publish:
185
+
186
+ - `conformance/` vectors and the contract suite (attacks we author)
187
+ - the doors **we** run (for example the muretai.com entry)
188
+ - a GitHub issue a site owner **opts into**, attaching a redacted
189
+ fixture they exported (`export --redact` if later built; default off,
190
+ never runs itself)
191
+
192
+ A package release may change refusal text, `howTo` defaults (still no
193
+ third-party host), rate-lane behaviour, or new contract tests. It MUST
194
+ NOT patch a stranger's `skills[]`. That list is their signed claim.
195
+
196
+ Measure a release against **our** fixtures (§5). If we do not have a
197
+ new fixture, we do not have a new skill.
198
+
199
+ ### Rail B — each installer's machine (what they can update)
200
+
201
+ The only place their knock data exists is their process. The Distiller,
202
+ if they run it, reads a local `observer` sink they configured. The
203
+ child `skills[]` stays on their card. We never receive it.
204
+
205
+ ```
206
+ their observer → their disk → their Distiller → their next card
207
+ ```
208
+
209
+ `stats()` they already have is for **them**. It is not a feed to us.
210
+ User-Agent remains unusable as a label.
211
+
212
+ ### What we do when we cannot see production
213
+
214
+ We do not wait for it. The first dojo (§6) and every later package
215
+ change are fixture-grown. When a user reports "visitors keep getting
216
+ refused and the recipe did not teach X", the artifact we want is a
217
+ **reproducing envelope**, not their ledger. That becomes a conformance
218
+ case. That is the only upstream ratchet that does not take their
219
+ customers.
package/spec/v1.md CHANGED
@@ -396,6 +396,25 @@ higher rate than the signed lane's aggregate.
396
396
  > **Observation.** With the lane on, drive unsigned requests above the bound; assert refusal. An
397
397
  > unauthenticated caller must never become an unmetered signing oracle.
398
398
 
399
+ **AE-30.** An entry **MAY** publish `agentEntry.prefer`: the site's own order of its ways in
400
+ for a visiting agent. It is an array whose entries are a kind — `"page"`, `"card"`, `"mcp"` —
401
+ or an object `{"kind": <kind>, "when": <condition>}` with `when` one of `person`, `alone`,
402
+ `key`, `no-key`, `token`, `browser`, read by the visitor against what it has on hand. When
403
+ published it **MUST** appear under the neutral `agentEntry` key exactly as the operator
404
+ declared it (validated, not rewritten), and **MUST** appear identically in the signed
405
+ envelope's inner card. The legacy `muretai` alias **MUST NOT** carry it. When not configured,
406
+ the card **MUST NOT** carry a `prefer` key. A declaration that fails validation **MUST** make
407
+ the entry refuse to start rather than publish a corrected or partial order.
408
+
409
+ > **Observation.** Start an entry with a declaration; `GET` the card and the envelope; assert
410
+ > `agentEntry.prefer` equals the declaration in both and `muretai` has no `prefer`. Start one
411
+ > without; assert no `prefer` key. Start one with `["teleport"]`; assert it exits non-zero and
412
+ > binds nothing. Why refuse rather than fix: a signed card is the origin's statement, and a
413
+ > statement the operator did not make is a worse card than none — the same posture as a bad
414
+ > `domains` list. Why the visitor's conditions live here: which way in a stranger should try
415
+ > first is the site's design (read on the page, become a counterparty later — or knock first),
416
+ > and the card is the one place the site can say so that a page script cannot rewrite.
417
+
399
418
  ---
400
419
 
401
420
  ## 5. Relationship to other specifications
@@ -629,6 +648,7 @@ be written is a requirement that does not belong in §4.
629
648
  | AE-27 | MUST | size caps | oversized body and text |
630
649
  | AE-28 | MUST | aggregate reply ceiling, refused with `-32004` | drive above the ceiling |
631
650
  | AE-29 | MUST | unsigned lane bounded entry-wide | drive the anonymous lane |
651
+ | AE-30 | MAY / MUST | `agentEntry.prefer` verbatim on card + envelope, or absent; invalid refuses to start | `GET` both, compare; start with a bad list → exit ≠ 0 |
632
652
 
633
653
  ---
634
654