@etiquekit/etq 1.0.14 → 1.0.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.
Files changed (143) hide show
  1. package/AGENTS.md +26 -19
  2. package/LICENSE +3 -2
  3. package/NOTICE +4 -6
  4. package/QuickStart.md +46 -35
  5. package/README.md +56 -56
  6. package/bin/etiquette +5 -1
  7. package/bin/etiquette-core +5 -1
  8. package/docs/ARCHITECTURE.md +17 -20
  9. package/docs/CONCEPTS.md +5 -5
  10. package/docs/CORE_PROFILE.md +15 -7
  11. package/docs/LANE_PROVISIONING.md +2 -7
  12. package/docs/README.md +14 -13
  13. package/docs/RELEASE_SURFACE_AUDIT.md +7 -8
  14. package/docs/SEAT_DISCIPLINE.md +91 -55
  15. package/docs/SEAT_PROVISIONING.md +19 -16
  16. package/docs/TEAM_HANDOFF.md +21 -21
  17. package/docs/WORKTREE_QOL.md +0 -7
  18. package/docs/contracts/ledger-entry/README.md +11 -11
  19. package/docs/contracts/ledger-entry/ledger-entry.v0.2.md +2 -2
  20. package/docs/contracts/ledger-entry/ledger-entry.v0.md +8 -8
  21. package/lib/etiquette-core.js +313 -0
  22. package/lib/etiquette.js +1151 -0
  23. package/package.json +11 -10
  24. package/templates/etiquette-vanilla-v0/README.md +3 -2
  25. package/templates/etiquette-vanilla-v0/source/control-seat/README.md +6 -0
  26. package/templates/etiquette-vanilla-v0/source/control-seat/bin/access-assurance-check +55 -0
  27. package/templates/etiquette-vanilla-v0/source/control-seat/bin/seat-doctor +5 -0
  28. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/ACCESS-ASSURANCE.md +39 -0
  29. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/workspace-secure-profile.v0.json +53 -0
  30. package/templates/etiquette-vanilla-v0/validate-vanilla.sh +5 -0
  31. package/templates/hosted-receiver/README.md +41 -0
  32. package/templates/hosted-receiver/w1-github-webhook-receiver.mjs +129 -0
  33. package/templates/seat-packs-v0/README.md +2 -3
  34. package/templates/seat-packs-v0/source/claude-code-seat/README.md +3 -3
  35. package/templates/seat-packs-v0/source/codex-seat/README.md +3 -3
  36. package/templates/seat-packs-v0/source/gemini-seat/README.md +3 -3
  37. package/templates/seat-packs-v0/source/ollama-seat/README.md +3 -3
  38. package/templates/seat-packs-v0/source/openrouter-seat/README.md +3 -3
  39. package/docs/CONCEPT_STATUS.md +0 -66
  40. package/packages/control/src/authority/lease.ts +0 -261
  41. package/packages/control/src/authority/node-delegation.ts +0 -257
  42. package/packages/control/src/authority/rig-conductor.ts +0 -632
  43. package/packages/control/src/cli/argv.ts +0 -155
  44. package/packages/control/src/cli/commands/console.ts +0 -200
  45. package/packages/control/src/cli/commands/dispatch-core.ts +0 -89
  46. package/packages/control/src/cli/commands/dispatch.ts +0 -279
  47. package/packages/control/src/cli/commands/harness.ts +0 -89
  48. package/packages/control/src/cli/commands/hook.ts +0 -50
  49. package/packages/control/src/cli/commands/ledger.ts +0 -91
  50. package/packages/control/src/cli/commands/local-workflow.ts +0 -4690
  51. package/packages/control/src/cli/commands/memory.ts +0 -445
  52. package/packages/control/src/cli/commands/release.ts +0 -108
  53. package/packages/control/src/cli/commands/rubric.ts +0 -103
  54. package/packages/control/src/cli/commands/seat.ts +0 -179
  55. package/packages/control/src/cli/commands/session.ts +0 -127
  56. package/packages/control/src/cli/commands/supervision.ts +0 -246
  57. package/packages/control/src/cli/commands/sync.ts +0 -119
  58. package/packages/control/src/cli/commands/workflow.ts +0 -86
  59. package/packages/control/src/cli/commands/workspace.ts +0 -50
  60. package/packages/control/src/cli/core-usage.ts +0 -34
  61. package/packages/control/src/cli/prompt.ts +0 -67
  62. package/packages/control/src/cli/supervision-deps.ts +0 -44
  63. package/packages/control/src/cli/usage.ts +0 -241
  64. package/packages/control/src/cli.ts +0 -207
  65. package/packages/control/src/core-cli.ts +0 -50
  66. package/packages/control/src/dispatch/decision.ts +0 -202
  67. package/packages/control/src/dispatch/projection.ts +0 -293
  68. package/packages/control/src/dispatch/record.ts +0 -153
  69. package/packages/control/src/engagement/project.ts +0 -170
  70. package/packages/control/src/fs.ts +0 -19
  71. package/packages/control/src/harness/pruning.ts +0 -406
  72. package/packages/control/src/hooks/dispatcher.ts +0 -117
  73. package/packages/control/src/hooks/outbox.ts +0 -86
  74. package/packages/control/src/hooks/sanitize.ts +0 -6
  75. package/packages/control/src/hooks/types.ts +0 -34
  76. package/packages/control/src/index.ts +0 -384
  77. package/packages/control/src/ledger/entry.ts +0 -303
  78. package/packages/control/src/ledger/indexer.ts +0 -542
  79. package/packages/control/src/memory/context.ts +0 -149
  80. package/packages/control/src/memory/drain-import.ts +0 -207
  81. package/packages/control/src/memory/indexer.ts +0 -284
  82. package/packages/control/src/memory/query.ts +0 -75
  83. package/packages/control/src/memory/sanitize.ts +0 -50
  84. package/packages/control/src/memory/sharded-drain-import.ts +0 -212
  85. package/packages/control/src/memory/status.ts +0 -211
  86. package/packages/control/src/memory/store-lifecycle.ts +0 -509
  87. package/packages/control/src/memory/store.ts +0 -284
  88. package/packages/control/src/memory/types.ts +0 -146
  89. package/packages/control/src/parity/surfaces.ts +0 -748
  90. package/packages/control/src/project.ts +0 -141
  91. package/packages/control/src/projection/local-ledger-view.ts +0 -373
  92. package/packages/control/src/projection/return-enforcement.ts +0 -48
  93. package/packages/control/src/projection/timeline-preview.ts +0 -539
  94. package/packages/control/src/projection/timeline.ts +0 -708
  95. package/packages/control/src/release/readiness.ts +0 -842
  96. package/packages/control/src/rubric/loader.ts +0 -326
  97. package/packages/control/src/rubric/promotion.ts +0 -54
  98. package/packages/control/src/rubric/runner.ts +0 -159
  99. package/packages/control/src/rubric/types.ts +0 -158
  100. package/packages/control/src/seat/owner-card.ts +0 -388
  101. package/packages/control/src/seat/readiness.ts +0 -834
  102. package/packages/control/src/session/runbook.ts +0 -431
  103. package/packages/control/src/shared/sanitize.ts +0 -49
  104. package/packages/control/src/supervision/action-classes.ts +0 -192
  105. package/packages/control/src/supervision/command-apply.ts +0 -378
  106. package/packages/control/src/supervision/errors.ts +0 -14
  107. package/packages/control/src/supervision/event-replay.ts +0 -155
  108. package/packages/control/src/supervision/events.ts +0 -109
  109. package/packages/control/src/supervision/index.ts +0 -16
  110. package/packages/control/src/supervision/manifest.ts +0 -127
  111. package/packages/control/src/supervision/paths.ts +0 -49
  112. package/packages/control/src/supervision/projection-adapter.ts +0 -274
  113. package/packages/control/src/supervision/projection.ts +0 -75
  114. package/packages/control/src/supervision/rebuild.ts +0 -99
  115. package/packages/control/src/supervision/session-open.ts +0 -131
  116. package/packages/control/src/supervision/session-read.ts +0 -99
  117. package/packages/control/src/supervision/sqlite-impl.ts +0 -71
  118. package/packages/control/src/supervision/sqlite.ts +0 -121
  119. package/packages/control/src/supervision/store-rows.ts +0 -371
  120. package/packages/control/src/supervision/turn-close.ts +0 -154
  121. package/packages/control/src/supervision/turn-open.ts +0 -284
  122. package/packages/control/src/sync/event-log-merge-driver.ts +0 -263
  123. package/packages/control/src/sync/join-plan.ts +0 -375
  124. package/packages/control/src/sync/outbox.ts +0 -492
  125. package/packages/control/src/workflow/evaluator.ts +0 -140
  126. package/packages/control/src/workflow/loader.ts +0 -200
  127. package/packages/control/src/workflow/types.ts +0 -90
  128. package/packages/control/src/workspace/authority.ts +0 -499
  129. package/packages/protocol/src/guards.ts +0 -119
  130. package/packages/protocol/src/huddle-board.ts +0 -198
  131. package/packages/protocol/src/huddle.ts +0 -295
  132. package/packages/protocol/src/incident.ts +0 -251
  133. package/packages/protocol/src/index.ts +0 -8
  134. package/packages/protocol/src/interfaces.ts +0 -107
  135. package/packages/protocol/src/packet-profile.ts +0 -195
  136. package/packages/protocol/src/state.ts +0 -81
  137. package/packages/protocol/src/types.ts +0 -434
  138. package/release/lineage.v0.json +0 -15
  139. package/scripts/release-candidate-verify.sh +0 -175
  140. package/scripts/release-checksum.sh +0 -25
  141. package/scripts/release-pack-canary.sh +0 -97
  142. package/scripts/release-scan.sh +0 -249
  143. package/scripts/release-sign.sh +0 -34
