@etiquekit/etq 1.0.12 → 1.0.14

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.
Files changed (149) hide show
  1. package/AGENTS.md +19 -26
  2. package/LICENSE +2 -3
  3. package/NOTICE +6 -4
  4. package/QuickStart.md +35 -47
  5. package/README.md +54 -54
  6. package/bin/etiquette +1 -5
  7. package/bin/etiquette-core +1 -5
  8. package/docs/ARCHITECTURE.md +5 -5
  9. package/docs/CODEX_CLIENT_COMPATIBILITY.md +1 -1
  10. package/docs/CONCEPTS.md +7 -23
  11. package/docs/CONCEPT_STATUS.md +66 -0
  12. package/docs/CORE_PROFILE.md +3 -5
  13. package/docs/LANE_PROVISIONING.md +7 -2
  14. package/docs/README.md +4 -4
  15. package/docs/RELEASE_SURFACE_AUDIT.md +8 -7
  16. package/docs/SEAT_DISCIPLINE.md +55 -91
  17. package/docs/SEAT_PROVISIONING.md +19 -22
  18. package/docs/TEAM_HANDOFF.md +21 -21
  19. package/docs/WORKTREE_QOL.md +7 -6
  20. package/docs/contracts/ledger-entry/README.md +11 -11
  21. package/docs/contracts/ledger-entry/ledger-entry.v0.2.md +3 -3
  22. package/docs/contracts/ledger-entry/ledger-entry.v0.md +8 -8
  23. package/package.json +9 -9
  24. package/packages/control/src/authority/lease.ts +261 -0
  25. package/packages/control/src/authority/node-delegation.ts +257 -0
  26. package/packages/control/src/authority/rig-conductor.ts +632 -0
  27. package/packages/control/src/cli/argv.ts +155 -0
  28. package/packages/control/src/cli/commands/console.ts +200 -0
  29. package/packages/control/src/cli/commands/dispatch-core.ts +89 -0
  30. package/packages/control/src/cli/commands/dispatch.ts +279 -0
  31. package/packages/control/src/cli/commands/harness.ts +89 -0
  32. package/packages/control/src/cli/commands/hook.ts +50 -0
  33. package/packages/control/src/cli/commands/ledger.ts +91 -0
  34. package/packages/control/src/cli/commands/local-workflow.ts +4690 -0
  35. package/packages/control/src/cli/commands/memory.ts +445 -0
  36. package/packages/control/src/cli/commands/release.ts +108 -0
  37. package/packages/control/src/cli/commands/rubric.ts +103 -0
  38. package/packages/control/src/cli/commands/seat.ts +179 -0
  39. package/packages/control/src/cli/commands/session.ts +127 -0
  40. package/packages/control/src/cli/commands/supervision.ts +246 -0
  41. package/packages/control/src/cli/commands/sync.ts +119 -0
  42. package/packages/control/src/cli/commands/workflow.ts +86 -0
  43. package/packages/control/src/cli/commands/workspace.ts +50 -0
  44. package/packages/control/src/cli/core-usage.ts +34 -0
  45. package/packages/control/src/cli/prompt.ts +67 -0
  46. package/packages/control/src/cli/supervision-deps.ts +44 -0
  47. package/packages/control/src/cli/usage.ts +241 -0
  48. package/packages/control/src/cli.ts +207 -0
  49. package/packages/control/src/core-cli.ts +50 -0
  50. package/packages/control/src/dispatch/decision.ts +202 -0
  51. package/packages/control/src/dispatch/projection.ts +293 -0
  52. package/packages/control/src/dispatch/record.ts +153 -0
  53. package/packages/control/src/engagement/project.ts +170 -0
  54. package/packages/control/src/fs.ts +19 -0
  55. package/packages/control/src/harness/pruning.ts +406 -0
  56. package/packages/control/src/hooks/dispatcher.ts +117 -0
  57. package/packages/control/src/hooks/outbox.ts +86 -0
  58. package/packages/control/src/hooks/sanitize.ts +6 -0
  59. package/packages/control/src/hooks/types.ts +34 -0
  60. package/packages/control/src/index.ts +384 -0
  61. package/packages/control/src/ledger/entry.ts +303 -0
  62. package/packages/control/src/ledger/indexer.ts +542 -0
  63. package/packages/control/src/memory/context.ts +149 -0
  64. package/packages/control/src/memory/drain-import.ts +207 -0
  65. package/packages/control/src/memory/indexer.ts +284 -0
  66. package/packages/control/src/memory/query.ts +75 -0
  67. package/packages/control/src/memory/sanitize.ts +50 -0
  68. package/packages/control/src/memory/sharded-drain-import.ts +212 -0
  69. package/packages/control/src/memory/status.ts +211 -0
  70. package/packages/control/src/memory/store-lifecycle.ts +509 -0
  71. package/packages/control/src/memory/store.ts +284 -0
  72. package/packages/control/src/memory/types.ts +146 -0
  73. package/packages/control/src/parity/surfaces.ts +748 -0
  74. package/packages/control/src/project.ts +141 -0
  75. package/packages/control/src/projection/local-ledger-view.ts +373 -0
  76. package/packages/control/src/projection/return-enforcement.ts +48 -0
  77. package/packages/control/src/projection/timeline-preview.ts +539 -0
  78. package/packages/control/src/projection/timeline.ts +708 -0
  79. package/packages/control/src/release/readiness.ts +842 -0
  80. package/packages/control/src/rubric/loader.ts +326 -0
  81. package/packages/control/src/rubric/promotion.ts +54 -0
  82. package/packages/control/src/rubric/runner.ts +159 -0
  83. package/packages/control/src/rubric/types.ts +158 -0
  84. package/packages/control/src/seat/owner-card.ts +388 -0
  85. package/packages/control/src/seat/readiness.ts +834 -0
  86. package/packages/control/src/session/runbook.ts +431 -0
  87. package/packages/control/src/shared/sanitize.ts +49 -0
  88. package/packages/control/src/supervision/action-classes.ts +192 -0
  89. package/packages/control/src/supervision/command-apply.ts +378 -0
  90. package/packages/control/src/supervision/errors.ts +14 -0
  91. package/packages/control/src/supervision/event-replay.ts +155 -0
  92. package/packages/control/src/supervision/events.ts +109 -0
  93. package/packages/control/src/supervision/index.ts +16 -0
  94. package/packages/control/src/supervision/manifest.ts +127 -0
  95. package/packages/control/src/supervision/paths.ts +49 -0
  96. package/packages/control/src/supervision/projection-adapter.ts +274 -0
  97. package/packages/control/src/supervision/projection.ts +75 -0
  98. package/packages/control/src/supervision/rebuild.ts +99 -0
  99. package/packages/control/src/supervision/session-open.ts +131 -0
  100. package/packages/control/src/supervision/session-read.ts +99 -0
  101. package/packages/control/src/supervision/sqlite-impl.ts +71 -0
  102. package/packages/control/src/supervision/sqlite.ts +121 -0
  103. package/packages/control/src/supervision/store-rows.ts +371 -0
  104. package/packages/control/src/supervision/turn-close.ts +154 -0
  105. package/packages/control/src/supervision/turn-open.ts +284 -0
  106. package/packages/control/src/sync/event-log-merge-driver.ts +263 -0
  107. package/packages/control/src/sync/join-plan.ts +375 -0
  108. package/packages/control/src/sync/outbox.ts +492 -0
  109. package/packages/control/src/workflow/evaluator.ts +140 -0
  110. package/packages/control/src/workflow/loader.ts +200 -0
  111. package/packages/control/src/workflow/types.ts +90 -0
  112. package/packages/control/src/workspace/authority.ts +499 -0
  113. package/packages/protocol/src/guards.ts +119 -0
  114. package/packages/protocol/src/huddle-board.ts +198 -0
  115. package/packages/protocol/src/huddle.ts +295 -0
  116. package/packages/protocol/src/incident.ts +251 -0
  117. package/packages/protocol/src/index.ts +8 -0
  118. package/packages/protocol/src/interfaces.ts +107 -0
  119. package/packages/protocol/src/packet-profile.ts +195 -0
  120. package/packages/protocol/src/state.ts +81 -0
  121. package/packages/protocol/src/types.ts +434 -0
  122. package/release/lineage.v0.json +15 -0
  123. package/scripts/release-candidate-verify.sh +175 -0
  124. package/scripts/release-checksum.sh +25 -0
  125. package/scripts/release-pack-canary.sh +97 -0
  126. package/scripts/release-scan.sh +249 -0
  127. package/scripts/release-sign.sh +34 -0
  128. package/templates/etiquette-vanilla-v0/README.md +2 -3
  129. package/templates/etiquette-vanilla-v0/source/control-seat/README.md +0 -6
  130. package/templates/etiquette-vanilla-v0/source/control-seat/bin/seat-doctor +0 -5
  131. package/templates/etiquette-vanilla-v0/validate-vanilla.sh +0 -5
  132. package/templates/seat-packs-v0/README.md +3 -2
  133. package/templates/seat-packs-v0/source/claude-code-seat/README.md +3 -29
  134. package/templates/seat-packs-v0/source/codex-seat/README.md +3 -17
  135. package/templates/seat-packs-v0/source/gemini-seat/README.md +3 -23
  136. package/templates/seat-packs-v0/source/ollama-seat/README.md +3 -3
  137. package/templates/seat-packs-v0/source/openrouter-seat/README.md +3 -3
  138. package/docs/AGENT_SPAWNING.md +0 -78
  139. package/docs/INTEGRATION_UI.md +0 -215
  140. package/docs/OPERATOR_PLAYBOOK.md +0 -77
  141. package/docs/TAG_ROUTE.md +0 -95
  142. package/lib/etiquette-core.js +0 -315
  143. package/lib/etiquette.js +0 -1160
  144. package/templates/DISPATCH_PREMISES.md +0 -39
  145. package/templates/etiquette-vanilla-v0/source/control-seat/bin/access-assurance-check +0 -55
  146. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/ACCESS-ASSURANCE.md +0 -39
  147. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/workspace-secure-profile.v0.json +0 -53
  148. package/templates/hosted-receiver/README.md +0 -41
  149. package/templates/hosted-receiver/w1-github-webhook-receiver.mjs +0 -129
