From df4a058384e3c1f74b1ff19066b64c9dce10219c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 7 Sep 2026 13:53:05 +0000 Subject: [PATCH 1/2] docs: lock anti-truncation teach into app notes and LLM-GUIDE Prefer filter-out or high enough max_rows over hard truncate that drops FND/checklist/fundamentals. Engine M caps stay hard rejects. No package bump; honesty teach only. Co-authored-by: chouswei --- docs/LLM-GUIDE.md | 5 +++-- docs/application-notes/README.md | 1 + docs/application-notes/system/llm-system-dev-multitask.md | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/LLM-GUIDE.md b/docs/LLM-GUIDE.md index 5837873..346a7f3 100644 --- a/docs/LLM-GUIDE.md +++ b/docs/LLM-GUIDE.md @@ -74,7 +74,7 @@ Formal wire: [`grammar/gql-wire-profile.md`](grammar/gql-wire-profile.md). ### Goldfish loop (every turn) -Interact only with **relevant slices** of the session — never dump the graph. Default **one** `pin_map(q)` (or skip). **Drop** prior map rows from the prompt before the next generate — stuffing MCP JSON into a growing chat list is a fail (`stuffed_maps`). Commit a **sparse** Δ (`add`/`update` of what changed only). Env blobs (pytest logs, screenshots) stay in the outer harness. That writeback is not Path-B absorb. +Interact only with **relevant slices** of the session — never dump the graph. Default **one** `pin_map(q)` (or skip). **Drop** prior map rows from the prompt before the next generate — stuffing MCP JSON into a growing chat list is a fail (`stuffed_maps`). Prefer **filter-out** (drop news / tighten cue) or uncapped / high enough `max_rows` over hard truncate that drops `FND` / checklist / fundamentals. Engine \(M\) caps stay hard rejects — change cue/filter/scope; never claim a complete extract under a truncating window. Commit a **sparse** Δ (`add`/`update` of what changed only). Env blobs (pytest logs, screenshots) stay in the outer harness. That writeback is not Path-B absorb. 1. **Seed relative nodes** — cue \(q\) (kind / labels+props / keyword). `find(kind='TSK', limit=L)` / `memnet query find --kind TSK --limit L` yields \(Q\). Empty \(q\) (no cue) ⇒ **session outline** (0.11: kinds + LIMIT exemplars of \(S\)); then pick one seen cue. Empty \(Q\) on a *kind* cue ⇒ skip (do not invent). leftover 0.9: copy an id then `--anchor` is leftover, not this loop. 2. **ShapeWalk one slice** from \(Q\) (one \(M\), not \(M\times|Q|\)): @@ -151,7 +151,7 @@ Next turn: `pin_map(q)` on a live cue — settled rows absent. Optionally `house ### Reading strategy -- **Normal turn:** one `pin_map(kind='TSK', locators=[…], depth=2, max_rows=50)` (or skip). Optional `view=shell` on a **seeded** topic hub only when blocked, then interior on the task. leftover `--anchor` / `anchor=` is a leftover nickname alias, not law. +- **Normal turn:** one `pin_map(kind='TSK', locators=[…], depth=2, max_rows=50)` (or skip). If that window would clip load-bearing kinds, **tighten the cue** or raise `max_rows` — do not silently truncate. Optional `view=shell` on a **seeded** topic hub only when blocked, then interior on the task. leftover `--anchor` / `anchor=` is a leftover nickname alias, not law. - Pin map includes engine LAW rows (prepended) — that is why \(N\) maps waste tokens. - Excludes rows with `recycle=delete_on_settle` or `delete_on_expire` (unless leftover nickname cue touches endpoints per LAW01). - leftover `read_list(active_only=True)` may enumerate; product is `find` then one `pin_map`. @@ -237,6 +237,7 @@ See `docs/grammar/` for targets. Durable online GQL store adapter = **M2.5** (0. | Chat / graph dump as handoff | Session id + cue / re-`pin_map` (import for path B) | | leftover `id:'NEW'` / copy-id `--anchor` as law | Pattern Commit; cue `pin_map` (those are leftover 0.9) | | Stuffing every `pin_map` into `messages` | Drop prior map rows; env blobs stay in the harness (`stuffed_maps`) | +| Hard-truncate `pin_map` / Shape (drop FND / checklist / fundamentals) | Filter-out or raise `max_rows`; never claim a complete extract under a truncating window. Do not soften engine \(M\) | ### Minimal complete turn (MCP) diff --git a/docs/application-notes/README.md b/docs/application-notes/README.md index e7d09f8..a826b02 100644 --- a/docs/application-notes/README.md +++ b/docs/application-notes/README.md @@ -21,6 +21,7 @@ MemNet is **mission working memory** — named session \(S\), bounded Recall Sha | Shaped `pin_map` emit: labels + observable properties only (`SHAPE_DROP_KEYS` drops `hid` / `_memnet_hid` / `elementId`; nickname `id` stays off the wire) | Copy hid / `_memnet_hid` / `elementId` / nickname `id` from emit as identity; leftover `--anchor` as goldfish | | MCP tool arg **`session`** | Tool arg `session_id` (JSON envelope may still *return* `session_id`) | | In-process MCP for a single agent | In-process MCP under Multitask (use TCP / streamable-http) | +| Filter-out (drop news / tighten cue / narrower scope) or **uncapped / high enough `max_rows`** so load-bearing kinds (`FND`, checklist, fundamentals) stay in \(\tilde{X}\). Engine \(M\) caps stay **hard rejects** — change cue/filter/scope, do not soften \(M\). Never claim a complete extract under a truncating window | Hard-truncate a `pin_map` / Shape so FND / checklist / fundamentals silently drop; claim completeness under a truncating window; clip load-bearing kinds to fit \(M\) | Kinds not in the open map fail `unknown_tag`. Bundled maps: `parts/common/memnet/memnet/examples/schema.*.example.txt`. diff --git a/docs/application-notes/system/llm-system-dev-multitask.md b/docs/application-notes/system/llm-system-dev-multitask.md index 6c61790..6c3b20c 100644 --- a/docs/application-notes/system/llm-system-dev-multitask.md +++ b/docs/application-notes/system/llm-system-dev-multitask.md @@ -77,7 +77,7 @@ Probe with `serve_status` before delegating if transport is uncertain. - Mint and own **`TSK_*`** / **`USR_*`**: `status=active` → `status=settled`; optional `led_to_success` edges. - Assign **write scope** (anchor ids + allowed relation types) in self-contained worker prompts. - **End the turn** after background spawn — no poll, no await (MN-REQ-12.6). -- Next coordinator turn: **`pin_map` first**; act from refreshed slice — do not redo worker investigation from chat. +- Next coordinator turn: **`pin_map` first**; act from a refreshed slice that still holds load-bearing kinds — filter-out or raise `max_rows` rather than hard-truncate; never claim a complete extract under a truncating window. Do not redo worker investigation from chat. - Prefer **one worker** per coherent workstream; parallel only with **disjoint** anchors or **separate** sessions (MN-REQ-12.5). ### MUST NOT @@ -92,7 +92,7 @@ Probe with `serve_status` before delegating if transport is uncertain. ### MUST - Use the parent's **session id**; **`pin_map` first** every turn. -- Copy assigned ids from pin map — **MUST NOT** invent ids the parent already minted. +- Copy assigned ids from a **filter-out / high enough** pin-map slice — **MUST NOT** invent ids the parent already minted, and **MUST NOT** treat a truncating window as a complete extract (FND / checklist / fundamentals must not silently drop). - Mutate only under the **assigned subgraph** (anchors + relations in the prompt). - Return a concise result; durable facts live in MemNet rows. @@ -101,6 +101,7 @@ Probe with `serve_status` before delegating if transport is uncertain. - Open a different session unless explicitly assigned. - Settle parent-owned `TSK_*` / `USR_*` unless delegated. - Use in-process MCP when the parent uses shared TCP/HTTP. +- Hard-truncate a worker `pin_map` / Shape to fit \(M\); claim completeness under that window; soften engine caps. Tighten cue/filter/scope instead. --- @@ -185,6 +186,7 @@ Edges: `owns`, `about`, `constrained_by`, `led_to_success` (parent settle), doma | Assuming full ACL modes / `session_token` | False isolation | CapsPolicy when enabled; RSV + Path-B ingest **are** shipped; full modes still to-be | | SysML vs MemNet drift | Model and pins disagree | SysML in git wins for structure; MemNet holds locators + mission state | | Worker settles parent `TSK_*` | Lifecycle violation | Parent-only settle unless delegated | +| Truncating `pin_map` as the copied slice | FND / checklist / fundamentals missing; false-complete extract | Filter-out (drop news / tighten cue) or raise `max_rows`; engine \(M\) stays a hard reject | --- From f76b4eec15eb11e9baaa9d9859d99887d1f46786 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 7 Sep 2026 13:55:21 +0000 Subject: [PATCH 2/2] docs: require a visible truncation signal on clipped pin_map When ShapeWalk hits a hard cap and clips, the emit MUST mark it (CueConflict honesty family). Agents treat that Shape as incomplete. Wire-flag honesty c may follow in a sibling PR. Engine M stays hard. Co-authored-by: chouswei --- docs/LLM-GUIDE.md | 9 ++++++--- docs/application-notes/README.md | 3 ++- .../application-notes/system/llm-system-dev-multitask.md | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/LLM-GUIDE.md b/docs/LLM-GUIDE.md index 346a7f3..45d7dca 100644 --- a/docs/LLM-GUIDE.md +++ b/docs/LLM-GUIDE.md @@ -74,7 +74,7 @@ Formal wire: [`grammar/gql-wire-profile.md`](grammar/gql-wire-profile.md). ### Goldfish loop (every turn) -Interact only with **relevant slices** of the session — never dump the graph. Default **one** `pin_map(q)` (or skip). **Drop** prior map rows from the prompt before the next generate — stuffing MCP JSON into a growing chat list is a fail (`stuffed_maps`). Prefer **filter-out** (drop news / tighten cue) or uncapped / high enough `max_rows` over hard truncate that drops `FND` / checklist / fundamentals. Engine \(M\) caps stay hard rejects — change cue/filter/scope; never claim a complete extract under a truncating window. Commit a **sparse** Δ (`add`/`update` of what changed only). Env blobs (pytest logs, screenshots) stay in the outer harness. That writeback is not Path-B absorb. +Interact only with **relevant slices** of the session — never dump the graph. Default **one** `pin_map(q)` (or skip). **Drop** prior map rows from the prompt before the next generate — stuffing MCP JSON into a growing chat list is a fail (`stuffed_maps`). Prefer **filter-out** (drop news / tighten cue) or uncapped / high enough `max_rows` over hard truncate that drops `FND` / checklist / fundamentals. Engine \(M\) caps stay hard rejects — change cue/filter/scope. When ShapeWalk **does** hit a hard cap (`max_rows` / hop / budget) and the offer is clipped, the emit **MUST** carry an explicit truncation signal — same honesty family as **CueConflict** (visible on the wire, not silent). Treat that as an **incomplete Shape**; never claim a complete extract. Wire-flag honesty `c` MAY land in a sibling PR; the MUST holds even if the emit token follows. Commit a **sparse** Δ (`add`/`update` of what changed only). Env blobs (pytest logs, screenshots) stay in the outer harness. That writeback is not Path-B absorb. 1. **Seed relative nodes** — cue \(q\) (kind / labels+props / keyword). `find(kind='TSK', limit=L)` / `memnet query find --kind TSK --limit L` yields \(Q\). Empty \(q\) (no cue) ⇒ **session outline** (0.11: kinds + LIMIT exemplars of \(S\)); then pick one seen cue. Empty \(Q\) on a *kind* cue ⇒ skip (do not invent). leftover 0.9: copy an id then `--anchor` is leftover, not this loop. 2. **ShapeWalk one slice** from \(Q\) (one \(M\), not \(M\times|Q|\)): @@ -84,6 +84,8 @@ Interact only with **relevant slices** of the session — never dump the graph. leftover engine may still take `--anchor` as a **nickname** cue — not TARGET law. + If the walk hits \(M\) / hop / budget and clips: the emit MUST show the truncation mark (CueConflict family). That slice is incomplete — tighten cue or raise `max_rows`; do not reason as if \(\tilde{X}\) were whole \(S\). + Blocked on a topic hub: at most one extra `pin_map(..., view=shell)` **on that seed**, then interior on the live `TSK`. `view=shell` is grain on a seed — **not** session outline (0.11). Do **not** issue \(N\) full maps (duplicate LAW / overlap). Do not fuse ranks. 3. **Act / reason** using only the **live** pin-map slice + the current user request. Do not keep turn-\(n-1\) maps in the pack. 4. **Commit sparse Δ** — CREATE / SET on changed elements only. Do not echo the fetched map. leftover `id_exists` / NEW mint is leftover. @@ -151,7 +153,7 @@ Next turn: `pin_map(q)` on a live cue — settled rows absent. Optionally `house ### Reading strategy -- **Normal turn:** one `pin_map(kind='TSK', locators=[…], depth=2, max_rows=50)` (or skip). If that window would clip load-bearing kinds, **tighten the cue** or raise `max_rows` — do not silently truncate. Optional `view=shell` on a **seeded** topic hub only when blocked, then interior on the task. leftover `--anchor` / `anchor=` is a leftover nickname alias, not law. +- **Normal turn:** one `pin_map(kind='TSK', locators=[…], depth=2, max_rows=50)` (or skip). If that window would clip load-bearing kinds, **tighten the cue** or raise `max_rows` — prefer filter-out over truncate. If the engine still clips, the emit MUST carry a **truncation signal** (CueConflict honesty family, on the wire — not stderr-only). Treat as incomplete Shape. Optional `view=shell` on a **seeded** topic hub only when blocked, then interior on the task. leftover `--anchor` / `anchor=` is a leftover nickname alias, not law. - Pin map includes engine LAW rows (prepended) — that is why \(N\) maps waste tokens. - Excludes rows with `recycle=delete_on_settle` or `delete_on_expire` (unless leftover nickname cue touches endpoints per LAW01). - leftover `read_list(active_only=True)` may enumerate; product is `find` then one `pin_map`. @@ -237,7 +239,8 @@ See `docs/grammar/` for targets. Durable online GQL store adapter = **M2.5** (0. | Chat / graph dump as handoff | Session id + cue / re-`pin_map` (import for path B) | | leftover `id:'NEW'` / copy-id `--anchor` as law | Pattern Commit; cue `pin_map` (those are leftover 0.9) | | Stuffing every `pin_map` into `messages` | Drop prior map rows; env blobs stay in the harness (`stuffed_maps`) | -| Hard-truncate `pin_map` / Shape (drop FND / checklist / fundamentals) | Filter-out or raise `max_rows`; never claim a complete extract under a truncating window. Do not soften engine \(M\) | +| Hard-truncate `pin_map` / Shape (drop FND / checklist / fundamentals) | Filter-out or raise `max_rows`; never claim a complete extract. Do not soften engine \(M\) | +| Silent clip (no truncation mark on emit) | Same honesty family as CueConflict: clipped Shape MUST be marked on the wire. Incomplete until cue/filter/scope changes. Flag token MAY follow in a sibling honesty `c` PR | ### Minimal complete turn (MCP) diff --git a/docs/application-notes/README.md b/docs/application-notes/README.md index a826b02..9832e6a 100644 --- a/docs/application-notes/README.md +++ b/docs/application-notes/README.md @@ -21,7 +21,8 @@ MemNet is **mission working memory** — named session \(S\), bounded Recall Sha | Shaped `pin_map` emit: labels + observable properties only (`SHAPE_DROP_KEYS` drops `hid` / `_memnet_hid` / `elementId`; nickname `id` stays off the wire) | Copy hid / `_memnet_hid` / `elementId` / nickname `id` from emit as identity; leftover `--anchor` as goldfish | | MCP tool arg **`session`** | Tool arg `session_id` (JSON envelope may still *return* `session_id`) | | In-process MCP for a single agent | In-process MCP under Multitask (use TCP / streamable-http) | -| Filter-out (drop news / tighten cue / narrower scope) or **uncapped / high enough `max_rows`** so load-bearing kinds (`FND`, checklist, fundamentals) stay in \(\tilde{X}\). Engine \(M\) caps stay **hard rejects** — change cue/filter/scope, do not soften \(M\). Never claim a complete extract under a truncating window | Hard-truncate a `pin_map` / Shape so FND / checklist / fundamentals silently drop; claim completeness under a truncating window; clip load-bearing kinds to fit \(M\) | +| Prefer **filter-out** (drop news / tighten cue / narrower scope) or **uncapped / high enough `max_rows`** so load-bearing kinds (`FND`, checklist, fundamentals) stay in \(\tilde{X}\). Engine \(M\) caps stay **hard rejects** — change cue/filter/scope, do not soften \(M\) | Hard-truncate a `pin_map` / Shape so FND / checklist / fundamentals drop; clip load-bearing kinds to fit \(M\); soften engine \(M\) | +| When `pin_map` / ShapeWalk hits a hard cap (`max_rows` / hop / budget) and the offer is **clipped**, the emit **MUST** carry an explicit **truncation signal** — same honesty family as **CueConflict** (visible on the wire, not silent). Treat that Shape as **incomplete**. Never claim a complete extract. Wire-flag honesty `c` MAY land in a sibling PR; this MUST holds even if the emit token follows | Silent clip; ignore a truncation mark; treat stderr `@WRN:` as the only signal; claim completeness under a truncating window | Kinds not in the open map fail `unknown_tag`. Bundled maps: `parts/common/memnet/memnet/examples/schema.*.example.txt`. diff --git a/docs/application-notes/system/llm-system-dev-multitask.md b/docs/application-notes/system/llm-system-dev-multitask.md index 6c3b20c..7ceb588 100644 --- a/docs/application-notes/system/llm-system-dev-multitask.md +++ b/docs/application-notes/system/llm-system-dev-multitask.md @@ -77,7 +77,7 @@ Probe with `serve_status` before delegating if transport is uncertain. - Mint and own **`TSK_*`** / **`USR_*`**: `status=active` → `status=settled`; optional `led_to_success` edges. - Assign **write scope** (anchor ids + allowed relation types) in self-contained worker prompts. - **End the turn** after background spawn — no poll, no await (MN-REQ-12.6). -- Next coordinator turn: **`pin_map` first**; act from a refreshed slice that still holds load-bearing kinds — filter-out or raise `max_rows` rather than hard-truncate; never claim a complete extract under a truncating window. Do not redo worker investigation from chat. +- Next coordinator turn: **`pin_map` first**; act from a refreshed slice that still holds load-bearing kinds — filter-out or raise `max_rows` rather than hard-truncate. If the emit carries a **truncation signal** (CueConflict family), treat the Shape as incomplete; never claim a complete extract. Do not redo worker investigation from chat. - Prefer **one worker** per coherent workstream; parallel only with **disjoint** anchors or **separate** sessions (MN-REQ-12.5). ### MUST NOT @@ -92,7 +92,7 @@ Probe with `serve_status` before delegating if transport is uncertain. ### MUST - Use the parent's **session id**; **`pin_map` first** every turn. -- Copy assigned ids from a **filter-out / high enough** pin-map slice — **MUST NOT** invent ids the parent already minted, and **MUST NOT** treat a truncating window as a complete extract (FND / checklist / fundamentals must not silently drop). +- Copy assigned ids from a **filter-out / high enough** pin-map slice — **MUST NOT** invent ids the parent already minted. If `pin_map` is clipped at a hard cap, the emit **MUST** show a truncation mark (same honesty family as CueConflict); treat that as incomplete Shape (FND / checklist / fundamentals must not silently drop). - Mutate only under the **assigned subgraph** (anchors + relations in the prompt). - Return a concise result; durable facts live in MemNet rows. @@ -101,7 +101,7 @@ Probe with `serve_status` before delegating if transport is uncertain. - Open a different session unless explicitly assigned. - Settle parent-owned `TSK_*` / `USR_*` unless delegated. - Use in-process MCP when the parent uses shared TCP/HTTP. -- Hard-truncate a worker `pin_map` / Shape to fit \(M\); claim completeness under that window; soften engine caps. Tighten cue/filter/scope instead. +- Hard-truncate a worker `pin_map` / Shape to fit \(M\); claim completeness under that window; ignore a truncation mark on the emit; soften engine caps. Tighten cue/filter/scope instead. Wire-flag honesty `c` MAY follow in a sibling PR; the MUST to mark a clip still holds. --- @@ -186,7 +186,7 @@ Edges: `owns`, `about`, `constrained_by`, `led_to_success` (parent settle), doma | Assuming full ACL modes / `session_token` | False isolation | CapsPolicy when enabled; RSV + Path-B ingest **are** shipped; full modes still to-be | | SysML vs MemNet drift | Model and pins disagree | SysML in git wins for structure; MemNet holds locators + mission state | | Worker settles parent `TSK_*` | Lifecycle violation | Parent-only settle unless delegated | -| Truncating `pin_map` as the copied slice | FND / checklist / fundamentals missing; false-complete extract | Filter-out (drop news / tighten cue) or raise `max_rows`; engine \(M\) stays a hard reject | +| Truncating `pin_map` as the copied slice | FND / checklist / fundamentals missing; false-complete extract | Filter-out (drop news / tighten cue) or raise `max_rows`; engine \(M\) stays a hard reject. Clipped emit MUST carry a truncation signal (CueConflict family); treat as incomplete Shape | ---