@brainervirus/workit-core 5.0.0 → 6.0.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.
@@ -10,7 +10,6 @@ export const OPERATION_FAMILIES = [
10
10
  "finding",
11
11
  "decision",
12
12
  "worker",
13
- "writer",
14
13
  "state",
15
14
  ] as const;
16
15
  export type OperationFamily = (typeof OPERATION_FAMILIES)[number];
@@ -145,19 +144,6 @@ export const refSchema = z.discriminatedUnion("kind", [
145
144
  .strict(),
146
145
  z.object({ kind: z.literal("host"), host: hostSchema, handle: nonEmpty }).strict(),
147
146
  z.object({ kind: z.literal("external"), url: text.url() }).strict(),
148
- // Standing auto-approval receipt: authorizes without a live question while
149
- // the referenced workspace rule covers the operation class. Verified live
150
- // at reserve time against current config; dropped on export/import (a rule
151
- // from another machine must never authorize here). Scalar-only shape keeps
152
- // advertised operation schemas within provider depth limits.
153
- z
154
- .object({
155
- kind: z.literal("standing"),
156
- workspace: nonEmpty,
157
- class: nonEmpty,
158
- configDigest: nullableDigest,
159
- })
160
- .strict(),
161
147
  ]);
162
148
  export type Ref = z.infer<typeof refSchema>;
163
149
 
@@ -274,7 +260,6 @@ export const provenanceSchema = z
274
260
  host: hostSchema,
275
261
  session: refSchema.nullable(),
276
262
  workerId: nullableId,
277
- receipts: z.array(refSchema),
278
263
  })
279
264
  .strict();
280
265
  export type Provenance = z.infer<typeof provenanceSchema>;
@@ -622,6 +607,13 @@ export const evidenceEvaluationSchema = z
622
607
  })
623
608
  .strict();
624
609
  export type EvidenceEvaluation = z.infer<typeof evidenceEvaluationSchema>;
610
+ /**
611
+ * A durable decision record (D2, D18): agent-asserted like every other
612
+ * recording. It satisfies `decisions` requirements and accepted limitations;
613
+ * it never authorizes an external effect — autonomy grants and the host's
614
+ * own permission prompt do that. Legacy keys (`approvedContent`, `displayed`,
615
+ * `standing`, `consumption`) are dropped on read (D17).
616
+ */
625
617
  export const decisionSchema = z
626
618
  .object({
627
619
  purpose: z.enum(["design", "action", "limitation", "preference"]),
@@ -631,53 +623,18 @@ export const decisionSchema = z
631
623
  workspaceId: id,
632
624
  scope: scopeSchema,
633
625
  presented: text,
634
- approvedContent: text,
635
- displayed: text.optional(),
636
626
  contentRefs: z.array(refSchema),
637
627
  statedChoice: z.object({ ref: text, text: text }).strict().optional(),
638
- standing: z.object({ workspace: nonEmpty, class: nonEmpty }).strict().optional(),
639
628
  })
640
629
  .strict(),
641
630
  digest,
642
631
  response: z.enum(["approved", "rejected", "stated"]),
643
632
  requirementIds: z.array(digest),
644
633
  revoked: z.object({ at: utc, reason: text }).strict().nullable(),
645
- consumption: z
646
- .object({
647
- state: z.enum(["reserved", "consumed", "uncertain"]),
648
- at: utc,
649
- actionRef: refSchema,
650
- /** Historical identifier only; never interpreted as native authority. */
651
- historicalActionId: text.optional(),
652
- })
653
- .strict()
654
- .nullable(),
655
634
  })
656
635
  .strict();
657
636
  export type Decision = z.infer<typeof decisionSchema>;
658
637
 
659
- /** Show-before-ask guard: binding questions are single-sentence and never
660
- * carry the artifact, descriptor, or payload body in the question UI. */
661
- export const BINDING_QUESTION_BUDGET = 300;
662
- const bindingQuestionHeader = /^Workit decision: (design|action|limitation|preference)$/;
663
- export const workitBindingQuestionIssue = (questions: unknown): string | null => {
664
- if (!Array.isArray(questions) || questions.length !== 1) return null;
665
- const question = questions[0] as { header?: unknown; question?: unknown; options?: unknown };
666
- if (!question || typeof question !== "object") return null;
667
- if (typeof question.header !== "string" || !bindingQuestionHeader.test(question.header.trim()))
668
- return null;
669
- const over = (label: string, value: string) =>
670
- `invalid_input: ${label} is ${value.length} characters; Workit binding questions must stay within ${BINDING_QUESTION_BUDGET}. present the item in the conversation first, then ask a short scoped question.`;
671
- if (typeof question.question === "string" && question.question.length > BINDING_QUESTION_BUDGET)
672
- return over("the question text", question.question);
673
- if (Array.isArray(question.options))
674
- for (const option of question.options) {
675
- const description = (option as { description?: unknown }).description;
676
- if (typeof description === "string" && description.length > BINDING_QUESTION_BUDGET)
677
- return over("an option description", description);
678
- }
679
- return null;
680
- };
681
638
  export const findingSchema = z