@@ -0,0 +1,434 @@
1
+ export const SLICE_STATES = [
2
+ 'draft',
3
+ 'planned',
4
+ 'split',
5
+ 'assigned',
6
+ 'in_progress',
7
+ 'integration',
8
+ 'validated',
9
+ 'closed',
10
+ ] as const;
11
+
12
+ export const TASK_STATES = [
13
+ 'incoming',
14
+ 'claimed',
15
+ 'in_progress',
16
+ 'evidence_ready',
17
+ 'accepted',
18
+ 'countered',
19
+ 'blocked',
20
+ 'resolved',
21
+ ] as const;
22
+
23
+ export const PACKET_STATES = ['PROPOSED', 'ACCEPTED', 'LOCKED', 'PROVISIONED'] as const;
24
+ export const SCRUTINY_STATES = ['OPEN', 'IN_PROGRESS', 'BLOCKED', 'DEFERRED', 'RESOLVED', 'VERIFIED', 'WONT_FIX'] as const;
25
+ export const SCRUTINY_KINDS = ['issue', 'feature', 'feature_set', 'readiness_gate', 'dependency', 'risk', 'research', 'decision', 'migration', 'cleanup'] as const;
26
+ export const CORE_SURFACES = ['backend', 'bff', 'android', 'ios', 'integration'] as const;
27
+ export const ACTOR_KINDS = ['owner', 'worker', 'secretary', 'integrator', 'reviewer'] as const;
28
+
29
+ export type SliceState = (typeof SLICE_STATES)[number];
30
+ export type TaskState = (typeof TASK_STATES)[number];
31
+ export type PacketState = (typeof PACKET_STATES)[number];
32
+ export type ScrutinyState = (typeof SCRUTINY_STATES)[number];
33
+ export type ScrutinyKind = (typeof SCRUTINY_KINDS)[number];
34
+ export type CoreSurface = (typeof CORE_SURFACES)[number];
35
+ export type Surface = string;
36
+ export type ActorKind = (typeof ACTOR_KINDS)[number];
37
+
38
+ export interface Actor {
39
+ actorId: string;
40
+ kind: ActorKind;
41
+ displayName: string;
42
+ }
43
+
44
+ export interface Dependency {
45
+ taskId: string;
46
+ kind: 'blocked-by' | 'depends-on';
47
+ }
48
+
49
+ export interface StateTransition {
50
+ state: string;
51
+ actorId: string;
52
+ at: string;
53
+ note?: string;
54
+ }
55
+
56
+ export interface EvidenceItem {
57
+ kind: 'report' | 'receipt' | 'sample' | 'artifact' | 'note';
58
+ path: string;
59
+ summary: string;
60
+ }
61
+
62
+ export interface EvidenceBundle {
63
+ bundleId: string;
64
+ taskId: string;
65
+ status: 'pending' | 'ready' | 'accepted';
66
+ items: EvidenceItem[];
67
+ }
68
+
69
+ export interface Verdict {
70
+ verdictId: string;
71
+ sliceId: string;
72
+ taskId?: string;
73
+ outcome: 'accepted' | 'countered' | 'blocked' | 'completed';
74
+ by: string;
75
+ at: string;
76
+ note?: string;
77
+ }
78
+
79
+ export interface WorkBounds {
80
+ repoRoots: string[];
81
+ ownedPaths: string[];
82
+ forbiddenPaths: string[];
83
+ checks: string[];
84
+ evidenceFiles: string[];
85
+ }
86
+
87
+ export interface SliceTask {
88
+ taskId: string;
89
+ surface: Surface;
90
+ title: string;
91
+ summary: string;
92
+ scrutinyId: string;
93
+ state: TaskState;
94
+ packetId?: string;
95
+ worktreePath?: string;
96
+ branchName?: string;
97
+ owner?: string;
98
+ workerRole?: string;
99
+ bounds: WorkBounds;
100
+ dependencies: Dependency[];
101
+ transitions: StateTransition[];
102
+ }
103
+
104
+ export interface Slice {
105
+ schemaVersion: 'discipline-slice.v1';
106
+ sliceId: string;
107
+ projectId: string;
108
+ title: string;
109
+ objective: string;
110
+ scrutinyId: string;
111
+ state: SliceState;
112
+ repoRoots: string[];
113
+ handshakeStorePath: string;
114
+ tasks: SliceTask[];
115
+ transitions: StateTransition[];
116
+ createdAt: string;
117
+ updatedAt: string;
118
+ }
119
+
120
+ export interface SurfaceDefaults {
121
+ owner: string;
122
+ workerRole: string;
123
+ repoRoots: string[];
124
+ ownedPaths: string[];
125
+ forbiddenPaths: string[];
126
+ checks: string[];
127
+ evidenceFiles: string[];
128
+ worktreeTemplate: string;
129
+ }
130
+
131
+ export interface SliceTaskBlueprint {
132
+ title: string;
133
+ summary: string;
134
+ repoRoots?: string[];
135
+ ownedPaths?: string[];
136
+ forbiddenPaths?: string[];
137
+ checks?: string[];
138
+ evidenceFiles?: string[];
139
+ worktreePath?: string;
140
+ workerRole?: string;
141
+ owner?: string;
142
+ dependencies?: Dependency[];
143
+ }
144
+
145
+ export interface SliceBlueprint {
146
+ title: string;
147
+ objective: string;
148
+ scrutinyId: string;
149
+ repoRoots?: string[];
150
+ tasks: Record<string, SliceTaskBlueprint>;
151
+ }
152
+
153
+ export type WorkerScripts = Record<string, string>;
154
+
155
+ export interface ProjectManifest {
156
+ schemaVersion: 'discipline-project.v1';
157
+ projectId: string;
158
+ title: string;
159
+ projectRoot: string;
160
+ handshakeStorePath: string;
161
+ logixRepoRoot?: string;
162
+ scrutinyWorkflowPath: string;
163
+ defaultWorktreeRoot: string;
164
+ workerScripts: WorkerScripts;
165
+ surfaces: Record<string, SurfaceDefaults>;
166
+ slices: Record<string, SliceBlueprint>;
167
+ }
168
+
169
+ export interface TaskPacketSpec {
170
+ packetId: string;
171
+ sliceId: string;
172
+ task: SliceTask;
173
+ project: ProjectManifest;
174
+ }
175
+
176
+ export interface TaskLedgerRecord {
177
+ task_id: string;
178
+ status: 'incoming' | 'pending' | 'resolved';
179
+ source: string;
180
+ packet_id: string;
181
+ action: string;
182
+ actor: string;
183
+ created_at: string;
184
+ ingested_at: string;
185
+ claimed_by: string | null;
186
+ claimed_at: string | null;
187
+ resolved_by: string | null;
188
+ resolved_at: string | null;
189
+ resolution_note: string | null;
190
+ summary: string;
191
+ chat_text: string;
192
+ }
193
+
194
+ export interface SliceStatusSnapshot {
195
+ sliceId: string;
196
+ sliceState: SliceState;
197
+ scrutinyState: ScrutinyState;
198
+ packetStates: Record<PacketState, number>;
199
+ taskStates: Record<TaskState, number>;
200
+ unresolvedTasks: string[];
201
+ readyToClose: boolean;
202
+ blockers: string[];
203
+ }
204
+
205
+ export interface SecretaryAction {
206
+ level: 'info' | 'action' | 'blocked';
207
+ taskId?: string;
208
+ surface?: string;
209
+ summary: string;
210
+ }
211
+
212
+ export interface SecretarySummary {
213
+ sliceId: string;
214
+ actions: SecretaryAction[];
215
+ }
216
+
217
+ // ============================================================================
218
+ // Supervision (Phase 1)
219
+ // Authority: etiquette/internal/docs/supervision/PHASE1.md
220
+ // Doctrine: llm-substrate/governance/shared-live-supervision.md
221
+ // ============================================================================
222
+
223
+ export const SESSION_STATUSES = [
224
+ 'running',
225
+ 'paused',
226
+ 'blocked',
227
+ 'awaiting_human',
228
+ 'closed',
229
+ ] as const;
230
+ export type SessionStatus = (typeof SESSION_STATUSES)[number];
231
+
232
+ export const TURN_STATUSES = ['open', 'closed'] as const;
233
+ export type TurnStatus = (typeof TURN_STATUSES)[number];
234
+
235
+ export const TURN_RESULTS = [
236
+ 'done',
237
+ 'blocked',
238
+ 'handed_off',
239
+ 'stopped',
240
+ 'timed_out',
241
+ ] as const;
242
+ export type TurnResult = (typeof TURN_RESULTS)[number];
243
+
244
+ export const SUPERVISION_COMMANDS = [
245
+ 'status',
246
+ 'pause',
247
+ 'resume',
248
+ 'stop',
249
+ 'approve_next_turn',
250
+ 'redirect_owner',
251
+ 'request_summary',
252
+ 'mark_blocked',
253
+ 'escalate_to_human',
254
+ ] as const;
255
+ export type SupervisionCommand = (typeof SUPERVISION_COMMANDS)[number];
256
+
257
+ export const COMMAND_STATUSES = [
258
+ 'queued',
259
+ 'applied',
260
+ 'rejected',
261
+ 'expired',
262
+ ] as const;
263
+ export type CommandStatus = (typeof COMMAND_STATUSES)[number];
264
+
265
+ export const ACTION_CLASSES = [
266
+ 'coordination_only',
267
+ 'read_only_local',
268
+ 'bounded_verification',
269
+ 'bounded_product_mutation',
270
+ 'human_only',
271
+ ] as const;
272
+ export type ActionClass = (typeof ACTION_CLASSES)[number];
273
+
274
+ export const ALLOWED_COMMAND_IDS = [
275
+ 'inspect_repo',
276
+ 'run_verify',
277
+ 'write_projection',
278
+ 'append_evidence',
279
+ 'write_product_files',
280
+ 'launch_runtime_target',
281
+ ] as const;
282
+ export type AllowedCommandId = (typeof ALLOWED_COMMAND_IDS)[number];
283
+
284
+ export const PROJECTION_POLICIES = [
285
+ 'on_state_change',
286
+ 'on_command_only',
287
+ ] as const;
288
+ export type ProjectionPolicy = (typeof PROJECTION_POLICIES)[number];
289
+
290
+ export const SUPERVISION_EVENT_TYPES = [
291
+ 'session.opened',
292
+ 'session.status_changed',
293
+ 'session.next_owner_changed',
294
+ 'turn.opened',
295
+ 'turn.closed',
296
+ 'command.queued',
297
+ 'command.applied',
298
+ 'command.rejected',
299
+ 'projection.rendered',
300
+ 'rebuild.completed',
301
+ ] as const;
302
+ export type SupervisionEventType = (typeof SUPERVISION_EVENT_TYPES)[number];
303
+
304
+ export const RUNTIME_KINDS = [
305
+ 'codex',
306
+ 'claude-code',
307
+ 'human-mobile',
308
+ 'human-desktop',
309
+ 'other',
310
+ ] as const;
311
+ export type RuntimeKind = (typeof RUNTIME_KINDS)[number];
312
+
313
+ export type SupervisionAudience =
314
+ | 'all'
315
+ | 'lead'
316
+ | 'responder'
317
+ | 'escalation_owner'
318
+ | `seat:${string}`;
319
+
320
+ export interface SupervisionSession {
321
+ sessionId: string;
322
+ campaignRoot: string;
323
+ topic: string;
324
+ objective: string;
325
+ status: SessionStatus;
326
+ leadSeat: string;
327
+ responderSeat: string;
328
+ escalationOwner: string;
329
+ timeCapMinutes: number;
330
+ turnCap: number;
331
+ currentTurnId: string | null;
332
+ nextOwnerHint: string | null;
333
+ approvedNextTurnJson: string | null;
334
+ lastBlockerJson: string | null;
335
+ sourceRefs: string[];
336
+ createdAt: string;
337
+ updatedAt: string;
338
+ }
339
+
340
+ export interface SupervisionTurn {
341
+ turnId: string;
342
+ sessionId: string;
343
+ sequenceNo: number;
344
+ status: TurnStatus;
345
+ ownerSeat: string;
346
+ allowedActionClass: ActionClass;
347
+ maxDurationMinutes: number;
348
+ allowedCommands: AllowedCommandId[];
349
+ repoRoots: string[];
350
+ ownedPaths: string[];
351
+ forbiddenPaths: string[];
352
+ verifyCommands: string[];
353
+ requiresHumanApproval: boolean;
354
+ projectionPolicy: ProjectionPolicy;
355
+ startedAt: string;
356
+ endedAt: string | null;
357
+ result: TurnResult | null;
358
+ summary: string | null;
359
+ evidenceRefs: string[];
360
+ }
361
+
362
+ export interface SupervisionCommandRecord {
363
+ commandId: string;
364
+ sessionId: string;
365
+ turnId: string | null;
366
+ issuedBy: string;
367
+ command: SupervisionCommand;
368
+ payloadJson: string;
369
+ status: CommandStatus;
370
+ issuedAt: string;
371
+ appliedAt: string | null;
372
+ rejectionReason: string | null;
373
+ }
374
+
375
+ export interface SupervisionEvent {
376
+ eventId: string;
377
+ sessionId: string;
378
+ turnId: string | null;
379
+ commandId: string | null;
380
+ eventType: SupervisionEventType;
381
+ actor: string;
382
+ audience: SupervisionAudience;
383
+ at: string;
384
+ payload: unknown;
385
+ }
386
+
387
+ export interface SeatCapabilityManifest {
388
+ schemaVersion: 'discipline-supervision-seat-capabilities.v1';
389
+ seatId: string;
390
+ displayName: string;
391
+ runtimeKind: RuntimeKind;
392
+ canReadHandshake: boolean;
393
+ canWriteHandshake: boolean;
394
+ canReadProductRepo: boolean;
395
+ canRunBuilds: boolean;
396
+ canWriteProductRepo: boolean;
397
+ canLaunchRuntimeTargets: boolean;
398
+ canAcceptMobileSteering: boolean;
399
+ allowedActionClasses: ActionClass[];
400
+ defaultRequiresHumanApprovalForProductMutation: boolean;
401
+ updatedAt: string;
402
+ }
403
+
404
+ export interface SupervisionProjection {
405
+ sessionId: string;
406
+ renderedAt: string;
407
+ sessionSnapshot: SupervisionSession;
408
+ currentTurn: SupervisionTurn | null;
409
+ pendingCommands: SupervisionCommandRecord[];
410
+ }
411
+
412
+ export interface ApprovedNextTurnPayload {
413
+ ownerSeat: string;
414
+ allowedActionClass: ActionClass;
415
+ maxDurationMinutes: number;
416
+ allowedCommands: AllowedCommandId[];
417
+ repoRoots: string[];
418
+ ownedPaths: string[];
419
+ forbiddenPaths: string[];
420
+ verifyCommands: string[];
421
+ requiresHumanApproval: boolean;
422
+ projectionPolicy: ProjectionPolicy;
423
+ issuedBy: string;
424
+ issuedAt: string;
425
+ expiresAt: string | null;
426
+ }
427
+
428
+ export interface BlockerPayload {
429
+ reason: string;
430
+ raisedBy: string;
431
+ raisedAt: string;
432
+ escalationOwner: string;
433
+ evidenceRefs: string[];
434
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "schema": "etq-release-lineage.v0",
3
+ "package_name": "@etiquekit/etq",
4
+ "candidate_version": "1.0.14",
5
+ "distribution_mode": "bun-typescript-source",
6
+ "source_repository": "git+https://github.com/leepickdev/etq-devkit.git",
7
+ "distribution_repository": "git+https://github.com/leepickdev/etq.git",
8
+ "source_base_commit": "b2384dc782548ce0d712da3bd33e108d977adb44",
9
+ "registry_floor": "1.0.13",
10
+ "required_bins": [
11
+ "etq",
12
+ "etiquette",
13
+ "etiquette-core"
14
+ ]
15
+ }
@@ -0,0 +1,175 @@
1
+ #!/bin/sh
2
+ # Prove the reviewed package tarball from an isolated install. Never publishes.
3
+ set -eu
4
+
5
+ ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
6
+ TMPDIR_ROOT=${TMPDIR:-/tmp}
7
+ TMP=$(mktemp -d "$TMPDIR_ROOT/etq-release-candidate.XXXXXX")
8
+ trap 'rm -rf "$TMP"' EXIT INT TERM
9
+
10
+ LINEAGE="$ROOT/release/lineage.v0.json"
11
+ PACKAGE_NAME=$(node -e 'const m=require(process.argv[1]); process.stdout.write(m.package_name)' "$LINEAGE")
12
+ VERSION=$(node -e 'const m=require(process.argv[1]); process.stdout.write(m.candidate_version)' "$LINEAGE")
13
+
14
+ cd "$ROOT"
15
+
16
+ if [ -n "$(git status --porcelain)" ]; then
17
+ echo "release-candidate: worktree must be clean" >&2
18
+ exit 1
19
+ fi
20
+
21
+ bun packages/control/src/cli.ts release readiness --project . --fail-on-blocked >/dev/null
22
+
23
+ REGISTRY_VERSION=$(npm view "$PACKAGE_NAME" version --json | node -e 'let d=""; process.stdin.on("data",c=>d+=c).on("end",()=>process.stdout.write(JSON.parse(d)))')
24
+ node -e '
25
+ const parse = value => {
26
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value);
27
+ if (!match) throw new Error(`invalid GA version: ${value}`);
28
+ return match.slice(1).map(Number);
29
+ };
30
+ const candidate = parse(process.argv[1]);
31
+ const current = parse(process.argv[2]);
32
+ for (let i = 0; i < 3; i += 1) {
33
+ if (candidate[i] > current[i]) process.exit(0);
34
+ if (candidate[i] < current[i]) process.exit(1);
35
+ }
36
+ process.exit(1);
37
+ ' "$VERSION" "$REGISTRY_VERSION" || {
38
+ echo "release-candidate: $VERSION is not newer than registry $REGISTRY_VERSION" >&2
39
+ exit 1
40
+ }
41
+
42
+ TAG_MATCH=$(git ls-remote --tags origin "refs/tags/v$VERSION" "refs/tags/v$VERSION^{}")
43
+ if [ -n "$TAG_MATCH" ]; then
44
+ echo "release-candidate: remote tag v$VERSION already exists" >&2
45
+ exit 1
46
+ fi
47
+
48
+ PACK_DIR="$TMP/pack"
49
+ PREFIX="$TMP/prefix"
50
+ SCRATCH="$TMP/scratch"
51
+ mkdir -p "$PACK_DIR" "$PREFIX" "$SCRATCH"
52
+
53
+ npm pack --pack-destination "$PACK_DIR" >/dev/null
54
+ TGZ=$(find "$PACK_DIR" -maxdepth 1 -name '*.tgz' -type f -print | sort | sed -n '1p')
55
+ if [ -z "$TGZ" ]; then
56
+ echo "release-candidate: npm pack produced no tarball" >&2
57
+ exit 1
58
+ fi
59
+
60
+ tar -tzf "$TGZ" > "$TMP/files.txt"
61
+ grep -Fxq 'package/release/lineage.v0.json' "$TMP/files.txt"
62
+ grep -Fxq 'package/packages/control/src/cli.ts' "$TMP/files.txt"
63
+ grep -Fxq 'package/packages/protocol/src/index.ts' "$TMP/files.txt"
64
+ if grep -Eq '^package/lib/' "$TMP/files.txt"; then
65
+ echo "release-candidate: compiled lib output contradicts source-shipping mode" >&2
66
+ exit 1
67
+ fi
68
+
69
+ tar -xzOf "$TGZ" package/package.json | node -e '
70
+ let d="";
71
+ process.stdin.on("data", c => d += c).on("end", () => {
72
+ const p = JSON.parse(d);
73
+ const expectedName = process.argv[1];
74
+ const expectedVersion = process.argv[2];
75
+ if (p.name !== expectedName || p.version !== expectedVersion) process.exit(1);
76
+ for (const name of ["etq", "etiquette", "etiquette-core"]) {
77
+ if (!p.bin || typeof p.bin[name] !== "string") process.exit(1);
78
+ }
79
+ if (p.prepack || (p.scripts && (p.scripts.prepack || p.scripts["release:build"]))) process.exit(1);
80
+ });
81
+ ' "$PACKAGE_NAME" "$VERSION"
82
+
83
+ npm install --prefix "$PREFIX" --ignore-scripts --no-audit --no-fund "$TGZ" >/dev/null
84
+ ETQ_BIN="$PREFIX/node_modules/.bin/etq"
85
+ ETIQUETTE_BIN="$PREFIX/node_modules/.bin/etiquette"
86
+ CORE_BIN="$PREFIX/node_modules/.bin/etiquette-core"
87
+ for binary in "$ETQ_BIN" "$ETIQUETTE_BIN" "$CORE_BIN"; do
88
+ if [ ! -x "$binary" ]; then
89
+ echo "release-candidate: installed binary missing: $binary" >&2
90
+ exit 1
91
+ fi
92
+ done
93
+
94
+ REAL_ETQ=$(node -e 'process.stdout.write(require("fs").realpathSync(process.argv[1]))' "$ETQ_BIN")
95
+ REAL_PREFIX=$(node -e 'process.stdout.write(require("fs").realpathSync(process.argv[1]))' "$PREFIX")
96
+ case "$REAL_ETQ" in
97
+ "$REAL_PREFIX"/*) ;;
98
+ *) echo "release-candidate: etq resolved outside isolated prefix" >&2; exit 1 ;;
99
+ esac
100
+
101
+ EXPECTED="etiquette $VERSION ($PACKAGE_NAME)"
102
+ [ "$($ETQ_BIN --version)" = "$EXPECTED" ]
103
+ [ "$($ETIQUETTE_BIN version)" = "$EXPECTED" ]
104
+
105
+ PROFILE="$SCRATCH/profile.yaml"
106
+ DRAFT="$SCRATCH/candidate-review.md"
107
+ cat > "$PROFILE" <<'YAML'
108
+ schema: packet-profile.v0
109
+ format: markdown-frontmatter
110
+ filename:
111
+ pattern: "{{created_at}}-{{kind}}"
112
+ extension: .md
113
+ frontmatter:
114
+ fields:
115
+ - key: kind
116
+ required: true
117
+ - key: work_id
118
+ required: true
119
+ - key: author
120
+ required: true
121
+ - key: recipient
122
+ required: true
123
+ - key: created_at
124
+ required: true
125
+ - key: changes_state
126
+ default: false
127
+ title:
128
+ derive: "{{work_id}} {{kind}}"
129
+ sections:
130
+ - key: summary
131
+ heading: Summary
132
+ required: true
133
+ - key: evidence
134
+ heading: Evidence
135
+ required: true
136
+ - key: next_step
137
+ heading: Next Step
138
+ required: true
139
+ YAML
140
+
141
+ (cd "$SCRATCH" && "$ETQ_BIN" post \
142
+ --profile "$PROFILE" \
143
+ --draft \
144
+ --out "$DRAFT" \
145
+ --kind review-return \
146
+ --work-id RELEASE-CANDIDATE \
147
+ --author candidate-seat \
148
+ --recipient review-seat \
149
+ --summary 'Candidate package installed from the reviewed tarball.' \
150
+ --evidence 'Exact package identity and isolated executable provenance passed.' \
151
+ --next-step 'Run the consumer lint bridge.' \
152
+ --at '2026-07-13T14:00:00.000Z' >/dev/null)
153
+
154
+ [ -f "$DRAFT" ]
155
+ [ ! -e "$SCRATCH/.etiquette" ]
156
+ grep -Fq 'changes_state: false' "$DRAFT"
157
+
158
+ mkdir -p "$ROOT/dist"
159
+ TARGET="$ROOT/dist/$(basename "$TGZ")"
160
+ cp "$TGZ" "$TARGET"
161
+ (cd "$ROOT/dist" && shasum -a 256 "$(basename "$TARGET")" > SHA256SUMS)
162
+ rm -f \
163
+ "$ROOT/dist/SHA256SUMS.sig" \
164
+ "$ROOT/dist/SHA256SUMS.hmac" \
165
+ "$ROOT/dist/SIGNATURE_MANIFEST.txt" \
166
+ "$ROOT/dist/SIGNATURE_REQUIRED.txt"
167
+ SHA256=$(shasum -a 256 "$TARGET" | awk '{print $1}')
168
+ printf 'release-candidate: ok\n'
169
+ printf 'package: %s@%s\n' "$PACKAGE_NAME" "$VERSION"
170
+ printf 'registry_floor_observed: %s\n' "$REGISTRY_VERSION"
171
+ printf 'tarball: %s\n' "$TARGET"
172
+ printf 'checksums: %s\n' "$ROOT/dist/SHA256SUMS"
173
+ printf 'sha256: %s\n' "$SHA256"
174
+ printf 'installed_etq: %s\n' "$REAL_ETQ"
175
+ printf 'draft: %s\n' "$DRAFT"
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+ # Create a fresh npm tarball and checksum manifest under ignored dist/.
3
+ set -eu
4
+
5
+ ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
6
+ TMPDIR_ROOT=${TMPDIR:-/tmp}
7
+ TMP=$(mktemp -d "$TMPDIR_ROOT/etiquette-release-checksum.XXXXXX")
8
+ trap 'rm -rf "$TMP"' EXIT INT TERM
9
+
10
+ cd "$ROOT"
11
+ sh scripts/release-pack-canary.sh >/dev/null
12
+ mkdir -p dist
13
+ npm pack --pack-destination "$TMP" >/dev/null
14
+
15
+ TGZ=$(find "$TMP" -maxdepth 1 -name '*.tgz' -print | sort | sed -n '1p')
16
+ if [ -z "$TGZ" ]; then
17
+ echo "release-checksum: npm pack did not produce a tarball" >&2
18
+ exit 1
19
+ fi
20
+
21
+ TARGET="dist/$(basename "$TGZ")"
22
+ cp "$TGZ" "$TARGET"
23
+ (cd dist && shasum -a 256 "$(basename "$TARGET")" > SHA256SUMS)
24
+
25
+ echo "release-checksum: wrote $TARGET and dist/SHA256SUMS"