docs: Campaign LA — pinned launch-contract schema COMMITTED into plan LA1
The LA3 Opus review process note was right: the contract both sides implement lived only in orchestrator prompts, which is exactly the drift mode the pin exists to prevent (and it produced the paths-key CRITICAL). The schema, field rules, probe-mode discriminator, and status vocabulary are now a binding plan section; amendments change this text first, implementations second. Ledger: LA3 fix round dispatched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0bcc7ba3a3
commit
db9ad53c1c
38 changed files with 2397 additions and 40 deletions
|
|
@ -108,6 +108,69 @@ referencing only `AcDream.Platform`.
|
|||
|
||||
## LA1 — launch contract (client side)
|
||||
|
||||
### Pinned launch-contract schema (v1, BINDING — committed per LA3 review)
|
||||
|
||||
This text is the single source of truth for the launcher↔host file
|
||||
contract. Both host readers (LA1), the composer (LA3), and the probe
|
||||
loader (LA2) implement EXACTLY this; any change is an amendment to THIS
|
||||
section first, implementations second. The LA1+LA3 merge adds a
|
||||
cross-assembly test feeding a composer-produced document to both host
|
||||
loaders — that test is the seam's permanent enforcement.
|
||||
|
||||
Session-config document (System.Text.Json, camelCase,
|
||||
`UnmappedMemberHandling.Disallow`, camelCase string enums):
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"process": {
|
||||
"content": { "datDirectory": "...", "preparedAssetPath": "..." }
|
||||
},
|
||||
"sessions": [{
|
||||
"id": "sess-1",
|
||||
"endpoint": { "host": "127.0.0.1", "port": 9000 },
|
||||
"account": "testaccount",
|
||||
"mode": "probe",
|
||||
"character": { "id": 1342177290 },
|
||||
"policy": { "id": "idle" },
|
||||
"credential": { "provider": "standardInput", "reference": "session" },
|
||||
"plugins": ["ExamplePlugin"],
|
||||
"loginCommands": ["/vt start"],
|
||||
"loginCommandDelayMs": 500,
|
||||
"statusFile": ".../launcher/sessions/sess-1/status.jsonl"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
Field rules:
|
||||
- `process.paths` is OMITTED unless a caller genuinely supplies overrides
|
||||
(never an empty object — the App reader has no `paths` member and
|
||||
strict parsing rejects unknown keys; LA3 review finding 1).
|
||||
- `mode`: ABSENT for normal play sessions; `"probe"` for the LA2 probe
|
||||
(connect → characterList → graceful disconnect, no EnterWorld). The
|
||||
headless loader accepts the field starting at LA2.
|
||||
- `character`: exactly ONE of index|id|name; OMITTED entirely (not null)
|
||||
for guiSelect and for probe sessions.
|
||||
- `policy`: `{ "id": "idle" }` for headless play sessions ONLY; omitted
|
||||
for gui/guiSelect/probe.
|
||||
- `credential`: always `{ "provider": "standardInput", "reference":
|
||||
"session" }` for launcher-composed configs.
|
||||
- `plugins`/`loginCommands`/`loginCommandDelayMs`/`statusFile`: optional,
|
||||
omitted-when-unset (never null, never `[]` for empty). Absent
|
||||
`loginCommandDelayMs` means 500.
|
||||
|
||||
Status stream (`statusFile`, one JSON object per line, writer flushes per
|
||||
line, writer opens `FileShare.Read`, tailer opens
|
||||
`Read/FileShare.ReadWrite|Delete`): events `started`, `connected`,
|
||||
`characterList{accountName,slotCount,characters[{id,name,secondsGreyedOut}]}`,
|
||||
`enteredWorld{characterId,characterName}`, `pluginLoaded{plugin}`,
|
||||
`pluginFailed{plugin,error}`, `disconnected{reason}`,
|
||||
`exited{code,reason}` — every line carries `"v":1`, `"e"`, `"t"`
|
||||
(ISO-8601 UTC), `"sessionId"`. `secondsGreyedOut` is a uint on BOTH
|
||||
sides. Unknown `e` values must parse to a typed Unknown event, never
|
||||
throw; a known `e` with a wrong payload shape should be distinguishable
|
||||
from an unknown `e` (LA3 review finding 12).
|
||||
|
||||
Three pieces, one slice, because they share the session-config/status seam:
|
||||
|
||||
1. **App `--session-config <path>`:** parsed once in `Program.cs` into
|
||||
|
|
@ -416,7 +479,7 @@ LA6 adds CH-regression scrutiny; LA0 adds guard-integrity scrutiny.
|
|||
| LA0 | **DONE 2026-08-14** | `cb6502c8`, `a49e92df` | Opus dual-lens PASS; all 6 findings CLOSED in narrow re-review | Byte-identity proven; Linux CI lanes restored; Platform BCL-only self-guard added; K0 guard untouched |
|
||||
| LA1 | in flight (Sonnet) | | | pinned contract v1 + 5 optional fields |
|
||||
| LA2 | — | | | |
|
||||
| LA3 | implemented (`37d74e44`, campaign-la3); Opus review in flight | `37d74e44` | review in flight | 71/71 Windows AND 71/71 WSL (0600 test real on Linux); reviewer checking contract token-fidelity + tailer fix |
|
||||
| LA3 | review FIX FIRST; fix round in flight | `37d74e44` + fixes pending | Opus 2026-08-14: 12 findings — 1 CRITICAL (`"paths": {}` breaks App loader), probe composition owed, Stop→SIGKILL hazard, 0600 temp window | Contract text now COMMITTED into LA1 section (review process note); cross-assembly loader test owed at LA1+LA3 merge; CI lane addition at merge |
|
||||
| LA4 | — | | | |
|
||||
| LA5 | — | | | |
|
||||
| LA6 | — | | | |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue