jg-agent-hq 0.2.0 → 0.3.0

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.
@@ -53,7 +53,7 @@ export declare const HqRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
53
53
  }, z.core.$strict>;
54
54
  kind: z.ZodLiteral<"finalize">;
55
55
  }, z.core.$strict>, z.ZodObject<{
56
- milestoneId: z.ZodUUID;
56
+ milestoneId: z.ZodNullable<z.ZodUUID>;
57
57
  checks: z.ZodArray<z.ZodObject<{
58
58
  command: z.ZodString;
59
59
  outcome: z.ZodLiteral<"passed">;
@@ -239,7 +239,7 @@ export declare const HqRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
239
239
  breakdownDigest: z.ZodNullable<z.ZodString>;
240
240
  }, z.core.$strict>;
241
241
  authorizationId: z.ZodUUID;
242
- milestoneId: z.ZodUUID;
242
+ milestoneId: z.ZodNullable<z.ZodUUID>;
243
243
  mode: z.ZodEnum<{
244
244
  supervised: "supervised";
245
245
  auto: "auto";
@@ -464,7 +464,7 @@ export declare const HqRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
464
464
  plan: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
465
465
  kind: z.ZodLiteral<"execution">;
466
466
  authorizationId: z.ZodUUID;
467
- milestoneId: z.ZodUUID;
467
+ milestoneId: z.ZodNullable<z.ZodUUID>;
468
468
  mode: z.ZodEnum<{
469
469
  supervised: "supervised";
470
470
  auto: "auto";
@@ -483,7 +483,7 @@ export declare const HqRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
483
483
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
484
484
  kind: z.ZodLiteral<"execution">;
485
485
  authorizationId: z.ZodUUID;
486
- milestoneId: z.ZodUUID;
486
+ milestoneId: z.ZodNullable<z.ZodUUID>;
487
487
  mode: z.ZodEnum<{
488
488
  supervised: "supervised";
489
489
  auto: "auto";
@@ -797,7 +797,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
797
797
  planDigest: z.ZodString;
798
798
  breakdownDigest: z.ZodNullable<z.ZodString>;
799
799
  }, z.core.$strict>;
800
- fileHash: z.ZodString;
800
+ fileHash: z.ZodNullable<z.ZodString>;
801
801
  createdAt: z.ZodNumber;
802
802
  }, z.core.$strict>>;
803
803
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -1017,7 +1017,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1017
1017
  planDigest: z.ZodString;
1018
1018
  breakdownDigest: z.ZodNullable<z.ZodString>;
1019
1019
  }, z.core.$strict>;
1020
- fileHash: z.ZodString;
1020
+ fileHash: z.ZodNullable<z.ZodString>;
1021
1021
  createdAt: z.ZodNumber;
1022
1022
  }, z.core.$strict>>;
1023
1023
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -1205,7 +1205,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1205
1205
  reference: z.ZodString;
1206
1206
  }, z.core.$strict>;
1207
1207
  }, z.core.$strict>;
1208
- milestoneId: z.ZodUUID;
1208
+ milestoneId: z.ZodNullable<z.ZodUUID>;
1209
1209
  revision: z.ZodObject<{
1210
1210
  planDigest: z.ZodString;
1211
1211
  breakdownDigest: z.ZodNullable<z.ZodString>;
@@ -1213,7 +1213,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1213
1213
  contractDigest: z.ZodString;
1214
1214
  title: z.ZodString;
1215
1215
  contract: z.ZodString;
1216
- sharedDigest: z.ZodString;
1216
+ sharedDigest: z.ZodNullable<z.ZodString>;
1217
1217
  checkouts: z.ZodArray<z.ZodObject<{
1218
1218
  repository: z.ZodString;
1219
1219
  directory: z.ZodString;
@@ -1361,7 +1361,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1361
1361
  planDigest: z.ZodString;
1362
1362
  breakdownDigest: z.ZodNullable<z.ZodString>;
1363
1363
  }, z.core.$strict>;
1364
- fileHash: z.ZodString;
1364
+ fileHash: z.ZodNullable<z.ZodString>;
1365
1365
  createdAt: z.ZodNumber;
1366
1366
  }, z.core.$strict>>;
1367
1367
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -1500,7 +1500,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1500
1500
  }, z.core.$strict>>;
1501
1501
  }, z.core.$strict>;