682
639
  .object({
683
640
  claim: text,
@@ -724,14 +681,6 @@ export const workerSchema = z
724
681
  })
725
682
  .strict();
726
683
  export type Worker = z.infer<typeof workerSchema>;
727
- export const ownerSchema = z
728
- .object({
729
- taskId: id,
730
- workerId: nullableId,
731
- session: z.object({ kind: z.literal("host"), host: hostSchema, handle: nonEmpty }).strict(),
732
- })
733
- .strict();
734
- export type Owner = z.infer<typeof ownerSchema>;
735
684
  export const closureSchema = z
736
685
  .object({
737
686
  outcome: outcomeSchema,
@@ -742,37 +691,6 @@ export const closureSchema = z
742
691
  })
743
692
  .strict();
744
693
  export type Closure = z.infer<typeof closureSchema>;
745
- export const actionProgressSchema = z
746
- .object({
747
- decisionId: id,
748
- steps: z.array(nonEmpty),
749
- completedSteps: z.array(nonEmpty),
750
- })
751
- .strict()
752
- .check((ctx) => {
753
- const { steps, completedSteps } = ctx.value;
754
- const valid =
755
- new Set(steps).size === steps.length &&
756
- new Set(completedSteps).size === completedSteps.length &&
757
- completedSteps.every((step, index) => steps[index] === step);
758
- if (!valid)
759
- ctx.issues.push({
760
- code: "custom",
761
- input: ctx.value,
762
- message: "completed action steps must be a unique prefix of approved steps",
763
- path: ["completedSteps"],
764
- });
765
- });
766
- export type ActionProgress = z.infer<typeof actionProgressSchema>;
767
- export const actionProgressListSchema = z.array(actionProgressSchema).check((ctx) => {
768
- if (new Set(ctx.value.map((progress) => progress.decisionId)).size !== ctx.value.length)
769
- ctx.issues.push({
770
- code: "custom",
771
- input: ctx.value,
772
- message: "action progress decision ids must be unique",
773
- path: ["decisionId"],
774
- });
775
- });
776
694
  export const runtimeSchema = z
777
695
  .object({
778
696
  createdWith: text.nullable(),
@@ -802,7 +720,6 @@ export const taskRecordSchema = z
802
720
  candidates: z.array(candidateSchema),
803
721
  evidence: z.array(entrySchema(evidenceSchema)),
804
722
  decisions: z.array(entrySchema(decisionSchema)),
805
- actionProgress: actionProgressListSchema.optional(),
806
723
  findings: z.array(entrySchema(findingSchema)),
807
724
  workers: z.array(entrySchema(workerSchema)),
808
725
  /** Paths a reader must understand; see parseStoredRecord. */
@@ -917,10 +834,6 @@ export const workspaceRecordSchema = z
917
834
  revision,
918
835
  root: nonEmpty,
919
836
  runtime: runtimeSchema.optional(),
920
- writer: z
921
- .object({ state: z.enum(["held", "uncertain"]), owner: ownerSchema, acquiredAt: utc })
922
- .strict()
923
- .nullable(),
924
837
  /** Paths a reader must understand; see parseStoredRecord. */
925
838
  critical: z.array(nonEmpty).optional(),
926
839
  })
@@ -970,7 +883,6 @@ export const taskSummarySchema = z
970
883
  progress: progressSchema,
971
884
  policy: policySchema.nullable(),
972
885
  requirements: z.array(requirementEvaluationSchema),
973
- writer: workspaceRecordSchema.shape.writer,
974
886
  })
975
887
  .strict();
976
888
  export type TaskSummary = z.infer<typeof taskSummarySchema>;
@@ -1046,7 +958,6 @@ const taskOperations = {
1046
958
  ...taskId,
1047
959
  ...revisions,
1048
960
  expectedWorkspaceRevision: revision.optional(),
1049
- authorityRefs: z.array(refSchema).optional(),
1050
961
  }),