@@ -1,207 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { parseArgs } from './cli/argv';
4
- import { dispatchConsole, isConsoleCommand } from './cli/commands/console';
5
- import { dispatchDispatch, isDispatchCommand } from './cli/commands/dispatch';
6
- import { dispatchHarness, isHarnessCommand } from './cli/commands/harness';
7
- import { dispatchHookCli, isHookCommand } from './cli/commands/hook';
8
- import { dispatchLedger, isLedgerCommand } from './cli/commands/ledger';
9
- import { dispatchLocalWorkflow, isLocalWorkflowCommand } from './cli/commands/local-workflow';
10
- import { dispatchMemory, isMemoryCommand } from './cli/commands/memory';
11
- import { dispatchRubric, isRubricCommand } from './cli/commands/rubric';
12
- import { dispatchRelease, isReleaseCommand } from './cli/commands/release';
13
- import { dispatchSeat, isSeatCommand } from './cli/commands/seat';
14
- import { dispatchSession, isSessionCommand } from './cli/commands/session';
15
- import { advancedUsage, usage } from './cli/usage';
16
- import { dispatchSync, isSyncCommand } from './cli/commands/sync';
17
- import { dispatchWorkflow, isWorkflowCommand } from './cli/commands/workflow';
18
- import { dispatchWorkspace, isWorkspaceCommand } from './cli/commands/workspace';
19
-
20
- /**
21
- * Thin dispatcher. The former monolithic `cli.ts` was split across
22
- * `cli/argv.ts` (parsing), `cli/usage.ts` (help text), and per-category
23
- * command modules. This entry point only classifies the top-level command and
24
- * delegates to the matching command module.
25
- */
26
- // Clean error rendering: a CLI failure must print a human-readable message,
27
- // never a raw stack/bundle dump (see CONTRIBUTING.md). Set ETQ_DEBUG=1 for stacks.
28
- function renderCliError(err: unknown): never {
29
- const message = err instanceof Error ? err.message : String(err);
30
- console.error(`error: ${message}`);
31
- if (process.env.ETQ_DEBUG && err instanceof Error && err.stack) {
32
- console.error(err.stack);
33
- }
34
- process.exit(1);
35
- }
36
- process.on('uncaughtException', renderCliError);
37
- process.on('unhandledRejection', renderCliError);
38
-
39
- const { positionals, flags } = parseArgs(process.argv.slice(2));
40
- const command = positionals[0];
41
-
42
- if (command === 'version' || flags.version) {
43
- const { readFileSync } = await import('node:fs');
44
- const pkg = JSON.parse(
45
- readFileSync(new URL('../../../package.json', import.meta.url), 'utf-8'),
46
- ) as { name?: string; version?: string };
47
- console.log(`etiquette ${pkg.version ?? 'unknown'} (${pkg.name ?? 'etiquette'})`);
48
- process.exit(0);
49
- }
50
-
51
- const SUPERVISION_COMMANDS_CLI: ReadonlySet<string> = new Set([
52
- 'session-open',
53
- 'session-status',
54
- 'turn-open',
55
- 'turn-close',
56
- 'session-command',
57
- 'session-project',
58
- 'session-rebuild',
59
- 'seat-validate',
60
- ]);
61
-
62
- if (!command) {
63
- console.error(usage());
64
- process.exit(1);
65
- }
66
-
67
- if (command === 'help' || flags.help) {
68
- console.error(positionals[1] === 'advanced' ? advancedUsage() : usage());
69
- process.exit(0);
70
- }
71
-
72
- if (SUPERVISION_COMMANDS_CLI.has(command)) {
73
- const { dispatchSupervision } = await import('./cli/commands/supervision');
74
- await dispatchSupervision(command, positionals, flags);
75
- process.exit(0);
76
- }
77
-
78
- if (command === 'agent-plane') {
79
- console.error(
80
- 'agent-plane commands are not included in the local devkit; they return with the remote runner-plane work.',
81
- );
82
- process.exit(1);
83
- }
84
-
85
- if (isMemoryCommand(command)) {
86
- await dispatchMemory(positionals, flags);
87
- process.exit(0);
88
- }
89
-
90
- if (command === 'mcp') {
91
- console.error(
92
- 'mcp commands are not included in the local devkit; use a source workspace.',
93
- );
94
- process.exit(1);
95
- }
96
-
97
- if (command === 'parity') {
98
- console.error(
99
- 'parity commands are not included in the local devkit; use a source workspace.',
100
- );
101
- process.exit(1);
102
- }
103
-
104
- if (isConsoleCommand(command)) {
105
- await dispatchConsole(positionals, flags);
106
- process.exit(0);
107
- }
108
-
109
- if (isHookCommand(command)) {
110
- await dispatchHookCli(positionals, flags);
111
- process.exit(0);
112
- }
113
-
114
- if (isHarnessCommand(command)) {
115
- await dispatchHarness(positionals, flags);
116
- process.exit(0);
117
- }
118
-
119
- if (command === 'hosted') {
120
- console.error(
121
- 'hosted commands are not included in the local devkit; use a hosted/control-plane source workspace.',
122
- );
123
- process.exit(1);
124
- }
125
-
126
- if (command === 'integration') {
127
- console.error(
128
- 'integration commands are not included in the local devkit; use a source workspace.',
129
- );
130
- process.exit(1);
131
- }
132
-
133
- if (isLedgerCommand(command)) {
134
- await dispatchLedger(positionals, flags);
135
- process.exit(0);
136
- }
137
-
138
- if (command === 'linear') {
139
- console.error(
140
- 'linear commands are not included in the local devkit; use a source workspace.',
141
- );
142
- process.exit(1);
143
- }
144
-
145
- if (isDispatchCommand(command)) {
146
- await dispatchDispatch(positionals, flags);
147
- process.exit(0);
148
- }
149
-
150
- if (isRubricCommand(command)) {
151
- await dispatchRubric(positionals, flags);
152
- process.exit(0);
153
- }
154
-
155
- if (isReleaseCommand(command)) {
156
- await dispatchRelease(positionals, flags);
157
- process.exit(0);
158
- }
159
-
160
- if (command === 'remote') {
161
- console.error(
162
- 'remote commands are not included in the local devkit; remote execution ships with the hosted workspace product later.',
163
- );
164
- process.exit(1);
165
- }
166
-
167
- if (command === 'runtime') {
168
- console.error(
169
- 'runtime commands are not included in the local devkit; use an infra/runtime source workspace.',
170
- );
171
- process.exit(1);
172
- }
173
-
174
- if (isSeatCommand(command)) {
175
- await dispatchSeat(positionals, flags);
176
- process.exit(0);
177
- }
178
-
179
- if (isSessionCommand(command)) {
180
- await dispatchSession(positionals, flags);
181
- process.exit(0);
182
- }
183
-
184
- if (isSyncCommand(command)) {
185
- await dispatchSync(positionals, flags);
186
- process.exit(0);
187
- }
188
-
189
- if (isWorkflowCommand(command)) {
190
- await dispatchWorkflow(positionals, flags);
191
- process.exit(0);
192
- }
193
-
194
- if (isLocalWorkflowCommand(command)) {
195
- await dispatchLocalWorkflow(positionals, flags);
196
- process.exit(0);
197
- }
198
-
199
- if (isWorkspaceCommand(command)) {
200
- await dispatchWorkspace(positionals, flags);
201
- process.exit(0);
202
- }
203
-
204
- console.error(`unknown command: ${command}`);
205
- console.error('');
206
- console.error(usage());
207
- process.exit(1);
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { parseArgs } from './cli/argv';
4
- import { coreUsage } from './cli/core-usage';
5
- import { dispatchCoreDispatch, isCoreDispatchCommand } from './cli/commands/dispatch-core';
6
- import { dispatchLedger, isLedgerCommand } from './cli/commands/ledger';
7
- import { dispatchRubric, isRubricCommand } from './cli/commands/rubric';
8
- import { dispatchSeat, isSeatCommand } from './cli/commands/seat';
9
- import { dispatchSession, isSessionCommand } from './cli/commands/session';
10
- import { dispatchWorkflow, isWorkflowCommand } from './cli/commands/workflow';
11
-
12
- const { positionals, flags } = parseArgs(process.argv.slice(2));
13
- const command = positionals[0];
14
-
15
- if (!command || command === 'help' || flags.help) {
16
- console.error(coreUsage());
17
- process.exit(command || flags.help ? 0 : 1);
18
- }
19
-
20
- if (isSeatCommand(command)) {
21
- await dispatchSeat(positionals, flags);
22
- process.exit(0);
23
- }
24
-
25
- if (isSessionCommand(command)) {
26
- await dispatchSession(positionals, flags);
27
- process.exit(0);
28
- }
29
-
30
- if (isWorkflowCommand(command)) {
31
- await dispatchWorkflow(positionals, flags);
32
- process.exit(0);
33
- }
34
-
35
- if (isRubricCommand(command)) {
36
- await dispatchRubric(positionals, flags);
37
- process.exit(0);
38
- }
39
-
40
- if (isCoreDispatchCommand(command)) {
41
- await dispatchCoreDispatch(positionals, flags);
42
- process.exit(0);
43
- }
44
-
45
- if (isLedgerCommand(command)) {
46
- await dispatchLedger(positionals, flags);
47
- process.exit(0);
48
- }
49
-
50
- throw new Error(`etiquette-core does not include '${command}'. Use the full 'etiquette' CLI for optional runtime, hosted, adapter, console, MCP, memory, sync, or release surfaces.`);
@@ -1,202 +0,0 @@
1
- import type { SandboxRunReceipt } from '../rubric/types';
2
- import type { SeatReadinessStatus } from '../seat/readiness';
3
- import type { WorkflowCheckEnvelope, WorkflowCheckResult, WorkflowMode } from '../workflow/types';
4
-
5
- export const OPERATIONAL_DECISIONS = [
6
- 'dispatch_ready',
7
- 'hold_for_grant',
8
- 'blocked_by_capability',
9
- 'blocked_by_validation',
10
- 'quarantine_hold',
11
- ] as const;
12
-
13
- export type OperationalDecision = typeof OPERATIONAL_DECISIONS[number];
14
-
15
- export interface OperationalDispatchDecision {
16
- schema: 'operational-dispatch-decision.v0';
17
- task_ref: string;
18
- seat: string;
19
- decision: OperationalDecision;
20
- reasons: string[];
21
- warnings: string[];
22
- profile_hint: 'quarantine_hold' | 'batch_backlog' | 'sabbatical_improvement' | null;
23
- inputs: {
24
- seat_readiness: {
25
- operational_status: SeatReadinessStatus['operational_status'];
26
- routing_recommendation: SeatReadinessStatus['routing_recommendation'];
27
- capability_trusted: boolean;
28
- model_tier: SeatReadinessStatus['model_tier'];
29
- effective_model_tier: SeatReadinessStatus['effective_model_tier'];
30
- active_workers: number;
31
- max_recommended_workers: number;
32
- is_stale: boolean;
33
- };
34
- workflow_check: {
35
- mode_id: string;
36
- mode_type: WorkflowCheckResult['mode_type'];
37
- recommendation: WorkflowCheckResult['recommendation'];
38
- missing: string[];
39
- warnings: string[];
40
- };
41
- strategy: {
42
- requested_strategy: string | null;
43
- policy: WorkflowMode['execution']['strategy_policy'];
44
- supported: boolean | null;
45
- unsupported: boolean | null;
46
- };
47
- rubric_receipt: {
48
- receipt_id: string | null;
49
- unexpected_outcomes: number | null;
50
- accepted: boolean | null;
51
- };
52
- };
53
- authority_boundary: {
54
- can_dispatch: false;
55
- can_authorize: false;
56
- can_attach_grant: false;
57
- can_execute: false;
58
- consumer_is_engine: false;
59
- };
60
- }
61
-
62
- function unique(values: string[]): string[] {
63
- return [...new Set(values)];
64
- }
65
-
66
- function isGrantOnlyBlock(workflow: WorkflowCheckResult): boolean {
67
- return workflow.missing.length > 0 && workflow.missing.every((item) => item === 'grant_ref');
68
- }
69
-
70
- function strategyStatus(
71
- status: SeatReadinessStatus,
72
- requestedStrategy: string | null,
73
- ): { supported: boolean | null; unsupported: boolean | null } {
74
- if (!requestedStrategy) return { supported: null, unsupported: null };
75
- return {
76
- supported: status.supported_strategies.includes(requestedStrategy),
77
- unsupported: status.unsupported_strategies.includes(requestedStrategy),
78
- };
79
- }
80
-
81
- function rubricAccepted(receipt: SandboxRunReceipt | null | undefined): boolean | null {
82
- if (!receipt) return null;
83
- return receipt.summary.unexpected_outcomes === 0;
84
- }
85
-
86
- export function evaluateOperationalDispatch(options: {
87
- seat: SeatReadinessStatus;
88
- mode: WorkflowMode;
89
- envelope: WorkflowCheckEnvelope;
90
- workflow: WorkflowCheckResult;
91
- sandboxReceipt?: SandboxRunReceipt | null;
92
- requestedStrategy?: string | null;
93
- }): OperationalDispatchDecision {
94
- const reasons: string[] = [];
95
- const warnings: string[] = [...options.workflow.warnings];
96
- let decision: OperationalDecision = 'dispatch_ready';
97
- let profileHint: OperationalDispatchDecision['profile_hint'] = null;
98
- const requestedStrategy = options.requestedStrategy ?? null;
99
- const strategy = strategyStatus(options.seat, requestedStrategy);
100
- const sandboxAccepted = rubricAccepted(options.sandboxReceipt);
101
-
102
- if (options.envelope.advisory_consensus_claims_authority) {
103
- decision = 'quarantine_hold';
104
- profileHint = 'quarantine_hold';
105
- reasons.push('advisory_consensus_claims_authority');
106
- }
107
-
108
- if (decision === 'dispatch_ready' && options.seat.routing_recommendation !== 'route_if_policy_allows') {
109
- decision = 'blocked_by_capability';
110
- reasons.push(`seat_routing_${options.seat.routing_recommendation}`);
111
- }
112
-
113
- if (decision === 'dispatch_ready' && options.seat.active_workers >= options.seat.max_recommended_workers) {
114
- decision = 'blocked_by_capability';
115
- reasons.push('seat_at_worker_capacity');
116
- }
117
-
118
- if (decision === 'dispatch_ready' && requestedStrategy && strategy.unsupported && options.mode.execution.strategy_policy === 'required') {
119
- decision = 'blocked_by_capability';
120
- reasons.push('required_strategy_unsupported');
121
- } else if (requestedStrategy && strategy.unsupported) {
122
- warnings.push('requested_strategy_unsupported_downshift_allowed');
123
- }
124
-
125
- if (decision === 'dispatch_ready' && options.workflow.recommendation === 'block') {
126
- if (isGrantOnlyBlock(options.workflow)) {
127
- decision = 'hold_for_grant';
128
- reasons.push('grant_ref_required');
129
- } else if (
130
- options.workflow.missing.includes('validation_refs')
131
- || options.workflow.missing.includes('receipt_ref')
132
- ) {
133
- decision = 'blocked_by_validation';
134
- reasons.push(...options.workflow.missing.filter((item) => item === 'validation_refs' || item === 'receipt_ref'));
135
- } else {
136
- decision = 'quarantine_hold';
137
- profileHint = 'quarantine_hold';
138
- reasons.push(...options.workflow.missing);
139
- }
140
- }
141
-
142
- if (decision === 'dispatch_ready' && options.mode.execution.rubric_required && !options.sandboxReceipt) {
143
- decision = 'blocked_by_validation';
144
- reasons.push('sandbox_run_receipt_required');
145
- }
146
-
147
- if (decision === 'dispatch_ready' && sandboxAccepted === false) {
148
- decision = 'blocked_by_validation';
149
- reasons.push('sandbox_run_receipt_unexpected_outcomes');
150
- }
151
-
152
- if (decision === 'dispatch_ready' && options.mode.mode_type === 'deliberative') {
153
- profileHint = 'sabbatical_improvement';
154
- }
155
-
156
- return {
157
- schema: 'operational-dispatch-decision.v0',
158
- task_ref: options.envelope.task_ref,
159
- seat: options.seat.seat,
160
- decision,
161
- reasons: unique(reasons),
162
- warnings: unique(warnings),
163
- profile_hint: profileHint,
164
- inputs: {
165
- seat_readiness: {
166
- operational_status: options.seat.operational_status,
167
- routing_recommendation: options.seat.routing_recommendation,
168
- capability_trusted: options.seat.capability_trusted,
169
- model_tier: options.seat.model_tier,
170
- effective_model_tier: options.seat.effective_model_tier,
171
- active_workers: options.seat.active_workers,
172
- max_recommended_workers: options.seat.max_recommended_workers,
173
- is_stale: options.seat.is_stale,
174
- },
175
- workflow_check: {
176
- mode_id: options.workflow.mode_id,
177
- mode_type: options.workflow.mode_type,
178
- recommendation: options.workflow.recommendation,
179
- missing: options.workflow.missing,
180
- warnings: options.workflow.warnings,
181
- },
182
- strategy: {
183
- requested_strategy: requestedStrategy,
184
- policy: options.mode.execution.strategy_policy,
185
- supported: strategy.supported,
186
- unsupported: strategy.unsupported,
187
- },
188
- rubric_receipt: {
189
- receipt_id: options.sandboxReceipt?.receipt_id ?? null,
190
- unexpected_outcomes: options.sandboxReceipt?.summary.unexpected_outcomes ?? null,
191
- accepted: sandboxAccepted,
192
- },
193
- },
194
- authority_boundary: {
195
- can_dispatch: false,
196
- can_authorize: false,
197
- can_attach_grant: false,
198
- can_execute: false,
199
- consumer_is_engine: false,
200
- },
201
- };
202
- }