1502
1502
  }, z.core.$strip>;
1503
- content: z.ZodString;
1503
+ content: z.ZodNullable<z.ZodString>;
1504
1504
  }, z.core.$strip>, z.ZodObject<{
1505
1505
  kind: z.ZodLiteral<"milestones">;
1506
1506
  result: z.ZodObject<{
@@ -1581,7 +1581,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1581
1581
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
1582
1582
  kind: z.ZodLiteral<"execution">;
1583
1583
  authorizationId: z.ZodUUID;
1584
- milestoneId: z.ZodUUID;
1584
+ milestoneId: z.ZodNullable<z.ZodUUID>;
1585
1585
  mode: z.ZodEnum<{
1586
1586
  supervised: "supervised";
1587
1587
  auto: "auto";
@@ -1714,7 +1714,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1714
1714
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
1715
1715
  kind: z.ZodLiteral<"execution">;
1716
1716
  authorizationId: z.ZodUUID;
1717
- milestoneId: z.ZodUUID;
1717
+ milestoneId: z.ZodNullable<z.ZodUUID>;
1718
1718
  mode: z.ZodEnum<{
1719
1719
  supervised: "supervised";
1720
1720
  auto: "auto";
@@ -2051,7 +2051,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2051
2051
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
2052
2052
  kind: z.ZodLiteral<"execution">;
2053
2053
  authorizationId: z.ZodUUID;
2054
- milestoneId: z.ZodUUID;
2054
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2055
2055
  mode: z.ZodEnum<{
2056
2056
  supervised: "supervised";
2057
2057
  auto: "auto";
@@ -2127,7 +2127,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2127
2127
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
2128
2128
  kind: z.ZodLiteral<"execution">;
2129
2129
  authorizationId: z.ZodUUID;
2130
- milestoneId: z.ZodUUID;
2130
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2131
2131
  mode: z.ZodEnum<{
2132
2132
  supervised: "supervised";
2133
2133
  auto: "auto";
@@ -2315,7 +2315,7 @@ export declare const HqResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2315
2315
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
2316
2316
  kind: z.ZodLiteral<"execution">;
2317
2317
  authorizationId: z.ZodUUID;
2318
- milestoneId: z.ZodUUID;
2318
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2319
2319
  mode: z.ZodEnum<{
2320
2320
  supervised: "supervised";
2321
2321
  auto: "auto";
@@ -2496,7 +2496,7 @@ export declare const IpcRequestSchema: z.ZodObject<{
2496
2496
  }, z.core.$strict>;
2497
2497
  kind: z.ZodLiteral<"finalize">;
2498
2498
  }, z.core.$strict>, z.ZodObject<{
2499
- milestoneId: z.ZodUUID;
2499
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2500
2500
  checks: z.ZodArray<z.ZodObject<{
2501
2501
  command: z.ZodString;
2502
2502
  outcome: z.ZodLiteral<"passed">;
@@ -2682,7 +2682,7 @@ export declare const IpcRequestSchema: z.ZodObject<{
2682
2682
  breakdownDigest: z.ZodNullable<z.ZodString>;
2683
2683
  }, z.core.$strict>;
2684
2684
  authorizationId: z.ZodUUID;
2685
- milestoneId: z.ZodUUID;
2685
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2686
2686
  mode: z.ZodEnum<{
2687
2687
  supervised: "supervised";
2688
2688
  auto: "auto";
@@ -2907,7 +2907,7 @@ export declare const IpcRequestSchema: z.ZodObject<{
2907
2907
  plan: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
2908
2908
  kind: z.ZodLiteral<"execution">;
2909
2909
  authorizationId: z.ZodUUID;
2910
- milestoneId: z.ZodUUID;
2910
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2911
2911
  mode: z.ZodEnum<{
2912
2912
  supervised: "supervised";
2913
2913
  auto: "auto";
@@ -2926,7 +2926,7 @@ export declare const IpcRequestSchema: z.ZodObject<{
2926
2926
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
2927
2927
  kind: z.ZodLiteral<"execution">;
2928
2928
  authorizationId: z.ZodUUID;
2929
- milestoneId: z.ZodUUID;
2929
+ milestoneId: z.ZodNullable<z.ZodUUID>;
2930
2930
  mode: z.ZodEnum<{
2931
2931
  supervised: "supervised";
2932
2932
  auto: "auto";
@@ -3096,7 +3096,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3096
3096
  planDigest: z.ZodString;
3097
3097
  breakdownDigest: z.ZodNullable<z.ZodString>;
3098
3098
  }, z.core.$strict>;
3099
- fileHash: z.ZodString;
3099
+ fileHash: z.ZodNullable<z.ZodString>;
3100
3100
  createdAt: z.ZodNumber;
3101
3101
  }, z.core.$strict>>;
3102
3102
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -3316,7 +3316,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3316
3316
  planDigest: z.ZodString;
3317
3317
  breakdownDigest: z.ZodNullable<z.ZodString>;
3318
3318
  }, z.core.$strict>;
3319
- fileHash: z.ZodString;
3319
+ fileHash: z.ZodNullable<z.ZodString>;
3320
3320
  createdAt: z.ZodNumber;
3321
3321
  }, z.core.$strict>>;
3322
3322
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -3504,7 +3504,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3504
3504
  reference: z.ZodString;
3505
3505
  }, z.core.$strict>;
3506
3506
  }, z.core.$strict>;
3507
- milestoneId: z.ZodUUID;
3507
+ milestoneId: z.ZodNullable<z.ZodUUID>;
3508
3508
  revision: z.ZodObject<{
3509
3509
  planDigest: z.ZodString;
3510
3510
  breakdownDigest: z.ZodNullable<z.ZodString>;
@@ -3512,7 +3512,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3512
3512
  contractDigest: z.ZodString;
3513
3513
  title: z.ZodString;
3514
3514
  contract: z.ZodString;
3515
- sharedDigest: z.ZodString;
3515
+ sharedDigest: z.ZodNullable<z.ZodString>;
3516
3516
  checkouts: z.ZodArray<z.ZodObject<{
3517
3517
  repository: z.ZodString;
3518
3518
  directory: z.ZodString;
@@ -3660,7 +3660,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3660
3660
  planDigest: z.ZodString;
3661
3661
  breakdownDigest: z.ZodNullable<z.ZodString>;
3662
3662
  }, z.core.$strict>;
3663
- fileHash: z.ZodString;
3663
+ fileHash: z.ZodNullable<z.ZodString>;
3664
3664
  createdAt: z.ZodNumber;
3665
3665
  }, z.core.$strict>>;
3666
3666
  planApproval: z.ZodNullable<z.ZodObject<{
@@ -3799,7 +3799,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3799
3799
  }, z.core.$strict>>;
3800
3800
  }, z.core.$strict>;
3801
3801
  }, z.core.$strip>;
3802
- content: z.ZodString;
3802
+ content: z.ZodNullable<z.ZodString>;
3803
3803
  }, z.core.$strip>, z.ZodObject<{
3804
3804
  kind: z.ZodLiteral<"milestones">;
3805
3805
  result: z.ZodObject<{
@@ -3880,7 +3880,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3880
3880
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
3881
3881
  kind: z.ZodLiteral<"execution">;
3882
3882
  authorizationId: z.ZodUUID;
3883
- milestoneId: z.ZodUUID;
3883
+ milestoneId: z.ZodNullable<z.ZodUUID>;
3884
3884
  mode: z.ZodEnum<{
3885
3885
  supervised: "supervised";
3886
3886
  auto: "auto";
@@ -4013,7 +4013,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4013
4013
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
4014
4014
  kind: z.ZodLiteral<"execution">;
4015
4015
  authorizationId: z.ZodUUID;
4016
- milestoneId: z.ZodUUID;
4016
+ milestoneId: z.ZodNullable<z.ZodUUID>;
4017
4017
  mode: z.ZodEnum<{
4018
4018
  supervised: "supervised";
4019
4019
  auto: "auto";
@@ -4350,7 +4350,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4350
4350
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
4351
4351
  kind: z.ZodLiteral<"execution">;
4352
4352
  authorizationId: z.ZodUUID;
4353
- milestoneId: z.ZodUUID;
4353
+ milestoneId: z.ZodNullable<z.ZodUUID>;
4354
4354
  mode: z.ZodEnum<{
4355
4355
  supervised: "supervised";
4356
4356
  auto: "auto";
@@ -4426,7 +4426,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4426
4426
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
4427
4427
  kind: z.ZodLiteral<"execution">;
4428
4428
  authorizationId: z.ZodUUID;
4429
- milestoneId: z.ZodUUID;
4429
+ milestoneId: z.ZodNullable<z.ZodUUID>;
4430
4430
  mode: z.ZodEnum<{
4431
4431
  supervised: "supervised";
4432
4432
  auto: "auto";
@@ -4614,7 +4614,7 @@ export declare const IpcResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4614
4614
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
4615
4615
  kind: z.ZodLiteral<"execution">;
4616
4616
  authorizationId: z.ZodUUID;
4617
- milestoneId: z.ZodUUID;
4617
+ milestoneId: z.ZodNullable<z.ZodUUID>;
4618
4618
  mode: z.ZodEnum<{
4619
4619
  supervised: "supervised";
4620
4620
  auto: "auto";
@@ -19,7 +19,7 @@ export declare const HandoffRecordSchema: z.ZodObject<{
19
19
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
20
20
  kind: z.ZodLiteral<"execution">;
21
21
  authorizationId: z.ZodUUID;
22
- milestoneId: z.ZodUUID;
22
+ milestoneId: z.ZodNullable<z.ZodUUID>;
23
23
  mode: z.ZodEnum<{
24
24
  supervised: "supervised";
25
25
  auto: "auto";
@@ -155,7 +155,7 @@ export declare const HandoffRecordSchema: z.ZodObject<{
155
155
  plan: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
156
156
  kind: z.ZodLiteral<"execution">;
157
157
  authorizationId: z.ZodUUID;
158
- milestoneId: z.ZodUUID;
158
+ milestoneId: z.ZodNullable<z.ZodUUID>;
159
159
  mode: z.ZodEnum<{
160
160
  supervised: "supervised";
161
161
  auto: "auto";
@@ -174,7 +174,7 @@ export declare const HandoffRecordSchema: z.ZodObject<{
174
174
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
175
175
  kind: z.ZodLiteral<"execution">;
176
176
  authorizationId: z.ZodUUID;
177
- milestoneId: z.ZodUUID;
177
+ milestoneId: z.ZodNullable<z.ZodUUID>;
178
178
  mode: z.ZodEnum<{
179
179
  supervised: "supervised";
180
180
  auto: "auto";
@@ -333,7 +333,7 @@ export declare const HandoffDispatchSchema: z.ZodObject<{
333
333
  plan: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
334
334
  kind: z.ZodLiteral<"execution">;
335
335
  authorizationId: z.ZodUUID;
336
- milestoneId: z.ZodUUID;
336
+ milestoneId: z.ZodNullable<z.ZodUUID>;
337
337
  mode: z.ZodEnum<{
338
338
  supervised: "supervised";
339
339
  auto: "auto";
@@ -352,7 +352,7 @@ export declare const HandoffDispatchSchema: z.ZodObject<{
352
352
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
353
353
  kind: z.ZodLiteral<"execution">;
354
354
  authorizationId: z.ZodUUID;
355
- milestoneId: z.ZodUUID;
355
+ milestoneId: z.ZodNullable<z.ZodUUID>;
356
356
  mode: z.ZodEnum<{
357
357
  supervised: "supervised";
358
358
  auto: "auto";
@@ -404,7 +404,7 @@ export declare const HandoffPageSchema: z.ZodObject<{
404
404
  scope: z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
405
405
  kind: z.ZodLiteral<"execution">;
406
406
  authorizationId: z.ZodUUID;
407
- milestoneId: z.ZodUUID;
407
+ milestoneId: z.ZodNullable<z.ZodUUID>;
408
408
  mode: z.ZodEnum<{
409
409
  supervised: "supervised";
410
410
  auto: "auto";
@@ -48,7 +48,7 @@ export declare const createPlanAdmission: (coordinationRoot: string, store: ISto
48
48
  scope: {
49
49
  kind: "execution";
50
50
  authorizationId: string;
51
- milestoneId: string;
51
+ milestoneId: string | null;
52
52
  mode: "supervised" | "auto";
53
53
  revision: {
54
54
  planDigest: string;
@@ -129,7 +129,7 @@ export declare const createPlanAdmission: (coordinationRoot: string, store: ISto
129
129
  scope: {
130
130
  kind: "execution";
131
131
  authorizationId: string;
132
- milestoneId: string;
132
+ milestoneId: string | null;
133
133
  mode: "supervised" | "auto";
134
134
  revision: {
135
135
  planDigest: string;
@@ -1,7 +1,7 @@
1
1
  import { Exception } from 'error-message-utils';
2
2
  import { getErrorKind } from '../errors/index.js';
3
3
  import { withHqLock } from '../locks/index.js';
4
- import { describePlan } from './authority.js';
4
+ import { canExecutePlanUnit, describePlan } from './authority.js';
5
5
  import { isSamePlanRevision } from './utilities.js';
6
6
  const conflict = () => {
7
7
  throw new Exception('The HQ action conflicts with its recorded state', undefined, {
@@ -29,10 +29,9 @@ export const createPlanAdmission = (coordinationRoot, store, runtimeEpoch, readP
29
29
  execution.revokedBy ||
30
30
  execution.action.id !== scope.authorizationId ||
31
31
  execution.mode !== scope.mode ||
32
- !execution.milestoneIds.includes(scope.milestoneId) ||
32
+ !canExecutePlanUnit(artifacts, scope.milestoneId) ||
33
33
  !isSamePlanRevision(execution.revision, scope.revision) ||
34
34
  !isSamePlanRevision(scope.revision, artifacts.revision) ||
35
- !status.isSequenceApproved ||
36
35
  status.state === 'blocked' ||
37
36
  (artifacts.coordination.revision && artifacts.coordination.revision.phase !== 'finished') ||
38
37
  artifacts.coordination.observedConflict)
@@ -112,6 +111,13 @@ export const createPlanAdmission = (coordinationRoot, store, runtimeEpoch, readP
112
111
  conflict();
113
112
  }
114
113
  }
114
+ // explicit assessment keeps its revision guard without inheriting implementation authority
115
+ const isFeedbackAssessment = !!action.expectedPlan &&
116
+ (command.kind === 'message' || command.kind === 'queue') &&
117
+ command.input.kind === 'skill' &&
118
+ prepared.skill?.name === 'jg-feedback';
119
+ // current-turn permission replies and labels do not start another implementation unit
120
+ const isSeparateNativeControl = command.kind === 'native-reply' || command.kind === 'thread-rename';
115
121
  if (action.plan) {
116
122
  if (!['message', 'queue', 'steer', 'thread-resume', 'thread-recover'].includes(command.kind) ||
117
123
  !threadId)
@@ -149,8 +155,22 @@ export const createPlanAdmission = (coordinationRoot, store, runtimeEpoch, readP
149
155
  }
150
156
  prepared.planContext = selected.context;
151
157
  }
158
+ else if (command.kind === 'queue-send' && queued?.planContext) {
159
+ const context = queued.planContext;
160
+ if (context.scope) {
161
+ const current = await scopeContext(context.scope);
162
+ if (!isSamePlanRevision(context.observedRevision, current.artifacts.revision) &&
163
+ context.scope.kind === 'execution')
164
+ conflict();
165
+ }
166
+ else
167
+ await boundArtifacts(context);
168
+ prepared.planContext = context;
169
+ }
152
170
  else if (binding && !safe) {
153
- if (command.kind === 'native-reply' && binding.scope?.kind === 'planning') {
171
+ if (binding.scope &&
172
+ !isFeedbackAssessment &&
173
+ !(binding.scope.kind === 'execution' && isSeparateNativeControl)) {
154
174
  prepared.planContext = (await scopeContext(binding.scope)).context;
155
175
  }
156
176
  else {
@@ -162,18 +182,6 @@ export const createPlanAdmission = (coordinationRoot, store, runtimeEpoch, readP
162
182
  };
163
183
  }
164
184
  }
165
- if (command.kind === 'queue-send' && queued?.planContext) {
166
- const context = queued.planContext;
167
- if (context.scope) {
168
- const current = await scopeContext(context.scope);
169
- if (!isSamePlanRevision(context.observedRevision, current.artifacts.revision) &&
170
- context.scope.kind === 'execution')
171
- conflict();
172
- }
173
- else
174
- await boundArtifacts(context);
175
- prepared.planContext = context;
176
- }
177
185
  return store.admit({ action, prepared });
178
186
  });
179
187
  },
@@ -2,6 +2,12 @@ import type { IPlanCommand, IPlanStatus, IPlanCoordination } from '../contracts/
2
2
  import type { IPlanArtifacts } from './types.js';
3
3
  /** Derives approval independently from native sessions and native permission requests. */
4
4
  export declare const describePlan: (artifacts: IPlanArtifacts, pendingActionId?: string | null) => IPlanStatus;
5
+ /**
6
+ * Checks the current approved unfinished unit, with null identifying an undivided plan.
7
+ * Runtime epoch, action identity and mode remain the caller's separate admission checks.
8
+ * @returns Whether the exact unit is selected by current execution authority.
9
+ */
10
+ export declare const canExecutePlanUnit: (artifacts: IPlanArtifacts, milestoneId: string | null) => boolean;
5
11
  /**
6
12
  * Applies one explicit operator decision without native dispatch or filesystem mutation.
7
13
  * @returns Updated current authority records.
@@ -12,9 +12,7 @@ export const describePlan = (artifacts, pendingActionId = null) => {
12
12
  const isPlanApproved = !!coordination.planApproval &&
13
13
  !coordination.planApproval.revokedBy &&
14
14
  coordination.planApproval.revision.planDigest === revision.planDigest;
15
- const isFinalized = !!coordination.finalized &&
16
- revision.breakdownDigest !== null &&
17
- isSamePlanRevision(coordination.finalized.revision, revision);
15
+ const isFinalized = !!coordination.finalized && isSamePlanRevision(coordination.finalized.revision, revision);
18
16
  const isSequenceApproved = isPlanApproved &&
19
17
  isFinalized &&
20
18
  !!coordination.sequenceApproval &&
@@ -22,6 +20,12 @@ export const describePlan = (artifacts, pendingActionId = null) => {
22
20
  isSamePlanRevision(coordination.sequenceApproval.revision, revision);
23
21
  const verified = createCompletionLookup(coordination.completions, coordination.correspondences);
24
22
  const workflow = coordination.revision;
23
+ const invalidated = new Set(coordination.correspondences.flatMap((record) => record.invalidatedReceiptIds));
24
+ const isWholePlanComplete = artifacts.milestones === null &&
25
+ coordination.completions.some((receipt) => receipt.milestoneId === null &&
26
+ receipt.contractDigest === revision.planDigest &&
27
+ receipt.revision.breakdownDigest === null &&
28
+ !invalidated.has(receipt.id));
25
29
  const state = coordination.observedConflict ||
26
30
  pendingActionId ||
27
31
  workflow?.phase === 'blocked' ||
@@ -38,10 +42,11 @@ export const describePlan = (artifacts, pendingActionId = null) => {
38
42
  ? 'plan-approval-required'
39
43
  : !isFinalized
40
44
  ? 'breakdown-required'
41
- : !isSequenceApproved
45
+ : artifacts.milestones !== null && !isSequenceApproved
42
46
  ? 'sequence-approval-required'
43
- : artifacts.parsed.length > 0 &&
44
- artifacts.parsed.every((milestone) => milestone.status === 'done' && verified(milestone))
47
+ : isWholePlanComplete ||
48
+ (artifacts.parsed.length > 0 &&
49
+ artifacts.parsed.every((milestone) => milestone.status === 'done' && verified(milestone)))
45
50
  ? 'completed'
46
51
  : artifacts.parsed.some((milestone) => milestone.status === 'in progress')
47
52
  ? 'in-progress'
@@ -89,6 +94,26 @@ export const describePlan = (artifacts, pendingActionId = null) => {
89
94
  },
90
95
  };
91
96
  };
97
+ /**
98
+ * Checks the current approved unfinished unit, with null identifying an undivided plan.
99
+ * Runtime epoch, action identity and mode remain the caller's separate admission checks.
100
+ * @returns Whether the exact unit is selected by current execution authority.
101
+ */
102
+ export const canExecutePlanUnit = (artifacts, milestoneId) => {
103
+ const status = describePlan(artifacts);
104
+ const execution = artifacts.coordination.execution;
105
+ if (!execution ||
106
+ !status.isPlanApproved ||
107
+ !status.isFinalized ||
108
+ ['blocked', 'completed', 'revising'].includes(status.state))
109
+ return false;
110
+ return artifacts.milestones === null
111
+ ? milestoneId === null && execution.milestoneIds.length === 0
112
+ : status.isSequenceApproved &&
113
+ milestoneId !== null &&
114
+ execution.milestoneIds.includes(milestoneId) &&
115
+ artifacts.parsed.some((milestone) => milestone.id === milestoneId && milestone.status !== 'done');
116
+ };
92
117
  /** Revocation records operator provenance without granting any replacement authority. */
93
118
  const revokeExecution = (coordination, action) => {
94
119
  if (coordination.execution)
@@ -104,7 +129,8 @@ export const updatePlanAuthority = (artifacts, command, runtimeEpoch) => {
104
129
  const coordination = structuredClone(artifacts.coordination);
105
130
  if (command.kind === 'approve') {
106
131
  const status = describePlan(artifacts);
107
- if (command.scope === 'sequence' && (!status.isFinalized || !status.isPlanApproved))
132
+ if (command.scope === 'sequence' &&
133
+ (artifacts.milestones === null || !status.isFinalized || !status.isPlanApproved))
108
134
  conflict();
109
135
  const presentation = command.scope === 'plan' ? artifacts.hashes.plan : artifacts.hashes.milestones;
110
136
  if (presentation !== command.presentationHash)
@@ -139,7 +165,12 @@ export const updatePlanAuthority = (artifacts, command, runtimeEpoch) => {
139
165
  coordination.revision.phase !== 'finished')
140
166
  conflict();
141
167
  if (status.state === 'blocked' ||
142
- !status.isSequenceApproved ||
168
+ status.state === 'completed' ||
169
+ !status.isPlanApproved ||
170
+ !status.isFinalized ||
171
+ (artifacts.milestones === null
172
+ ? command.milestoneIds.length !== 0
173
+ : !status.isSequenceApproved || command.milestoneIds.length === 0) ||
143
174
  command.milestoneIds.some((id) => !artifacts.parsed.some((milestone) => milestone.id === id && milestone.status !== 'done')))
144
175
  conflict();
145
176
  if (coordination.revision)
@@ -8,6 +8,6 @@ import type { IPlanArtifacts } from './types.js';
8
8
  * - -1: The HQ plan is invalid
9
9
  */
10
10
  export declare const finalizeInitialSequence: (artifacts: IPlanArtifacts) => {
11
- content: string;
11
+ content: string | null;
12
12
  revision: IPlanRevision;
13
13
  };
@@ -14,10 +14,11 @@ const conflict = () => {
14
14
  * - -1: The HQ plan is invalid
15
15
  */
16
16
  export const finalizeInitialSequence = (artifacts) => {
17
- if (artifacts.milestones === null ||
18
- (artifacts.coordination.finalized &&
19
- !isSamePlanRevision(artifacts.coordination.finalized.revision, artifacts.revision)))
17
+ if (artifacts.coordination.finalized &&
18
+ !isSamePlanRevision(artifacts.coordination.finalized.revision, artifacts.revision))
20
19
  conflict();
20
+ if (artifacts.milestones === null)
21
+ return { content: null, revision: artifacts.revision };
21
22
  let milestones = artifacts.milestones.replace(/\r\n?/g, '\n');
22
23
  // insertion offsets are applied backwards so original positions stay valid
23
24
  for (const milestone of [...artifacts.parsed].reverse())
@@ -116,7 +116,7 @@ export declare const createPlans: (coordinationRoot: string, roots: string[], st
116
116
  * - -1: HQ lock ownership changed before release
117
117
  */
118
118
  checkpoint(target: IPlanCommand["target"], revisionId: string, phaseActionId: string): Promise<void>;
119
- admitNative(action: import("../contracts/index.js").IActionEnvelope, prepared: import("../store/control/types.js").IAdmission["prepared"]): Promise<{
119
+ admitNative(action: import("../contracts/index.js").IActionEnvelope, prepared: import("../store/control/types.ts").IAdmission["prepared"]): Promise<{
120
120
  receipt: {
121
121
  id: string;
122
122
  digest: string;
@@ -134,7 +134,7 @@ export declare const createPlans: (coordinationRoot: string, roots: string[], st
134
134
  scope: {
135
135
  kind: "execution";
136
136
  authorizationId: string;
137
- milestoneId: string;
137
+ milestoneId: string | null;
138
138
  mode: "supervised" | "auto";
139
139
  revision: {
140
140
  planDigest: string;
@@ -192,7 +192,7 @@ export declare const createPlans: (coordinationRoot: string, roots: string[], st
192
192
  scope: {
193
193
  kind: "execution";
194
194
  authorizationId: string;
195
- milestoneId: string;
195
+ milestoneId: string | null;
196
196
  mode: "supervised" | "auto";
197
197
  revision: {
198
198
  planDigest: string;
@@ -4,7 +4,7 @@ import { PlanMilestoneSchema, } from '../contracts/index.js';
4
4
  import { getErrorKind } from '../errors/index.js';
5
5
  import { withHqLock } from '../locks/index.js';
6
6
  import { resolveWorkspaceTarget } from '../runtime/state/index.js';
7
- import { describePlan, updatePlanAuthority } from './authority.js';
7
+ import { canExecutePlanUnit, describePlan, updatePlanAuthority } from './authority.js';
8
8
  import { createPlanAdmission } from './admission.js';
9
9
  import { readPlanPage } from './projections.js';
10
10
  import { finalizeInitialSequence } from './finalization.js';
@@ -340,16 +340,14 @@ export const createPlans = (coordinationRoot, roots, store, runtimeEpoch, parseC
340
340
  const execution = artifacts.coordination.execution;
341
341
  if (pendingActionId ||
342
342
  status.state === 'blocked' ||
343
- !status.isSequenceApproved ||
344
343
  !execution ||
345
344
  execution.runtimeEpoch !== runtimeEpoch ||
346
345
  execution.revokedBy ||
347
346
  execution.action.id !== command.authorizationId ||
348
347
  execution.mode !== command.mode ||
349
- !execution.milestoneIds.includes(command.milestoneId) ||
348
+ !canExecutePlanUnit(artifacts, command.milestoneId) ||
350
349
  !isSamePlanRevision(command.expected, artifacts.revision) ||
351
- !isSamePlanRevision(execution.revision, artifacts.revision) ||
352
- !artifacts.parsed.some((milestone) => milestone.id === command.milestoneId && milestone.status !== 'done'))
350
+ !isSamePlanRevision(execution.revision, artifacts.revision))
353
351
  conflict();
354
352
  return {
355
353
  kind: 'execution-check',
@@ -367,9 +365,7 @@ export const createPlans = (coordinationRoot, roots, store, runtimeEpoch, parseC
367
365
  await apply(previous);
368
366
  artifacts = await readPlanArtifacts(command.target, roots, parseContract);
369
367
  const current = describeCurrent(artifacts, await store.getPendingPlanOperationId(artifacts.directory));
370
- return command.kind === 'finalize' &&
371
- current.isFinalized &&
372
- artifacts.milestones !== null
368
+ return command.kind === 'finalize' && current.isFinalized
373
369
  ? { kind: 'finalized', result: current, content: artifacts.milestones }
374
370
  : { kind: 'status', result: current };
375
371
  }
@@ -449,7 +445,7 @@ export const createPlans = (coordinationRoot, roots, store, runtimeEpoch, parseC
449
445
  conflict();
450
446
  if ((await store.getPlanThreads(artifacts.directory)).length)
451
447
  conflict();
452
- if (!workflow.checkpoint?.isQuiescent || artifacts.milestones === null)
448
+ if (!workflow.checkpoint?.isQuiescent)
453
449
  conflict();
454
450
  const proposal = workflow.proposal ?? proposeReconciliation(artifacts, command.action);
455
451
  if (proposal.inspectionHash !== artifacts.hashes.milestones ||
@@ -475,7 +471,9 @@ export const createPlans = (coordinationRoot, roots, store, runtimeEpoch, parseC
475
471
  }
476
472
  else if (command.confirmation)
477
473
  conflict();
478
- const content = renderReconciledSequence(artifacts.milestones, drafts);
474
+ const content = artifacts.milestones === null
475
+ ? null
476
+ : renderReconciledSequence(artifacts.milestones, drafts);
479
477
  const revision = computePlanRevision({
480
478
  ...artifacts.contract,
481
479
  milestones: content,
@@ -498,7 +496,7 @@ export const createPlans = (coordinationRoot, roots, store, runtimeEpoch, parseC
498
496
  coordination.finalized = {
499
497
  action: command.action,
500
498
  revision: finalized.revision,
501
- fileHash: hashPlanContent(milestones),
499
+ fileHash: milestones === null ? null : hashPlanContent(milestones),
502
500
  createdAt: Date.now(),
503
501
  };
504
502
  coordination.baseline = refreshPlanBaseline(artifacts, milestones, finalized.revision);