@jsonstudio/appsdk-linux-x64-gnu 0.0.0-stage → 0.1.15

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/README.md CHANGED
@@ -1,3 +1,9 @@
1
- # Temporary Holding Version
1
+ # @jsonstudio/appsdk-linux-x64-gnu
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Linux x64 glibc runtime package metadata for AppSDK.
4
+
5
+ The M5 packaging flow assembles the verified `appsdk` and `project-memory`
6
+ GNU/glibc binaries plus the three managed Skills into the paths declared by
7
+ `files` before this package is packed or installed. The tracked metadata does
8
+ not contain binary, Skill, or placeholder payloads. musl is not supported by
9
+ this package.
package/artifact.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "sourceCommit": "ab6e57501316b92f4e84247924ea13cbc809dd06",
3
+ "sourceVersion": "0.1.0015",
4
+ "targetTriple": "x86_64-unknown-linux-gnu",
5
+ "files": {
6
+ "bin/appsdk": "33194a41cf213f7248b14099b8243c34576230f2a8906ff6d0c2b2f52d2f7e21",
7
+ "bin/project-memory": "7389a553a7463a9f0bedecad5f43a0b973e801b4c1d253d3fc754ac1b7adaf6e",
8
+ "skills/appsdk-migration/SKILL.md": "609935299de8141bd25a38e02f6ae4dc4852ae3b330d52c33debf36044a71c8b",
9
+ "skills/appsdk-project-governance/agents/openai.yaml": "caeea787723f1e9bf6b0cfb9d506f1a59c8cf680de5f125b08f604b75c0ba2d4",
10
+ "skills/appsdk-project-governance/appsdk-guidance.json": "565eb018676581216e97017506401734c10e60244fe3def4d7dc3fe64c9252c3",
11
+ "skills/appsdk-project-governance/references/authoritative-review-template.md": "a1e634e4a5ec8cb1cd1ec6a1ff29d828a59dad9b61816760738e4269a9e23d73",
12
+ "skills/appsdk-project-governance/references/bootstrap-migration.md": "ad14d33e7e1abb42072d8c22c2ab1b4236b2544f658ac566be0bc2277f6f2f68",
13
+ "skills/appsdk-project-governance/references/command-surface.md": "7bd973e57e149f28e137933bcd5033d33e967f8d58836aec39140a4659689e78",
14
+ "skills/appsdk-project-governance/references/contracts-and-failures.md": "6aeba3519dd65cfafa5b9c5c6962c5dfcd2bf604c1762dc28ff0376c79a4b24a",
15
+ "skills/appsdk-project-governance/references/development-debug.md": "360fc78310d3c5b86e40e93b02301ea0f80af59418ac297309e4ca11d402c94b",
16
+ "skills/appsdk-project-governance/references/goal-prompt.md": "04ab122f2d91e31fc7e928701f134d16d600658bd710bd50bc7fa4b2fae2273e",
17
+ "skills/appsdk-project-governance/references/init-prompts.md": "f99489bd4a42613c2b8057544ac2ac9cfa46b1c32cb609ce1bf72c3cd54a73ea",
18
+ "skills/appsdk-project-governance/references/process-control-harness.md": "0be5085bc51909f6cf32f14b0555cb9ce56a71a3b9f512c835e42378e3e51a2a",
19
+ "skills/appsdk-project-governance/references/review-delivery.md": "b9967a608432282fffb1908a696ed0143f09a85ff5a5ed846a52311d78903ae4",
20
+ "skills/appsdk-project-governance/references/state-paths.md": "3cee6eb1142427e81d0d762da31694578ae0b2786e76713bbdd6d2d9cfb7674b",
21
+ "skills/appsdk-project-governance/references/subagents-config.md": "d99648503a9e6433b7f29e7528abda505fddd8e0386186c07dd0f1a209d929a9",
22
+ "skills/appsdk-project-governance/SKILL.md": "fea5be938055d2a41a921cff25dfcf154a7df645f747c4470e38e57ab7dce91c",
23
+ "skills/project-memory/SKILL.md": "aed7e89edd4d233778eafdfe66b7fd0e0be45cd1e13a9edfba8e061bcbce4dbf"
24
+ }
25
+ }
package/bin/appsdk ADDED
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "@jsonstudio/appsdk-linux-x64-gnu",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.15",
4
+ "description": "Linux x64 glibc runtime package for AppSDK; populated from verified release artifacts.",
5
+ "os": [
6
+ "linux"
7
+ ],
8
+ "cpu": [
9
+ "x64"
10
+ ],
11
+ "libc": [
12
+ "glibc"
13
+ ],
14
+ "files": [
15
+ "bin/appsdk",
16
+ "bin/project-memory",
17
+ "skills/appsdk-project-governance/**",
18
+ "skills/appsdk-migration/**",
19
+ "skills/project-memory/**",
20
+ "artifact.json"
21
+ ],
22
+ "appsdk": {
23
+ "targetTriple": "x86_64-unknown-linux-gnu"
24
+ },
25
+ "license": "MIT"
26
+ }
@@ -0,0 +1,429 @@
1
+ ---
2
+ name: appsdk-migration
3
+ description: "AppSDK/Collab 控制面迁移、身份上下文恢复或授权重置; 仅状态、daemon、身份或 reset 实际变化时使用。owner 全程记录证据; worker 只可查候选, 不可删状态/重启/改身份/未授权删除。"
4
+ ---
5
+
6
+ # AppSDK migration
7
+
8
+ Use this Skill only when an existing AppSDK or its Collab runtime control plane
9
+ must move to a reviewed version, when peer identity or route binding must be
10
+ reconciled after a reviewed migration, or when the operator has explicitly
11
+ authorized discarding a named legacy control plane. SDK-only rule, Skill,
12
+ template, binary, or installer upgrades and ordinary `appsdk init` do not invoke
13
+ this state machine unless control-plane state, daemon, identity, or reset is
14
+ actually changing.
15
+
16
+ The migration owner runs the whole operation and records its evidence. A
17
+ worker may inspect or prepare a candidate, but may not independently delete
18
+ state, restart the daemon, change identity, or resume admissions.
19
+
20
+ This Skill owns the migration state machine:
21
+
22
+ ```text
23
+ prepare -> inspect -> classify -> snapshot -> freeze
24
+ -> install/restart -> identity-context -> verify -> resume
25
+ ```
26
+
27
+ The installed `collab` Skill owns transport, daemon, route, and identity
28
+ semantics. The AppSDK project-governance Skill owns AppSDK quality gates and
29
+ the canonical `appsdk reset-governance <project> --discard-legacy` operation.
30
+ Read those Skills before acting; do not copy their state machines into this
31
+ one. For the project-level preserve/reset choices, also read
32
+ [`bootstrap-migration.md`](../appsdk-project-governance/references/bootstrap-migration.md).
33
+
34
+ The two clean-epoch owners are independent. Use `collab migrate` when the
35
+ Collab journal is replayable; use `collab reset --project --discard-legacy
36
+ --approval "<user text>"` only when the operator authorizes abandoning the
37
+ project Collab epoch. Use `appsdk init <project> --fresh --discard-legacy` or
38
+ the lower-level `appsdk reset-governance <project> --discard-legacy` only for
39
+ the AppSDK-owned project control plane. A reset record proves reset only; it
40
+ never proves delivery, review, install, restart, or live communication.
41
+
42
+ ## Invariants
43
+
44
+ - There is one global Collab daemon for the host. Resolve its PID and socket
45
+ before changing anything. Never start a second daemon, use a project-local
46
+ replacement, or repair a timeout by switching binaries or sockets.
47
+ - A project scope is the exact project root/cwd resolved by the authoritative
48
+ runtime. A process, screenshot, mailbox, or shared directory by itself does
49
+ not prove a registered identity or route.
50
+ - A durable peer registration and its live runtime route are the identity
51
+ authority. A transcript/session ID is observation metadata and may change
52
+ after compression, fork, thread replacement, or restart. Run `collab context`
53
+ once for the new live runtime; the daemon reconciles the durable peer
54
+ identity. Never copy tokens or make a session ID the durable identity.
55
+ - User authorization is required before promoting a peer to `master`. A peer
56
+ can register and communicate only through a server-selected App Server route
57
+ that passed its capability self-check. A Desktop runtime must not register a
58
+ goal subscription; only the authorized master/TUI scheduler may do so.
59
+ - The communication path and durable facts are different surfaces. An App
60
+ Server notification is a bounded wake hint; the journal/mailbox is the
61
+ durable record. Do not delete, rewrite, replay, or use a notification as
62
+ proof of consumption.
63
+ - Business source, runtime data, human documents, `active/`, and `protected/`
64
+ remain retained by default. Their age or filename is not evidence that they
65
+ are disposable.
66
+ - Only the exact legacy control objects named in the approved migration plan
67
+ may be removed, and only through the canonical reset/migration command. Do
68
+ not hand-edit or manually remove journals, mailbox files, identity tokens,
69
+ task records, bindings, claims, or worker state.
70
+ - A timeout, missing receipt, `unknown`, partial response, identity mismatch,
71
+ or count mismatch is a failed gate for progression. Preserve the exact
72
+ error, stop dependent writes, and do not claim success, retry in a tight
73
+ loop, or fall back to an older writer.
74
+
75
+ ## Prepare
76
+
77
+ Before inspecting mutable state, write a migration record with a unique
78
+ `run_id` and bind:
79
+
80
+ - the exact project root/cwd and appserver/runtime scope;
81
+ - the migration owner, authorized operator text, and requested action
82
+ (`preserve`, `canonical-migrate`, or `discard-legacy`);
83
+ - the source version/binary and the reviewed candidate version, commit, tree,
84
+ artifact, and expected SHA-256;
85
+ - the exact worktree and branch used for any code or Skill change;
86
+ - the acceptance gates, non-goals, and the path where append-only evidence is
87
+ stored.
88
+
89
+ For the AppSDK source repository itself, first determine whether the root is a
90
+ managed AppSDK project. The presence of SDK source or `.appsdk-control/` alone
91
+ does not implicitly register it as a governed application; governing the SDK
92
+ workspace requires explicit opt-in. When the user makes that choice, follow the
93
+ canonical initialization contract in the installed `appsdk-project-governance`
94
+ Skill; this Skill does not maintain a separate initialization location. If the
95
+ user has not made that choice, do not run `appsdk init` or reset commands merely
96
+ to manufacture a contract; perform only the declared SDK/runtime migration and
97
+ record that scope. A fresh reset still requires an existing contract plus
98
+ explicit `--fresh --discard-legacy` authorization.
99
+
100
+ All code, Skill, or contract changes are made in a clean non-`main` worktree
101
+ created from the latest `origin/main`. Merge and verify the candidate on the
102
+ intended mainline before installing it when installation changes shared
103
+ production or a daemon runtime. An explicitly authorized SDK-only client
104
+ candidate may be installed for pre-commit acceptance when the exact candidate is
105
+ recorded and no mainline, release, or daemon-migration status is claimed. Do not
106
+ develop in a dirty root or in the worktree that owns the live daemon.
107
+
108
+ ## Inspect
109
+
110
+ Inspection is read-only. Capture the current state before choosing a reset or
111
+ migration route. Use the official commands available in the installed
112
+ versions, with the usual Collab sequence:
113
+
114
+ ```sh
115
+ collab migrate inspect
116
+ collab context
117
+ ```
118
+
119
+ Also inspect the AppSDK project contract and current lifecycle state through
120
+ its read-only commands. Resolve, at minimum:
121
+
122
+ - one daemon PID, socket, binary path, version, and SHA-256;
123
+ - project root/cwd, current branch/HEAD, all worktrees, and any unmerged
124
+ worker branch;
125
+ - registered peers, roles, parent/owner relations, live App Server routes,
126
+ tasks, leases, claims, and active goal subscriptions;
127
+ - journal, mailbox, notification, task, worker, and identity counts plus their
128
+ last durable IDs;
129
+ - `.appsdk/`, `.appsdk-control/`, generated roots, `active/`, `protected/`,
130
+ runtime data, business source, and reports outside declared generated roots;
131
+ - current errors, in-flight transactions, freezes, and owner conflicts.
132
+
133
+ The inspection result must say whether the old daemon, project-local socket,
134
+ goal record, or control directory is authoritative, stale, or unknown. Do not
135
+ infer this from a PID file, mtime, or filename. If a local daemon appears to
136
+ exist, prove its PID/socket ownership and its relation to the global daemon
137
+ before taking any lifecycle action.
138
+
139
+ If inspection returns `PROJECT_SCOPE_UNKNOWN`, an identity error, a command
140
+ timeout, or an unavailable status, record that exact result and stop before
141
+ classification that could delete state. A live daemon is not enough to pass
142
+ inspection.
143
+
144
+ ## Classify
145
+
146
+ Create a path-level classification in the migration plan. Every item is one
147
+ of `retain`, `migrate`, `discard-through-canonical-command`, or `unknown`.
148
+
149
+ | Class | Default treatment | Examples |
150
+ | --- | --- | --- |
151
+ | `retain` | Keep in place and include its evidence reference | business source, runtime data, human documents, `active/`, `protected/`, valid external build/release output |
152
+ | `migrate` | Let the supported migration preserve/transform it once | supported daemon state, registered identity metadata, current task/lease records |
153
+ | `discard-through-canonical-command` | Remove only after authorization and freeze | old `.appsdk/` records/transactions/maps, stale audit or migration reports, `.appsdk-control/`, declared rebuildable generated projections |
154
+ | `unknown` | Retain and escalate; do not mutate | ambiguous PID/socket, external report, failed staging tied to an active task, unrecognized state file |
155
+
156
+ For the idempotent reset route that discards the named legacy control plane,
157
+ the exact command is:
158
+
159
+ ```sh
160
+ appsdk reset-governance <project> --discard-legacy
161
+ ```
162
+
163
+ Run it once, only in the clean non-`main` owner worktree after the named
164
+ objects and authorization are recorded. The command is idempotent and owns
165
+ removal of its declared legacy control set. Do not replace it with `rm`, a
166
+ glob, a directory rename, manual JSON edits, or a second reset attempt.
167
+
168
+ When the user explicitly chooses to abandon the old governance epoch and start
169
+ the existing project from the current SDK baseline, use the fresh-init entry:
170
+
171
+ ```sh
172
+ appsdk init <project> --fresh --discard-legacy
173
+ ```
174
+
175
+ This is the only init path that discards a legacy control plane. It requires an
176
+ existing `.appsdk/project.json`, a clean non-`main`/`master` worktree, and the
177
+ explicit `--discard-legacy` confirmation. The current SDK scaffold is the only
178
+ reset baseline: legacy SDK pins, migration witnesses, SDK-owned record and
179
+ transition contracts, indexes, and rebuildable projections are ignored and
180
+ regenerated; missing SDK-owned fields are refilled. Only project-owned identity,
181
+ module ownership, build declarations, and protection boundaries are carried
182
+ forward. It removes the remaining AppSDK-owned control state,
183
+ `.appsdk-control/`, and declared generated roots, then validates only the new
184
+ staging baseline. It records `mode: "fresh_init"`. Ordinary `appsdk init`
185
+ remains non-destructive; the lower-level reset command uses the same
186
+ transactional owner. A rejected fresh-init must leave the old state untouched.
187
+
188
+ The Collab-owned project control plane uses a separate reset owner:
189
+
190
+ ```sh
191
+ collab down
192
+ collab reset --project --discard-legacy --approval "<explicit user authorization>"
193
+ collab up
194
+ collab context
195
+ ```
196
+
197
+ It archives the exact `.agent-collab/` and `.agent-collab-v2/` bytes, removes
198
+ only Collab-owned control state and stale routes, and rebuilds the current
199
+ empty baseline with `delivery_verified: false`. It never removes `.appsdk/` or
200
+ `.appsdk-control/`; never manually delete either owner's state or start a
201
+ second daemon.
202
+
203
+ The canonical transition contract is `contracts/transitions/zone-transition.manifest.json`.
204
+ The historical `contracts/transitions/zone-transition-manifest.json` path remains
205
+ supported as a project declaration and must always be refreshed from that same
206
+ canonical content; it is not a separate governance history.
207
+
208
+ The reset does not authorize removal of `active/`, `protected/`, runtime data,
209
+ business source, `dist/`, `.deploy/`, `build/`, `tmp/`, or custom reports.
210
+ Obsolete Active/Protected or external artifacts need their own exact-path
211
+ authorization and cleanup record. Do not copy old PASS, hashes, receipts, or
212
+ review results into the new baseline. The reset record proves the reset only.
213
+
214
+ For the AppSDK host runtime registry (`~/.appsdk/runtimes.jsonl`), the explicit
215
+ AppServer-only baseline replacement is:
216
+
217
+ ```sh
218
+ appsdk communication reset-runtime-registry --discard-legacy --approval "<user text>"
219
+ ```
220
+
221
+ It requires explicit `--discard-legacy` and a non-empty approval, archives the
222
+ legacy registry bytes without parsing them, writes an empty current baseline,
223
+ and records `delivery_verified: false`. It touches only the runtime registry;
224
+ `projects.jsonl` and `communication.jsonl` are preserved. Run it before the
225
+ current AppServer-only `register_runtime` path when a host still has a
226
+ pre-AppServer registry.
227
+
228
+ If old state belongs to a still-valid task, use that task's canonical abort or
229
+ retry operation before reset. If its owner cannot be established, classify it
230
+ as `unknown` and stop; deletion would hide an ownership or delivery failure.
231
+
232
+ ## Snapshot
233
+
234
+ Take the immutable snapshot before the freeze or any removal. Store it in the
235
+ approved append-only run note or audit location outside the discard set. A
236
+ snapshot is provenance, not a replacement control plane and not a new PASS
237
+ receipt.
238
+
239
+ The snapshot records:
240
+
241
+ - `run_id`, UTC timestamp, operator/owner, project root/cwd, branch/HEAD, and
242
+ worktree path;
243
+ - daemon PID/socket/binary/version/SHA-256 and the exact reviewed candidate;
244
+ - every classified path with its class, reason, owner, and retention or
245
+ removal authorization;
246
+ - peer/role/parent/route identities, task and lease IDs, goal state, and
247
+ journal/mailbox/notification/worker counts;
248
+ - the last durable IDs and a hash or size/count manifest for retained
249
+ evidence;
250
+ - active errors, in-flight operations, and the command output that established
251
+ each fact.
252
+
253
+ Do not put credentials, identity tokens, or secret payloads in the snapshot.
254
+ Do not use a copied snapshot to satisfy a later live check; after restart,
255
+ query the authoritative store again.
256
+
257
+ ## Freeze
258
+
259
+ Freeze admissions and mutable migration inputs only after the snapshot passes
260
+ its completeness check. Use the official migration transaction, which holds
261
+ one transaction lease:
262
+
263
+ ```sh
264
+ collab migrate plan
265
+ collab migrate apply
266
+ ```
267
+
268
+ The plan must name the exact source, destination, retained classes, discard
269
+ classes, owner, and release condition. Stop new dispatches, goal registration,
270
+ and state-changing writes while the freeze is held. Do not freeze by deleting
271
+ files or killing processes. A worker notification or a direct message does
272
+ not authorize maintenance.
273
+
274
+ If a freeze lease is already held, ownership is ambiguous, or an operation is
275
+ in flight, preserve the existing state and stop. Do not steal the lease,
276
+ force-close another owner, or start a second migration transaction.
277
+
278
+ Timeouts are observation boundaries, not a reason to use a ten-second retry
279
+ loop. On a busy system, query the supported migration status once with a
280
+ bounded wait, preserve `in_progress` or `unknown` when no receipt exists, and
281
+ escalate to the migration owner. Resume only from the same canonical
282
+ transaction if the command explicitly supports it.
283
+
284
+ ## Install and restart
285
+
286
+ Install only the reviewed candidate that is already merged and verified on the
287
+ intended mainline. Verify its version and SHA-256 before changing the live
288
+ daemon. Installation alone does not replace a running process.
289
+
290
+ Use the official service lifecycle:
291
+
292
+ ```sh
293
+ collab down
294
+ collab up
295
+ ```
296
+
297
+ If `collab migrate apply` owns the restart, do not run a second manual restart;
298
+ follow the command's receipt. Otherwise keep the daemon explicitly down while
299
+ the reviewed candidate is installed, then bring up exactly one daemon. Never
300
+ use `pkill`, `killall`, broad process matching, a second socket, or an older
301
+ binary as an implicit fallback.
302
+
303
+ After the restart, prove one PID and socket, the expected binary hash, and no
304
+ old writer. A restart error or ambiguous process ownership is `unknown`; do
305
+ not run identity reconciliation or send recovery messages until the owner
306
+ resolves it.
307
+
308
+ ## Identity context reconciliation
309
+
310
+ After the daemon and socket pass the restart gate, run `collab context` once
311
+ for each named live peer whose runtime must be reconciled. The current peer
312
+ must have a live App Server runtime whose capability self-check and server
313
+ selection passed. The daemon owns identity creation, selection, restoration,
314
+ update, registration, route publication, and lease restoration. If context
315
+ returns `required_fields`, supply only those real facts once:
316
+
317
+ ```sh
318
+ collab context --provide '<JSON>'
319
+ ```
320
+
321
+ The supplement may contain only requested `session_id`, `thread_id`,
322
+ `endpoint`, or `namespace` facts; it never supplies a worker, approval, token,
323
+ route, or binding.
324
+
325
+ The evidence must bind the durable peer ID to the live runtime, selected
326
+ App Server target, exact project cwd, role, parent, and capabilities. A screen
327
+ preview, process name, or session ID alone is insufficient.
328
+
329
+ When an App Server binding is replaced, or a transcript is forked/compressed,
330
+ run `collab context` once from the new live runtime. The daemon reconciles the
331
+ durable peer identity from proven anchors. Do not reuse a stale endpoint,
332
+ register a new master, copy identity tokens, or replay the old mailbox batch. A
333
+ user-approved master assignment is the only basis for the `master` role;
334
+ otherwise the peer remains a peer.
335
+
336
+ If any identity, scope, parent, or capability differs from the snapshot, stop
337
+ before messaging. Record `identity_mismatch` and require an explicit migration
338
+ owner or user decision before continuing.
339
+
340
+ ## Verify
341
+
342
+ Verification is ordered and each gate needs its own evidence. Passing one gate
343
+ does not imply the next.
344
+
345
+ 1. **Runtime:** one global daemon/PID/socket, expected binary/version/hash,
346
+ no duplicate or old writer, and a successful official status query.
347
+ 2. **Durability:** journal, mailbox, tasks, workers, leases, and last durable
348
+ IDs are continuous with the snapshot, apart from explicitly recorded
349
+ migration events. Any unexplained count or ID loss fails the gate.
350
+ 3. **Identity:** each reconciled peer has a confirmed durable identity, exact
351
+ cwd/project scope, role, and live bidirectional App Server route.
352
+ 4. **Communication:** send one unique migration marker to an authorized
353
+ registered peer and require separate evidence for durable journal
354
+ acceptance, notification delivery, peer consumption, and a reply. `sent`,
355
+ transport acceptance, or `recv` alone is not an end-to-end success receipt.
356
+ 5. **Governance:** after a reset, initialize and compile only the fresh current
357
+ contract, then run `appsdk verify` through the project governance Skill.
358
+ Verify that no discarded legacy goal/control record is active and that no
359
+ old PASS or receipt was imported.
360
+ 6. **Scope:** only the approved paths were removed; business, runtime,
361
+ `active/`, `protected/`, and retained evidence remain present and owned.
362
+
363
+ If the real marker cannot be consumed or the reply is missing, record the
364
+ first failed layer and stop. Do not call a mailbox append, App Server queue
365
+ acceptance, or status response a communication proof.
366
+
367
+ ## Resume
368
+
369
+ Resume only after every applicable verification gate has a current receipt:
370
+
371
+ - release the migration freeze through its canonical command;
372
+ - re-read authoritative daemon, identity, task, and goal state;
373
+ - restore the one authorized master and only its valid routes;
374
+ - let the master dispatch new work from the fresh/current plan;
375
+ - register a long-horizon goal only from the authorized master/TUI when the
376
+ user requested ongoing wakeups. Desktop must not run `goal subscribe`;
377
+ - send one aggregated recovery/completion notice that points to the durable
378
+ run record. Do not replay every old notification.
379
+
380
+ If any gate is missing, leave the system frozen or in its explicitly reported
381
+ partial state, retain the snapshot and exact error, and hand the next action
382
+ to the migration owner. “Daemon is up” is not permission to resume work.
383
+
384
+ ## Failure and unknown-error contract
385
+
386
+ Use this contract at every phase:
387
+
388
+ | First divergence | Required action | Forbidden action |
389
+ | --- | --- | --- |
390
+ | inspect/status timeout or unavailable scope | preserve exact output; stop before classification/removal | infer identity, retry in a tight loop, or claim healthy |
391
+ | incomplete snapshot or count/hash mismatch | keep current state; repair snapshot inputs or escalate | freeze with incomplete truth or overwrite the snapshot |
392
+ | lease/owner conflict | preserve both owners and task IDs; ask the migration owner to resolve | steal, force-close, or invent an owner |
393
+ | candidate/version/hash mismatch | stop before install; report expected and observed values | install “close enough” or use the old binary silently |
394
+ | restart timeout or ambiguous PID/socket | leave lifecycle state explicit; inspect once through the official command | send, run another identity command, start a second daemon, or kill by process name |
395
+ | identity/scope mismatch | stop all messaging and goal operations; use `collab context` once or escalate to the migration owner | copy tokens, guess a session binding, or promote a peer |
396
+ | partial reset/migration result | preserve transaction ID and files; use the canonical recovery path | manually finish deletion or run a second reset |
397
+ | communication marker missing reply | classify the failing layer and keep the route unverified | treat durable send or notification as peer consumption |
398
+
399
+ An unknown error is not a transient success. A later attempt is allowed only
400
+ when the canonical command reports the previous transaction state and the
401
+ migration owner explicitly continues that same transaction. Never hide an
402
+ unknown by falling back, changing the project scope, or creating a new daemon.
403
+
404
+ ## Evidence record
405
+
406
+ Write one append-only JSONL event for each phase transition and each failed
407
+ gate. Use this shape; omit secrets and large payloads:
408
+
409
+ ```json
410
+ {"schema":"appsdk-migration/v1","run_id":"20260910T000000Z-example","at":"2026-09-10T00:00:00Z","phase":"inspect","operation":"collab migrate inspect","result":"pass","actor":{"peer_id":"peer-id","role":"master","runtime_id":"runtime-id","transport":{"kind":"appserver","target":"thread-id"},"cwd":"/absolute/project"},"source":{"head":"commit","tree":"tree","binary":"/absolute/bin","version":"0.1.6","sha256":"hex"},"evidence":{"paths":["/absolute/run-note.jsonl"],"counts":{"tasks":0,"workers":0,"mailbox":0},"receipts":["receipt-id"],"errors":[]},"retained":["active/","protected/"],"discarded":[],"next":"classify"}
411
+ ```
412
+
413
+ Required semantics:
414
+
415
+ - `result` is exactly `pass`, `fail`, `unknown`, or `skipped`; an absent
416
+ result is incomplete evidence.
417
+ - `source` identifies the observed candidate; `actor` identifies the real
418
+ runtime that performed the operation. Do not substitute a transcript ID for
419
+ either.
420
+ - `evidence` contains paths, counts, receipts, and exact error codes/text
421
+ references. It must not contain credentials or copied control tokens.
422
+ - `retained` and `discarded` list only classified paths; `discarded` requires
423
+ the authorization and canonical-operation receipt elsewhere in the record.
424
+ - A new baseline may reference the inventory for history, but it must not
425
+ rebuild control state from this JSONL or inherit old PASS claims.
426
+
427
+ The migration is complete only when the final `resume` event is `pass`, all
428
+ applicable verification receipts are present, the exact removed/retained paths
429
+ are reported, and no unresolved `unknown` or owner conflict remains.