1051
962
  close: operation({
1052
963
  action: z.literal("close"),
@@ -1141,30 +1052,12 @@ const workerOperations = {
1141
1052
  reason: text,
1142
1053
  }),
1143
1054
  };
1144
- const writerOperations = {
1145
- acquire: operation({
1146
- action: z.literal("acquire"),
1147
- ...taskId,
1148
- expectedRevision: revision.optional(),
1149
- expectedWorkspaceRevision: revision.optional(),
1150
- workerId: nullableId.optional(),
1151
- reason: text.optional(),
1152
- }),
1153
- release: operation({
1154
- action: z.literal("release"),
1155
- ...taskId,
1156
- expectedRevision: revision.optional(),
1157
- expectedWorkspaceRevision: revision.optional(),
1158
- reason: text.optional(),
1159
- }),
1160
- };
1161
1055
  const stateOperations = {
1162
1056
  export: operation({ action: z.literal("export"), ...taskId }),
1163
1057
  import: operation({
1164
1058
  action: z.literal("import"),
1165
1059
  expectedWorkspaceRevision: revision.nullable().optional(),
1166
1060
  bundle: exportBundleSchema,
1167
- authorityRefs: z.array(refSchema),
1168
1061
  }),
1169
1062
  };
1170
1063
 
@@ -1175,7 +1068,6 @@ export const operationSchemas = {
1175
1068
  finding: z.discriminatedUnion("action", Object.values(findingOperations) as any),
1176
1069
  decision: z.discriminatedUnion("action", Object.values(decisionOperations) as any),
1177
1070
  worker: z.discriminatedUnion("action", Object.values(workerOperations) as any),
1178
- writer: z.discriminatedUnion("action", Object.values(writerOperations) as any),
1179
1071
  state: z.discriminatedUnion("action", Object.values(stateOperations) as any),
1180
1072
  } as const;
1181
1073
  export type OperationRequest = z.infer<(typeof operationSchemas)[OperationFamily]>;
@@ -1198,7 +1090,6 @@ export const advertisedOperationSchemas = {
1198
1090
  finding: advertised(findingOperations),
1199
1091
  decision: advertised(decisionOperations),
1200
1092
  worker: advertised(workerOperations),
1201
- writer: advertised(writerOperations),
1202
1093
  state: advertised(stateOperations),
1203
1094
  } as const;
1204
1095
  export type TaskStartRequest = z.infer<typeof taskOperations.start>;
@@ -1222,7 +1113,6 @@ export type ErrorCode =
1222
1113
  | "permission_denied"
1223
1114
  | "capability_unavailable"
1224
1115
  | "requirements_unsatisfied"
1225
- | "writer_conflict"
1226
1116
  /** Retryable: another live Workit call holds the checkout's metadata lock. */
1227
1117
  | "busy"
1228
1118
  | "recovery_required"
@@ -1237,16 +1127,9 @@ export type ErrorDetails = {
1237
1127
  actualWorkspaceRevision?: Revision | null;
1238
1128
  requirementIds?: Digest[];
1239
1129
  capability?: string;
1240
- owner?: Owner;
1241
1130
  path?: string;
1242
1131
  operation?: string;
1243
1132
  outcome?: "not_started" | "pending" | "unknown";
1244
- /** Present when a native approval must be asked from a concise proposal. */
1245
- proposal?: {
1246
- presented: string;
1247
- approvedContent: string;
1248
- descriptorDigest: string;
1249
- };
1250
1133
  guidance?: string;
1251
1134
  /** Structured remedy for unsatisfied requirements: rule, reason, and
1252
1135
  * satisfaction text instead of opaque requirement hashes alone. */
@@ -1505,12 +1388,7 @@ const compareNullableText = (left: string | null, right: string | null): number
1505
1388
  const compareBooleanNullable = (left: boolean | null, right: boolean | null): number =>
1506
1389
  left === right ? 0 : left === null ? -1 : right === null ? 1 : Number(left) - Number(right);
1507
1390
  export function decisionDigest(input: Omit<Decision, "digest"> | Decision): Digest {
1508
- const {
1509
- digest: _ignored,
1510
- revoked: _revoked,
1511
- consumption: _consumption,
1512
- ...value
1513
- } = input as Decision;
1391
+ const { digest: _ignored, revoked: _revoked, ...value } = input as Decision;
1514
1392
  return sha256(value);
1515
1393
  }
1516
1394
  export function candidateDigest(input: Candidate): Digest {