@productbrain/mcp 0.0.1-beta.3346 → 0.0.1-beta.3359

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.
@@ -46,7 +46,7 @@ import {
46
46
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
47
47
 
48
48
  // src/tools/entries.ts
49
- import { z as z6 } from "zod/v3";
49
+ import { z as z8 } from "zod/v3";
50
50
 
51
51
  // src/envelope.ts
52
52
  import { z } from "zod/v3";
@@ -540,10 +540,10 @@ async function dispatchDiscriminated(toolName, union2, flatData, actionSpecs, ha
540
540
  }
541
541
 
542
542
  // src/tools/knowledge.ts
543
- import { z as z3 } from "zod/v3";
543
+ import { z as z5 } from "zod/v3";
544
544
 
545
545
  // src/tools/smart-capture.ts
546
- import { z as z2 } from "zod/v3";
546
+ import { z as z4 } from "zod/v3";
547
547
 
548
548
  // src/lib/scopedCache.ts
549
549
  var ScopedCache = class {
@@ -637,115 +637,809 @@ function coherencyRefusedResult(toolName, entryId, refusal, options) {
637
637
  if (lines.length === beforeRoutes) {
638
638
  lines.push(GENERIC_RECOVERY_LINE);
639
639
  }
640
- } else {
641
- lines.push("", GENERIC_RECOVERY_LINE);
640
+ } else {
641
+ lines.push("", GENERIC_RECOVERY_LINE);
642
+ }
643
+ return failureResult(
644
+ lines.join("\n"),
645
+ "COHERENCY_REFUSED",
646
+ `Coherency gate refused ${toolName} on ${entryId}.`,
647
+ "Use one of the refusal's routes (link / coherencyAcknowledgement / steeringOverrideReason), then retry.",
648
+ void 0,
649
+ { entryId, refusal }
650
+ );
651
+ }
652
+
653
+ // src/lib/resolveCollection.ts
654
+ async function resolveCollection(params) {
655
+ const { name, description, typeHint, allowReviewRouting } = params;
656
+ const sessionId = getAgentSessionId();
657
+ const result2 = await kernelCall("chain.resolveCollection", {
658
+ entryName: name,
659
+ entryDescription: description,
660
+ ...typeHint ? { typeHint } : {},
661
+ ...allowReviewRouting ? { allowReviewRouting } : {},
662
+ ...sessionId ? { agentSessionId: sessionId } : {}
663
+ });
664
+ return result2 ?? null;
665
+ }
666
+
667
+ // src/lib/fieldTypes.ts
668
+ var FIELD_TYPE_DEFAULTS = {
669
+ "string": "",
670
+ "text": "",
671
+ "rich-text": "",
672
+ "number": null,
673
+ "boolean": false,
674
+ "select": null,
675
+ "multi-select": [],
676
+ "array": [],
677
+ "json": null,
678
+ "date": null,
679
+ "person": null
680
+ };
681
+
682
+ // src/lib/formatFieldGuidance.ts
683
+ function formatFieldGuidance(fields) {
684
+ const guidedFields = fields.filter((f) => f.writingGuidance);
685
+ if (guidedFields.length === 0) return "";
686
+ const lines = ["## Writing Guidance"];
687
+ for (const field of guidedFields) {
688
+ const displayName = field.label || field.key;
689
+ lines.push(`- ${displayName}: ${field.writingGuidance}`);
690
+ if (field.writingExamples && field.writingExamples.length > 0) {
691
+ lines.push(` Examples: ${field.writingExamples.join(" | ")}`);
692
+ }
693
+ }
694
+ return lines.join("\n");
695
+ }
696
+
697
+ // src/lib/inferSourceDate.ts
698
+ function inferSourceDate(...values) {
699
+ const combined = values.filter((value) => typeof value === "string" && value.trim().length > 0).join("\n");
700
+ if (!combined) return void 0;
701
+ const isoMatch = combined.match(/\b(20\d{2}-\d{2}-\d{2})\b/);
702
+ if (isoMatch) return isoMatch[1];
703
+ const monthMatch = combined.match(
704
+ /\b(january|february|march|april|may|june|july|august|september|october|november|december)\s+(\d{1,2})(?:st|nd|rd|th)?(?:,?\s+(20\d{2}))?\b/i
705
+ );
706
+ if (!monthMatch) return void 0;
707
+ const monthIndex = [
708
+ "january",
709
+ "february",
710
+ "march",
711
+ "april",
712
+ "may",
713
+ "june",
714
+ "july",
715
+ "august",
716
+ "september",
717
+ "october",
718
+ "november",
719
+ "december"
720
+ ].indexOf(monthMatch[1].toLowerCase());
721
+ if (monthIndex < 0) return void 0;
722
+ const inferredYear = monthMatch[3] ?? combined.match(/\b(20\d{2})\b/)?.[1] ?? String((/* @__PURE__ */ new Date()).getUTCFullYear());
723
+ const month = String(monthIndex + 1).padStart(2, "0");
724
+ const day = monthMatch[2].padStart(2, "0");
725
+ return `${inferredYear}-${month}-${day}`;
726
+ }
727
+
728
+ // src/lib/collectionCache.ts
729
+ var collectionCache = new ScopedCache(COLLECTION_CACHE_TTL_MS);
730
+ async function getCollections() {
731
+ const scope = cacheScope();
732
+ const hit = collectionCache.get(scope);
733
+ if (hit) return hit.collections;
734
+ const result2 = await kernelQuery("chain.listCollections") ?? [];
735
+ const bySlug = new Map(result2.map((c) => [c.slug, c]));
736
+ collectionCache.set(scope, { collections: result2, bySlug });
737
+ return result2;
738
+ }
739
+ async function getCollectionBySlug(slug) {
740
+ await getCollections();
741
+ return collectionCache.get(cacheScope())?.bySlug.get(slug);
742
+ }
743
+ function invalidateCollectionCacheForScope() {
744
+ collectionCache.delete(cacheScope());
745
+ }
746
+ async function isGoverned(slug) {
747
+ const col = await getCollectionBySlug(slug);
748
+ return !!col?.governed;
749
+ }
750
+
751
+ // src/lib/textMatch.ts
752
+ var STOP_WORDS = /* @__PURE__ */ new Set([
753
+ "the",
754
+ "and",
755
+ "for",
756
+ "are",
757
+ "but",
758
+ "not",
759
+ "you",
760
+ "all",
761
+ "can",
762
+ "has",
763
+ "her",
764
+ "was",
765
+ "one",
766
+ "our",
767
+ "out",
768
+ "day",
769
+ "had",
770
+ "hot",
771
+ "how",
772
+ "its",
773
+ "may",
774
+ "new",
775
+ "now",
776
+ "old",
777
+ "see",
778
+ "way",
779
+ "who",
780
+ "did",
781
+ "get",
782
+ "let",
783
+ "say",
784
+ "she",
785
+ "too",
786
+ "use",
787
+ "from",
788
+ "have",
789
+ "been",
790
+ "each",
791
+ "that",
792
+ "this",
793
+ "with",
794
+ "will",
795
+ "they",
796
+ "what",
797
+ "when",
798
+ "make",
799
+ "like",
800
+ "long",
801
+ "look",
802
+ "many",
803
+ "some",
804
+ "them",
805
+ "than",
806
+ "most",
807
+ "only",
808
+ "over",
809
+ "such",
810
+ "into",
811
+ "also",
812
+ "back",
813
+ "just",
814
+ "much",
815
+ "must",
816
+ "name",
817
+ "very",
818
+ "your",
819
+ "after",
820
+ "which",
821
+ "their",
822
+ "about",
823
+ "would",
824
+ "there",
825
+ "should",
826
+ "could",
827
+ "other",
828
+ "these",
829
+ "first",
830
+ "being",
831
+ "those",
832
+ "still",
833
+ "where"
834
+ ]);
835
+ function tokenizeText(input) {
836
+ return input.toLowerCase().replace(/[^\p{L}\p{N}\s]+/gu, " ").split(/\s+/).filter(Boolean);
837
+ }
838
+
839
+ // src/lib/batchCaptureOutput.ts
840
+ import { z as z2 } from "zod/v3";
841
+ var batchCaptureRealOutputSchema = z2.object({
842
+ captured: z2.array(z2.object({
843
+ entryId: z2.string(),
844
+ collection: z2.string(),
845
+ name: z2.string(),
846
+ // "draft_on_failure" is the status emitted when an auto-commit is REFUSED/failed (the entry
847
+ // stays a draft) — the same path that now also emits coherencyRefusal. The strict schema must
848
+ // accept it or a refused response fails to validate on `status` (codex review, completing the
849
+ // coherencyRefusal contract fix).
850
+ status: z2.enum(["draft", "committed", "proposed", "draft_on_failure"]),
851
+ classifiedBy: z2.enum(["llm", "heuristic", "explicit"]).optional(),
852
+ confidence: z2.number().optional(),
853
+ confidenceTier: z2.enum(["high", "medium", "low"]).optional(),
854
+ warnings: z2.array(z2.string()).optional(),
855
+ normalization: z2.object({
856
+ remapped: z2.record(z2.string()).optional(),
857
+ rejected: z2.array(z2.string()).optional()
858
+ }).optional(),
859
+ // TEN-2365: capture-time authority-domain proposal slug (PENDING ratification), when filed.
860
+ domain: z2.string().optional(),
861
+ // WP-465 surface parity: structured coherency refusal for a gate-refused auto-commit (batch
862
+ // shape). Loose record — same single-source rationale as captureSuccessOutputSchema.
863
+ coherencyRefusal: z2.record(z2.unknown()).optional(),
864
+ // WP-485 Slice 2b round 4 (Codex P2, FEAT-1370): per-entry contradiction advisory, emitted
865
+ // into structuredContent but previously undeclared here. Not `.strict()` so this one was
866
+ // silently stripped rather than rejected — declared anyway so batch consumers actually see it.
867
+ contradictionAdvisory: z2.record(z2.unknown()).optional()
868
+ })),
869
+ total: z2.number(),
870
+ failed: z2.number(),
871
+ committed: z2.number(),
872
+ proposed: z2.number(),
873
+ drafts: z2.number(),
874
+ classified: z2.number().optional(),
875
+ autoCommitApplied: z2.boolean(),
876
+ skippedLowConfidence: z2.array(z2.object({
877
+ index: z2.number(),
878
+ name: z2.string(),
879
+ suggestedCollection: z2.string().optional(),
880
+ confidence: z2.number().optional(),
881
+ alternatives: z2.array(z2.object({
882
+ collection: z2.string(),
883
+ confidence: z2.number()
884
+ })).optional()
885
+ })).optional(),
886
+ failedEntries: z2.array(z2.object({
887
+ index: z2.number(),
888
+ collection: z2.string(),
889
+ name: z2.string(),
890
+ error: z2.string()
891
+ })).optional()
892
+ });
893
+ var batchCapturePreviewOutputSchema = z2.object({
894
+ outcome: z2.literal("preview"),
895
+ wouldCapture: z2.array(z2.object({
896
+ // Fix 1 (WP-577 review re-review, TEN-2918 follow-up): optional, not required — see
897
+ // WouldCaptureEntry's doc comment. Absent exactly when `entryIdAssignedAtCapture` is true.
898
+ entryId: z2.string().optional(),
899
+ entryIdAssignedAtCapture: z2.literal(true).optional(),
900
+ collection: z2.string(),
901
+ name: z2.string(),
902
+ classifiedBy: z2.string().optional(),
903
+ confidence: z2.number().optional(),
904
+ warnings: z2.array(z2.string()).optional()
905
+ })),
906
+ // WP-577 review follow-up (P2, TEN-2918): entries the server's WHY/glossary gate says would
907
+ // be BLOCKED on a real (non-preview) create — a distinct cohort from `wouldCapture` so the
908
+ // structured response never claims a governance-refused capture would succeed. Optional/
909
+ // additive: absent (or empty) on every response this route produced before this fix.
910
+ wouldBlock: z2.array(z2.object({
911
+ entryId: z2.string().optional(),
912
+ entryIdAssignedAtCapture: z2.literal(true).optional(),
913
+ collection: z2.string(),
914
+ name: z2.string(),
915
+ blockingReason: z2.string().optional(),
916
+ warnings: z2.array(z2.string()).optional()
917
+ })).optional(),
918
+ requested: z2.number(),
919
+ total: z2.number(),
920
+ failed: z2.number(),
921
+ skippedLowConfidence: z2.array(z2.object({
922
+ index: z2.number(),
923
+ name: z2.string(),
924
+ suggestedCollection: z2.string().optional(),
925
+ confidence: z2.number().optional()
926
+ })).optional(),
927
+ failedEntries: z2.array(z2.object({
928
+ index: z2.number(),
929
+ collection: z2.string(),
930
+ name: z2.string(),
931
+ error: z2.string()
932
+ })).optional()
933
+ });
934
+ var batchCaptureOutputSchema = z2.union([
935
+ batchCaptureRealOutputSchema,
936
+ batchCapturePreviewOutputSchema
937
+ ]);
938
+ function buildBatchPreviewSummary({ wouldCapture, wouldBlock = [], failed, skipped, requested }) {
939
+ const noun = requested === 1 ? "entry" : "entries";
940
+ const blockedNote = wouldBlock.length > 0 ? `, ${wouldBlock.length} would be BLOCKED` : "";
941
+ const failedNote = failed.length > 0 ? `, ${failed.length} would fail` : "";
942
+ const skippedNote = skipped.length > 0 ? `, ${skipped.length} skipped (low confidence)` : "";
943
+ return `Preview: would capture ${wouldCapture.length} of ${requested} ${noun}${blockedNote}${failedNote}${skippedNote} \u2014 no DB writes.`;
944
+ }
945
+ function buildBatchEntryFailure(args) {
946
+ return {
947
+ entryIdx: args.entryIdx,
948
+ name: args.name,
949
+ collection: args.collection,
950
+ entryId: "",
951
+ ok: false,
952
+ autoLinks: 0,
953
+ advisedLinks: 0,
954
+ status: "draft",
955
+ classifiedBy: args.classifiedBy,
956
+ confidence: args.confidence,
957
+ confidenceTier: args.confidenceTier,
958
+ error: args.error
959
+ };
960
+ }
961
+ function buildBatchPreviewFromResults(created, failed, skipped, requested, originalItems, originalAutoCommit) {
962
+ const wouldCaptureEntries = created.filter((r) => !r.wouldBlock);
963
+ const wouldBlockEntries = created.filter((r) => r.wouldBlock);
964
+ return buildBatchPreviewResult({
965
+ // Fix 1 (TEN-2918 follow-up): report the concrete `entryId` only when it was NOT
966
+ // auto-allocated (i.e. the caller supplied it for this item) — see WouldCaptureEntry's
967
+ // doc comment for why an auto-ID cannot be predicted per-item within a preview batch.
968
+ wouldCapture: wouldCaptureEntries.map((r) => ({
969
+ ...r.entryIdAssignedAtCapture ? { entryIdAssignedAtCapture: true } : { entryId: r.entryId },
970
+ collection: r.collection,
971
+ name: r.name,
972
+ ...r.classifiedBy ? { classifiedBy: r.classifiedBy } : {},
973
+ ...r.confidence != null ? { confidence: r.confidence } : {},
974
+ ...r.warnings?.length ? { warnings: r.warnings } : {}
975
+ })),
976
+ wouldBlock: wouldBlockEntries.map((r) => ({
977
+ ...r.entryIdAssignedAtCapture ? { entryIdAssignedAtCapture: true } : { entryId: r.entryId },
978
+ collection: r.collection,
979
+ name: r.name,
980
+ ...r.blockingReason ? { blockingReason: r.blockingReason } : {},
981
+ ...r.warnings?.length ? { warnings: r.warnings } : {}
982
+ })),
983
+ failed: failed.map((r) => ({ index: r.entryIdx, collection: r.collection, name: r.name, error: r.error ?? "unknown error" })),
984
+ skipped: skipped.map((s) => ({ index: s.index, name: s.name, ...s.suggestedCollection ? { suggestedCollection: s.suggestedCollection } : {}, ...s.confidence != null ? { confidence: s.confidence } : {} })),
985
+ requested,
986
+ // WP-577 review follow-up (P2, TEN-2918): thread the caller's original batch payload
987
+ // through so the "Capture for real" next-action can supply a non-empty `items` array —
988
+ // omitting it left the suggestion advertising `{ action: "batch" }` alone, which fails
989
+ // batchCaptureSchema's `.min(1)` items requirement the instant an agent follows it.
990
+ originalItems,
991
+ // Fix 1 (TEN-2918 follow-up): thread the batch's own autoCommit through unchanged.
992
+ originalAutoCommit
993
+ });
994
+ }
995
+ function buildBatchPreviewResult(input) {
996
+ const { wouldCapture, wouldBlock = [], failed, skipped, requested, originalItems, originalAutoCommit } = input;
997
+ const summary = buildBatchPreviewSummary(input);
998
+ const lines = [`# Batch Preview \u2014 No Entries Created`, summary, ""];
999
+ if (wouldCapture.length > 0) {
1000
+ lines.push("## Would capture");
1001
+ for (const r of wouldCapture) {
1002
+ const classNote = r.classifiedBy && r.classifiedBy !== "explicit" ? ` (${r.classifiedBy}${r.confidence != null ? ` ${r.confidence}%` : ""})` : "";
1003
+ const warnNote = r.warnings?.length ? ` \u2014 ${r.warnings.join("; ")}` : "";
1004
+ const idNote = r.entryId ? `**${r.entryId}**: ` : "";
1005
+ const assignedNote = r.entryIdAssignedAtCapture ? " (ID assigned at capture)" : "";
1006
+ lines.push(`- ${idNote}**${r.name}** [${r.collection}]${classNote}${warnNote}${assignedNote}`);
1007
+ }
1008
+ lines.push("");
1009
+ }
1010
+ if (wouldBlock.length > 0) {
1011
+ lines.push("## Would be BLOCKED");
1012
+ for (const b of wouldBlock) {
1013
+ const reasonNote = b.blockingReason ? ` \u2014 ${b.blockingReason}` : "";
1014
+ const idNote = b.entryId ? `**${b.entryId}**: ` : "";
1015
+ const assignedNote = b.entryIdAssignedAtCapture ? " (ID assigned at capture)" : "";
1016
+ lines.push(`- ${idNote}**${b.name}** [${b.collection}]${reasonNote}${assignedNote}`);
1017
+ }
1018
+ lines.push("");
1019
+ }
1020
+ if (skipped.length > 0) {
1021
+ lines.push("## Would be skipped \u2014 low confidence");
1022
+ for (const s of skipped) {
1023
+ const suggestion = s.suggestedCollection ? ` \u2014 best guess: \`${s.suggestedCollection}\`${s.confidence != null ? ` (${s.confidence}%)` : ""}` : " \u2014 no classification available";
1024
+ lines.push(`- **[${s.index}]** ${s.name}${suggestion}`);
1025
+ }
1026
+ lines.push("");
1027
+ }
1028
+ if (failed.length > 0) {
1029
+ lines.push("## Would fail");
1030
+ for (const f of failed) {
1031
+ lines.push(`- **[${f.index}]** ${f.name} [${f.collection}]: _${f.error}_`);
1032
+ }
1033
+ lines.push("");
1034
+ }
1035
+ lines.push("_No DB writes \u2014 call `capture action=batch` without `preview:true` to capture for real._");
1036
+ const next = originalItems && originalItems.length > 0 ? [{
1037
+ tool: "capture",
1038
+ description: "Capture for real",
1039
+ parameters: {
1040
+ action: "batch",
1041
+ items: originalItems,
1042
+ // Fix 1 (WP-577 review round 3, TEN-2918 follow-up): preserve the batch's own
1043
+ // autoCommit explicitly — `false` must survive (never dropped as falsy), and
1044
+ // `undefined` (never supplied) is omitted so the server default still governs.
1045
+ ...originalAutoCommit !== void 0 ? { autoCommit: originalAutoCommit } : {}
1046
+ }
1047
+ }] : [];
1048
+ return {
1049
+ content: [{ type: "text", text: lines.join("\n") }],
1050
+ structuredContent: {
1051
+ ...success(
1052
+ summary,
1053
+ {
1054
+ outcome: "preview",
1055
+ wouldCapture,
1056
+ ...wouldBlock.length > 0 ? { wouldBlock } : {},
1057
+ requested,
1058
+ total: wouldCapture.length,
1059
+ failed: failed.length,
1060
+ ...skipped.length > 0 ? { skippedLowConfidence: skipped } : {},
1061
+ ...failed.length > 0 ? { failedEntries: failed } : {}
1062
+ },
1063
+ next
1064
+ )
1065
+ }
1066
+ };
1067
+ }
1068
+
1069
+ // src/lib/createEntryPreviewResult.ts
1070
+ function isPreviewCreateEntryResult(result2) {
1071
+ return "preview" in result2 && result2.preview === true;
1072
+ }
1073
+ function extractPreviewWouldBlock(result2, preview) {
1074
+ return preview && result2 && isPreviewCreateEntryResult(result2) ? { wouldBlock: result2.wouldBlock === true, blockingReason: result2.blockingReason } : void 0;
1075
+ }
1076
+ function resolveEffectiveCollection(result2, preview, fallbackCollection) {
1077
+ return preview && result2 && isPreviewCreateEntryResult(result2) ? result2.collection ?? fallbackCollection : fallbackCollection;
1078
+ }
1079
+
1080
+ // src/lib/entryDataNormalization.ts
1081
+ function isEmptyValue(v) {
1082
+ return v == null || (Array.isArray(v) ? v.length === 0 : String(v).trim() === "");
1083
+ }
1084
+ function isNonEmptyValue(v) {
1085
+ return v != null && (Array.isArray(v) ? v.length > 0 : String(v).trim() !== "");
1086
+ }
1087
+ function levenshtein(a, b) {
1088
+ const m = a.length;
1089
+ const n = b.length;
1090
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
1091
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
1092
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
1093
+ for (let i = 1; i <= m; i++) {
1094
+ for (let j = 1; j <= n; j++) {
1095
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
1096
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
1097
+ }
1098
+ }
1099
+ return dp[m][n];
1100
+ }
1101
+ var APPETITE_OPTIONS = ["small", "medium", "large"];
1102
+ function findClosestOption(value, options) {
1103
+ const lower = value.toLowerCase();
1104
+ const exact = options.find((o) => o.toLowerCase() === lower);
1105
+ if (exact) return { opt: exact, dist: 0 };
1106
+ return options.reduce(
1107
+ (acc, opt) => {
1108
+ const d = levenshtein(lower, opt.toLowerCase());
1109
+ return d < acc.dist ? { opt, dist: d } : acc;
1110
+ },
1111
+ { opt: options[0], dist: Infinity }
1112
+ );
1113
+ }
1114
+ function canonicalizeSelects(data, fields, isBet) {
1115
+ if (isBet && data.appetite != null && typeof data.appetite === "string") {
1116
+ const val = data.appetite.trim();
1117
+ if (val) {
1118
+ const { opt, dist } = findClosestOption(val, APPETITE_OPTIONS);
1119
+ if (dist <= 4) data.appetite = opt;
1120
+ }
1121
+ }
1122
+ for (const field of fields) {
1123
+ if (field.type !== "select" || !field.options?.length) continue;
1124
+ if (field.key === "appetite" && isBet) continue;
1125
+ const val = data[field.key];
1126
+ if (val == null || typeof val !== "string") continue;
1127
+ const trimmed = val.trim();
1128
+ if (!trimmed) continue;
1129
+ const { opt, dist } = findClosestOption(trimmed, field.options);
1130
+ if (dist <= 4) data[field.key] = opt;
1131
+ }
1132
+ }
1133
+
1134
+ // src/lib/batchInlineRelations.ts
1135
+ async function applyBatchInlineRelations(relations, finalEntryId, preview, agentId) {
1136
+ const result2 = {
1137
+ relationsCreatedCount: 0,
1138
+ relationsProposedCount: 0,
1139
+ relationsNotValidatedCount: 0,
1140
+ relationsFailedList: []
1141
+ };
1142
+ if (!relations || relations.length === 0) return result2;
1143
+ if (preview) {
1144
+ result2.relationsNotValidatedCount = relations.length;
1145
+ return result2;
1146
+ }
1147
+ for (const rel of relations) {
1148
+ try {
1149
+ const relResult = await kernelMutation(
1150
+ "chain.createEntryRelation",
1151
+ {
1152
+ fromEntryId: finalEntryId,
1153
+ toEntryId: rel.to,
1154
+ type: rel.type,
1155
+ proposedBy: "user",
1156
+ sessionId: agentId ?? void 0
1157
+ }
1158
+ );
1159
+ if (relResult?.status === "agent_proposal_created") {
1160
+ result2.relationsProposedCount++;
1161
+ } else {
1162
+ result2.relationsCreatedCount++;
1163
+ }
1164
+ } catch (relErr) {
1165
+ const relMsg = relErr instanceof Error ? relErr.message : String(relErr);
1166
+ result2.relationsFailedList.push(`${rel.to} (${rel.type}): ${relMsg}`);
1167
+ }
1168
+ }
1169
+ return result2;
1170
+ }
1171
+
1172
+ // src/lib/captureForRealAction.ts
1173
+ function buildCaptureForRealNextAction(payload) {
1174
+ const {
1175
+ collection,
1176
+ name,
1177
+ description,
1178
+ context,
1179
+ entryId,
1180
+ canonicalKey,
1181
+ data,
1182
+ links,
1183
+ autoCommit,
1184
+ sourceRef,
1185
+ sourceExcerpt,
1186
+ ownerTeamEntryId,
1187
+ ownerRoleEntryId
1188
+ } = payload;
1189
+ return [{
1190
+ tool: "capture",
1191
+ description: "Capture for real",
1192
+ parameters: {
1193
+ collection,
1194
+ name,
1195
+ description,
1196
+ ...context ? { context } : {},
1197
+ ...entryId ? { entryId } : {},
1198
+ ...canonicalKey ? { canonicalKey } : {},
1199
+ ...data && Object.keys(data).length > 0 ? { data } : {},
1200
+ ...links && links.length > 0 ? { links } : {},
1201
+ ...autoCommit !== void 0 ? { autoCommit } : {},
1202
+ ...sourceRef ? { sourceRef } : {},
1203
+ ...sourceExcerpt ? { sourceExcerpt } : {},
1204
+ ...ownerTeamEntryId ? { ownerTeamEntryId } : {},
1205
+ ...ownerRoleEntryId ? { ownerRoleEntryId } : {}
1206
+ }
1207
+ }];
1208
+ }
1209
+
1210
+ // src/lib/rubricFormatting.ts
1211
+ function verdictQualityPhrase(result2) {
1212
+ const v = result2?.verdict;
1213
+ const criteria = v?.criteria ?? [];
1214
+ if (!v || criteria.length === 0) {
1215
+ return "Quality: not evaluated (no rubric for this type).";
1216
+ }
1217
+ const total = criteria.length;
1218
+ const passed = criteria.filter((c) => c.passed).length;
1219
+ return v.passed ? `Quality: all ${total} rubric criteria pass.` : `Quality: ${passed}/${total} rubric criteria pass \u2014 see the coaching above.`;
1220
+ }
1221
+ function formatRubricCoaching(result2) {
1222
+ const { verdict, rogerMartin } = result2;
1223
+ if (!verdict || verdict.criteria.length === 0) return "";
1224
+ const lines = ["## Semantic Quality"];
1225
+ const failed = (verdict.criteria ?? []).filter((c) => !c.passed);
1226
+ const total = verdict.criteria?.length ?? 0;
1227
+ const passedCount = total - failed.length;
1228
+ if (verdict.passed) {
1229
+ lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier).`);
1230
+ } else {
1231
+ lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier)`);
1232
+ lines.push("");
1233
+ for (const c of verdict.criteria) {
1234
+ const icon = c.passed ? "[x]" : "[ ]";
1235
+ const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
1236
+ lines.push(`${icon} ${c.id}${extra}`);
1237
+ }
1238
+ if (verdict.weakest) {
1239
+ lines.push("");
1240
+ lines.push(`**Coaching hint:** ${verdict.weakest.hint}`);
1241
+ lines.push(`_Question to consider:_ ${verdict.weakest.questionTemplate}`);
1242
+ }
1243
+ }
1244
+ if (rogerMartin) {
1245
+ lines.push("");
1246
+ lines.push("### Roger Martin Test");
1247
+ if (rogerMartin.isStrategicChoice) {
1248
+ lines.push("This principle passes \u2014 the opposite is a reasonable strategic choice.");
1249
+ } else {
1250
+ lines.push(`This principle may not be a strategic choice. ${rogerMartin.reasoning}`);
1251
+ if (rogerMartin.suggestion) {
1252
+ lines.push(`_Suggestion:_ ${rogerMartin.suggestion}`);
1253
+ }
1254
+ }
1255
+ }
1256
+ return lines.join("\n");
1257
+ }
1258
+ function formatRubricVerdictSection(verdict) {
1259
+ if (!verdict || !verdict.criteria || verdict.criteria.length === 0) return "";
1260
+ const lines = ["## Semantic Quality"];
1261
+ const failed = verdict.criteria.filter((c) => !c.passed);
1262
+ const total = verdict.criteria.length;
1263
+ const passedCount = total - failed.length;
1264
+ const durationSuffix = verdict.llmDurationMs ? ` in ${(verdict.llmDurationMs / 1e3).toFixed(1)}s` : "";
1265
+ const statusNote = verdict.llmStatus === "pending" ? " \u2014 LLM evaluation in progress..." : verdict.llmStatus === "failed" ? ` \u2014 LLM evaluation failed${verdict.llmError ? `: ${verdict.llmError}` : ""}, showing heuristic results` : verdict.source === "llm" && durationSuffix ? ` \u2014 evaluated${durationSuffix}` : "";
1266
+ if (failed.length === 0) {
1267
+ lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation).${statusNote}`);
1268
+ } else {
1269
+ lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation)${statusNote}`);
1270
+ lines.push("");
1271
+ for (const c of verdict.criteria) {
1272
+ const icon = c.passed ? "[x]" : "[ ]";
1273
+ const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
1274
+ lines.push(`${icon} ${c.id}${extra}`);
1275
+ }
1276
+ if (verdict.weakest) {
1277
+ lines.push("");
1278
+ lines.push(`**Top improvement:** ${verdict.weakest.hint}`);
1279
+ }
1280
+ }
1281
+ if (verdict.rogerMartin) {
1282
+ const rm = verdict.rogerMartin;
1283
+ lines.push("");
1284
+ lines.push("### Roger Martin Test");
1285
+ if (rm.isStrategicChoice) {
1286
+ lines.push(`This is a real strategic choice \u2014 the opposite is reasonable. ${rm.reasoning}`);
1287
+ } else {
1288
+ lines.push(`This may not be a strategic choice. ${rm.reasoning}`);
1289
+ if (rm.suggestion) {
1290
+ lines.push(`_Suggestion:_ ${rm.suggestion}`);
1291
+ }
1292
+ }
642
1293
  }
643
- return failureResult(
644
- lines.join("\n"),
645
- "COHERENCY_REFUSED",
646
- `Coherency gate refused ${toolName} on ${entryId}.`,
647
- "Use one of the refusal's routes (link / coherencyAcknowledgement / steeringOverrideReason), then retry.",
648
- void 0,
649
- { entryId, refusal }
650
- );
651
- }
652
-
653
- // src/lib/resolveCollection.ts
654
- async function resolveCollection(params) {
655
- const { name, description, typeHint, allowReviewRouting } = params;
656
- const sessionId = getAgentSessionId();
657
- const result2 = await kernelCall("chain.resolveCollection", {
658
- entryName: name,
659
- entryDescription: description,
660
- ...typeHint ? { typeHint } : {},
661
- ...allowReviewRouting ? { allowReviewRouting } : {},
662
- ...sessionId ? { agentSessionId: sessionId } : {}
663
- });
664
- return result2 ?? null;
1294
+ return lines.join("\n");
665
1295
  }
666
1296
 
667
- // src/lib/fieldTypes.ts
668
- var FIELD_TYPE_DEFAULTS = {
669
- "string": "",
670
- "text": "",
671
- "rich-text": "",
672
- "number": null,
673
- "boolean": false,
674
- "select": null,
675
- "multi-select": [],
676
- "array": [],
677
- "json": null,
678
- "date": null,
679
- "person": null
680
- };
1297
+ // src/lib/captureSinglePreviewOutput.ts
1298
+ import { z as z3 } from "zod/v3";
1299
+ var groundingRelatedEntrySchema = z3.object({
1300
+ entryId: z3.string(),
1301
+ name: z3.string(),
1302
+ collectionSlug: z3.string(),
1303
+ overlapRatio: z3.number(),
1304
+ recommendedRelationType: z3.string(),
1305
+ reasoning: z3.string()
1306
+ });
1307
+ var groundingDuplicateEntrySchema = z3.object({
1308
+ entryId: z3.string(),
1309
+ name: z3.string(),
1310
+ collectionSlug: z3.string(),
1311
+ matchType: z3.enum(["related", "possible_duplicate"]),
1312
+ overlapRatio: z3.number()
1313
+ });
1314
+ var groundingGovernanceEntrySchema = z3.object({
1315
+ entryId: z3.string(),
1316
+ name: z3.string(),
1317
+ collectionSlug: z3.string()
1318
+ });
1319
+ var groundingReportSchema = z3.object({
1320
+ related: z3.array(groundingRelatedEntrySchema),
1321
+ duplicates: z3.array(groundingDuplicateEntrySchema),
1322
+ governance: z3.array(groundingGovernanceEntrySchema)
1323
+ });
1324
+ var taskAlignmentSchema = z3.record(z3.unknown());
1325
+ var captureSinglePreviewOutputSchema = z3.object({
1326
+ entryId: z3.string(),
1327
+ name: z3.string(),
1328
+ collection: z3.string(),
1329
+ outcome: z3.enum(["preview", "blocked"]),
1330
+ // Present only when `outcome: "blocked"` AND the server supplied a reason.
1331
+ blockingReason: z3.string().optional(),
1332
+ // Always present — `result.warnings ?? []`, never omitted.
1333
+ warnings: z3.array(z3.string()),
1334
+ groundingReport: groundingReportSchema,
1335
+ // TEN-2458: only present when the kernel computed a librarian verdict for this preview.
1336
+ taskAlignment: taskAlignmentSchema.optional()
1337
+ }).strict();
681
1338
 
682
- // src/lib/formatFieldGuidance.ts
683
- function formatFieldGuidance(fields) {
684
- const guidedFields = fields.filter((f) => f.writingGuidance);
685
- if (guidedFields.length === 0) return "";
686
- const lines = ["## Writing Guidance"];
687
- for (const field of guidedFields) {
688
- const displayName = field.label || field.key;
689
- lines.push(`- ${displayName}: ${field.writingGuidance}`);
690
- if (field.writingExamples && field.writingExamples.length > 0) {
691
- lines.push(` Examples: ${field.writingExamples.join(" | ")}`);
1339
+ // src/lib/batchPreviewDuplicates.ts
1340
+ function createBatchPreviewDuplicateTracker() {
1341
+ const seenByCollection = /* @__PURE__ */ new Map();
1342
+ const seenEntryIds = /* @__PURE__ */ new Set();
1343
+ return {
1344
+ isDuplicateName(collection, name) {
1345
+ return seenByCollection.get(collection)?.has(name) ?? false;
1346
+ },
1347
+ recordName(collection, name) {
1348
+ let names = seenByCollection.get(collection);
1349
+ if (!names) {
1350
+ names = /* @__PURE__ */ new Set();
1351
+ seenByCollection.set(collection, names);
1352
+ }
1353
+ names.add(name);
1354
+ },
1355
+ isDuplicateEntryId(entryId) {
1356
+ return seenEntryIds.has(entryId);
1357
+ },
1358
+ recordEntryId(entryId) {
1359
+ seenEntryIds.add(entryId);
692
1360
  }
693
- }
694
- return lines.join("\n");
695
- }
696
-
697
- // src/lib/inferSourceDate.ts
698
- function inferSourceDate(...values) {
699
- const combined = values.filter((value) => typeof value === "string" && value.trim().length > 0).join("\n");
700
- if (!combined) return void 0;
701
- const isoMatch = combined.match(/\b(20\d{2}-\d{2}-\d{2})\b/);
702
- if (isoMatch) return isoMatch[1];
703
- const monthMatch = combined.match(
704
- /\b(january|february|march|april|may|june|july|august|september|october|november|december)\s+(\d{1,2})(?:st|nd|rd|th)?(?:,?\s+(20\d{2}))?\b/i
705
- );
706
- if (!monthMatch) return void 0;
707
- const monthIndex = [
708
- "january",
709
- "february",
710
- "march",
711
- "april",
712
- "may",
713
- "june",
714
- "july",
715
- "august",
716
- "september",
717
- "october",
718
- "november",
719
- "december"
720
- ].indexOf(monthMatch[1].toLowerCase());
721
- if (monthIndex < 0) return void 0;
722
- const inferredYear = monthMatch[3] ?? combined.match(/\b(20\d{2})\b/)?.[1] ?? String((/* @__PURE__ */ new Date()).getUTCFullYear());
723
- const month = String(monthIndex + 1).padStart(2, "0");
724
- const day = monthMatch[2].padStart(2, "0");
725
- return `${inferredYear}-${month}-${day}`;
1361
+ };
726
1362
  }
727
-
728
- // src/lib/collectionCache.ts
729
- var collectionCache = new ScopedCache(COLLECTION_CACHE_TTL_MS);
730
- async function getCollections() {
731
- const scope = cacheScope();
732
- const hit = collectionCache.get(scope);
733
- if (hit) return hit.collections;
734
- const result2 = await kernelQuery("chain.listCollections") ?? [];
735
- const bySlug = new Map(result2.map((c) => [c.slug, c]));
736
- collectionCache.set(scope, { collections: result2, bySlug });
737
- return result2;
1363
+ function buildBatchPreviewDuplicateResult(entryIdx, name, collection, classifiedBy, confidence, confidenceTier) {
1364
+ return {
1365
+ entryIdx,
1366
+ name,
1367
+ collection,
1368
+ entryId: "",
1369
+ ok: false,
1370
+ autoLinks: 0,
1371
+ advisedLinks: 0,
1372
+ status: "draft",
1373
+ classifiedBy,
1374
+ confidence,
1375
+ confidenceTier,
1376
+ error: `Duplicate entry: "${name}" already claimed by an earlier item in this batch [${collection}] \u2014 the real (non-preview) run would write the first and reject this one.`
1377
+ };
738
1378
  }
739
- async function getCollectionBySlug(slug) {
740
- await getCollections();
741
- return collectionCache.get(cacheScope())?.bySlug.get(slug);
1379
+ function buildBatchPreviewDuplicateEntryIdResult(entryIdx, name, collection, entryId, classifiedBy, confidence, confidenceTier) {
1380
+ return {
1381
+ entryIdx,
1382
+ name,
1383
+ collection,
1384
+ entryId: "",
1385
+ ok: false,
1386
+ autoLinks: 0,
1387
+ advisedLinks: 0,
1388
+ status: "draft",
1389
+ classifiedBy,
1390
+ confidence,
1391
+ confidenceTier,
1392
+ error: `Duplicate entry: ID "${entryId}" already claimed by an earlier item in this batch (workspace-wide) \u2014 the real (non-preview) run would write the first and reject this one.`
1393
+ };
742
1394
  }
743
- function invalidateCollectionCacheForScope() {
744
- collectionCache.delete(cacheScope());
1395
+ function checkBatchPreviewDuplicate(tracker, args) {
1396
+ if (!args.preview) return null;
1397
+ if (args.callerEntryId && tracker.isDuplicateEntryId(args.callerEntryId)) {
1398
+ return buildBatchPreviewDuplicateEntryIdResult(
1399
+ args.entryIdx,
1400
+ args.name,
1401
+ args.collection,
1402
+ args.callerEntryId,
1403
+ args.classifiedBy,
1404
+ args.confidence,
1405
+ args.confidenceTier
1406
+ );
1407
+ }
1408
+ if (tracker.isDuplicateName(args.collection, args.name)) {
1409
+ return buildBatchPreviewDuplicateResult(
1410
+ args.entryIdx,
1411
+ args.name,
1412
+ args.collection,
1413
+ args.classifiedBy,
1414
+ args.confidence,
1415
+ args.confidenceTier
1416
+ );
1417
+ }
1418
+ return null;
745
1419
  }
746
- async function isGoverned(slug) {
747
- const col = await getCollectionBySlug(slug);
748
- return !!col?.governed;
1420
+ function recordBatchPreviewIfConfirmed(tracker, args) {
1421
+ if (!args.wouldCapture) return;
1422
+ tracker.recordName(args.effectiveCollection, args.name);
1423
+ if (args.callerEntryId) tracker.recordEntryId(args.callerEntryId);
1424
+ }
1425
+ function reconcileBatchPreviewDuplicate(tracker, args) {
1426
+ if (args.wouldCapture && tracker.isDuplicateName(args.effectiveCollection, args.name)) {
1427
+ return buildBatchPreviewDuplicateResult(
1428
+ args.entryIdx,
1429
+ args.name,
1430
+ args.effectiveCollection,
1431
+ args.classifiedBy,
1432
+ args.confidence,
1433
+ args.confidenceTier
1434
+ );
1435
+ }
1436
+ recordBatchPreviewIfConfirmed(tracker, {
1437
+ wouldCapture: args.wouldCapture,
1438
+ effectiveCollection: args.effectiveCollection,
1439
+ name: args.name,
1440
+ callerEntryId: args.callerEntryId
1441
+ });
1442
+ return null;
749
1443
  }
750
1444
 
751
1445
  // src/tools/smart-capture.ts
@@ -828,81 +1522,81 @@ var AUTO_LINK_CONFIDENCE_THRESHOLD = 35;
828
1522
  var MAX_AUTO_LINKS = 5;
829
1523
  var MAX_SUGGESTIONS = 5;
830
1524
  var BR_STD_ENTRY_ID_REGEX = /^(BR|STD)-\d+$/;
831
- var entryIdSchema = z2.string().regex(BR_STD_ENTRY_ID_REGEX).optional().describe("Only for business-rules and standards. Must match BR-NNN or STD-NNN. Omit for all other collections \u2014 IDs are auto-generated.");
832
- var captureSchema = z2.object({
833
- collection: z2.string().optional().describe("Collection slug, e.g. 'tensions', 'business-rules', 'glossary', 'decisions'. Optional \u2014 classifier auto-routes when omitted."),
834
- name: z2.string().describe("Display name \u2014 be specific (e.g. 'Convex adjacency list won't scale for graph traversal')"),
835
- description: z2.string().describe("Full context \u2014 what's happening, why it matters, what you observed"),
836
- context: z2.string().optional().describe("Optional additional context (e.g. 'Observed during context gather calls taking 700ms+')"),
1525
+ var entryIdSchema = z4.string().regex(BR_STD_ENTRY_ID_REGEX).optional().describe("Only for business-rules and standards. Must match BR-NNN or STD-NNN. Omit for all other collections \u2014 IDs are auto-generated.");
1526
+ var captureSchema = z4.object({
1527
+ collection: z4.string().optional().describe("Collection slug, e.g. 'tensions', 'business-rules', 'glossary', 'decisions'. Optional \u2014 classifier auto-routes when omitted."),
1528
+ name: z4.string().describe("Display name \u2014 be specific (e.g. 'Convex adjacency list won't scale for graph traversal')"),
1529
+ description: z4.string().describe("Full context \u2014 what's happening, why it matters, what you observed"),
1530
+ context: z4.string().optional().describe("Optional additional context (e.g. 'Observed during context gather calls taking 700ms+')"),
837
1531
  entryId: entryIdSchema,
838
- canonicalKey: z2.string().optional().describe("Semantic type (e.g. 'decision', 'tension', 'vision'). Auto-assigned from collection if omitted."),
839
- data: z2.record(z2.unknown()).optional().describe("Explicit field values when you know the schema (e.g. canonical_key, cardinality_rule, required_fields). Merged with inferred values; user-provided wins."),
840
- links: z2.array(z2.object({
841
- to: z2.string().describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
842
- type: z2.string().describe("Relation type (e.g. 'governs', 'related_to', 'informs')")
1532
+ canonicalKey: z4.string().optional().describe("Semantic type (e.g. 'decision', 'tension', 'vision'). Auto-assigned from collection if omitted."),
1533
+ data: z4.record(z4.unknown()).optional().describe("Explicit field values when you know the schema (e.g. canonical_key, cardinality_rule, required_fields). Merged with inferred values; user-provided wins."),
1534
+ links: z4.array(z4.object({
1535
+ to: z4.string().describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
1536
+ type: z4.string().describe("Relation type (e.g. 'governs', 'related_to', 'informs')")
843
1537
  })).optional().describe("Relations to create after capture. Skips auto-link discovery when provided."),
844
- autoCommit: z2.boolean().optional().describe("If true, commits the entry immediately after capture + linking. If omitted, Open mode workspaces auto-commit by default and consensus/role modes stay draft-first."),
845
- sourceRef: z2.string().optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
846
- sourceExcerpt: z2.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
1538
+ autoCommit: z4.boolean().optional().describe("If true, commits the entry immediately after capture + linking. If omitted, Open mode workspaces auto-commit by default and consensus/role modes stay draft-first."),
1539
+ sourceRef: z4.string().optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
1540
+ sourceExcerpt: z4.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
847
1541
  // WP-316 S3: Preview gate — dry-run mode. Returns what would happen, no DB writes.
848
- preview: z2.boolean().optional().describe("If true, validates the capture without writing. Returns what would happen. Default false."),
1542
+ preview: z4.boolean().optional().describe("If true, validates the capture without writing. Returns what would happen. Default false."),
849
1543
  // WP-318 S2: Pre-write grounding — run link suggestion before creating entry.
850
- suggestOnly: z2.boolean().optional().describe("If true, runs pre-write grounding (suggestLinksForCapture) and returns a groundingReport WITHOUT creating any entry. Use to preview graph participation before accepting. Default false."),
1544
+ suggestOnly: z4.boolean().optional().describe("If true, runs pre-write grounding (suggestLinksForCapture) and returns a groundingReport WITHOUT creating any entry. Use to preview graph participation before accepting. Default false."),
851
1545
  // WP-318 S2: Format for groundingReport in response.
852
- format: z2.enum(["agent", "human"]).optional().describe("Response format for grounding data. 'agent' (default): full JSON groundingReport. 'human': compressed summary string appended to the capture summary."),
1546
+ format: z4.enum(["agent", "human"]).optional().describe("Response format for grounding data. 'agent' (default): full JSON groundingReport. 'human': compressed summary string appended to the capture summary."),
853
1547
  // WP-513: team+role to create AS OWNER of (rung 2 only); no-op pre-rung-2.
854
- ownerTeamEntryId: z2.string().max(200).optional().describe("Owning team entry ID/ref (rung 2)."),
855
- ownerRoleEntryId: z2.string().max(200).optional().describe("Owning role entry ID/ref (rung 2).")
1548
+ ownerTeamEntryId: z4.string().max(200).optional().describe("Owning team entry ID/ref (rung 2)."),
1549
+ ownerRoleEntryId: z4.string().max(200).optional().describe("Owning role entry ID/ref (rung 2).")
856
1550
  });
857
- var batchCaptureRelationSchema = z2.object({
858
- to: z2.string().max(200).describe("Target entry ID already on the Chain, e.g. '<PREFIX>-<n>'."),
859
- type: z2.string().max(200).describe("Relation type, e.g. 'related_to', 'informed_by', 'governs'.")
1551
+ var batchCaptureRelationSchema = z4.object({
1552
+ to: z4.string().max(200).describe("Target entry ID already on the Chain, e.g. '<PREFIX>-<n>'."),
1553
+ type: z4.string().max(200).describe("Relation type, e.g. 'related_to', 'informed_by', 'governs'.")
860
1554
  });
861
- var batchCaptureSchema = z2.object({
862
- entries: z2.array(z2.object({
1555
+ var batchCaptureSchema = z4.object({
1556
+ entries: z4.array(z4.object({
863
1557
  // FEAT-160
864
- collection: z2.string().max(200).optional().describe("Collection slug. Optional \u2014 auto-classified via LLM when omitted."),
865
- name: z2.string().max(500).describe("Display name"),
866
- description: z2.string().max(2e4).describe("Full context / definition"),
1558
+ collection: z4.string().max(200).optional().describe("Collection slug. Optional \u2014 auto-classified via LLM when omitted."),
1559
+ name: z4.string().max(500).describe("Display name"),
1560
+ description: z4.string().max(2e4).describe("Full context / definition"),
867
1561
  entryId: entryIdSchema,
868
- data: z2.record(z2.unknown()).optional().describe("Explicit field values (e.g. urgency, status, assignee). Merged with inferred values; user-provided wins."),
869
- canonicalKey: z2.string().max(200).optional().describe("Semantic type (e.g. 'decision', 'tension', 'work_package'). Enables work-package redirect in createEntry when collection is 'chains'."),
870
- sourceRef: z2.string().max(2e3).optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
871
- sourceExcerpt: z2.string().max(5e3).optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
1562
+ data: z4.record(z4.unknown()).optional().describe("Explicit field values (e.g. urgency, status, assignee). Merged with inferred values; user-provided wins."),
1563
+ canonicalKey: z4.string().max(200).optional().describe("Semantic type (e.g. 'decision', 'tension', 'work_package'). Enables work-package redirect in createEntry when collection is 'chains'."),
1564
+ sourceRef: z4.string().max(2e3).optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
1565
+ sourceExcerpt: z4.string().max(5e3).optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
872
1566
  // TEN-957 (WP-484 S2): relations to create right after this entry is captured.
873
- relations: z2.array(batchCaptureRelationSchema).max(10).optional().describe("Relations to create right after this entry is captured \u2014 each {to, type} links the NEW entry to an existing Chain entry."),
1567
+ relations: z4.array(batchCaptureRelationSchema).max(10).optional().describe("Relations to create right after this entry is captured \u2014 each {to, type} links the NEW entry to an existing Chain entry."),
874
1568
  // WP-513: team+role to create THIS entry AS OWNER of (rung 2 only).
875
- ownerTeamEntryId: z2.string().max(200).optional().describe("Owning team entry ID/ref (rung 2)."),
876
- ownerRoleEntryId: z2.string().max(200).optional().describe("Owning role entry ID/ref (rung 2).")
1569
+ ownerTeamEntryId: z4.string().max(200).optional().describe("Owning team entry ID/ref (rung 2)."),
1570
+ ownerRoleEntryId: z4.string().max(200).optional().describe("Owning role entry ID/ref (rung 2).")
877
1571
  })).min(1).max(50).describe("Array of entries to capture"),
878
- autoCommit: z2.boolean().optional().describe(
1572
+ autoCommit: z4.boolean().optional().describe(
879
1573
  "If true, commits created entries immediately after linking. If omitted, Open mode workspaces commit by default and consensus/role modes stay draft-first."
880
1574
  ),
881
1575
  // WP-316 S3: Preview gate — dry-run mode. Returns what would happen, no DB writes.
882
- preview: z2.boolean().optional().describe("If true, validates all captures without writing. Returns what would happen. Default false.")
1576
+ preview: z4.boolean().optional().describe("If true, validates all captures without writing. Returns what would happen. Default false.")
883
1577
  });
884
- var captureClassifierSchema = z2.object({
885
- enabled: z2.boolean(),
886
- autoRouted: z2.boolean(),
887
- agrees: z2.boolean(),
888
- abstained: z2.boolean(),
889
- topConfidence: z2.number(),
890
- confidence: z2.number(),
891
- reasons: z2.array(z2.string()),
892
- candidates: z2.array(
893
- z2.object({
894
- collection: z2.string(),
895
- signalScore: z2.number().optional(),
896
- confidence: z2.number(),
1578
+ var captureClassifierSchema = z4.object({
1579
+ enabled: z4.boolean(),
1580
+ autoRouted: z4.boolean(),
1581
+ agrees: z4.boolean(),
1582
+ abstained: z4.boolean(),
1583
+ topConfidence: z4.number(),
1584
+ confidence: z4.number(),
1585
+ reasons: z4.array(z4.string()),
1586
+ candidates: z4.array(
1587
+ z4.object({
1588
+ collection: z4.string(),
1589
+ signalScore: z4.number().optional(),
1590
+ confidence: z4.number(),
897
1591
  /** WP-316 S2: required-field cost — how many fields the agent must supply for this collection. */
898
- requiredFieldCount: z2.number().optional()
1592
+ requiredFieldCount: z4.number().optional()
899
1593
  })
900
1594
  ),
901
- agentProvidedCollection: z2.string().optional(),
902
- overrideCommand: z2.string().optional(),
903
- classifiedBy: z2.enum(["llm", "heuristic", "explicit"]).optional(),
904
- confidenceTier: z2.enum(["high", "medium", "low"]).optional(),
905
- reasoning: z2.string().optional()
1595
+ agentProvidedCollection: z4.string().optional(),
1596
+ overrideCommand: z4.string().optional(),
1597
+ classifiedBy: z4.enum(["llm", "heuristic", "explicit"]).optional(),
1598
+ confidenceTier: z4.enum(["high", "medium", "low"]).optional(),
1599
+ reasoning: z4.string().optional()
906
1600
  });
907
1601
  function trackClassifierTelemetry(params) {
908
1602
  const telemetry = {
@@ -1130,106 +1824,55 @@ async function resolveCaptureCollection(params) {
1130
1824
  classifierMeta
1131
1825
  };
1132
1826
  }
1133
- var captureSuccessOutputSchema = z2.object({
1134
- entryId: z2.string(),
1135
- collection: z2.string(),
1136
- name: z2.string(),
1827
+ var captureSuccessOutputSchema = z4.object({
1828
+ entryId: z4.string(),
1829
+ collection: z4.string(),
1830
+ name: z4.string(),
1137
1831
  // "draft_on_failure" is the status emitted when an auto-commit is REFUSED/failed (the entry
1138
1832
  // stays a draft) — the same path that now also emits coherencyRefusal. The strict schema must
1139
1833
  // accept it or a refused response fails to validate on `status` (codex review, completing the
1140
1834
  // coherencyRefusal contract fix).
1141
- status: z2.enum(["draft", "committed", "proposed", "draft_on_failure"]),
1835
+ status: z4.enum(["draft", "committed", "proposed", "draft_on_failure"]),
1142
1836
  // WP-480 S1: `qualityScore` (required, client N/10) deleted — a named, accepted
1143
1837
  // breaking output-contract change. The server verdict stays as `qualityVerdict`.
1144
- qualityVerdict: z2.record(z2.unknown()).optional(),
1838
+ qualityVerdict: z4.record(z4.unknown()).optional(),
1145
1839
  classifier: captureClassifierSchema.optional(),
1146
- studioUrl: z2.string().optional(),
1147
- warnings: z2.array(z2.string()).optional(),
1148
- normalization: z2.object({
1149
- remapped: z2.record(z2.string()).optional(),
1150
- rejected: z2.array(z2.string()).optional()
1840
+ studioUrl: z4.string().optional(),
1841
+ warnings: z4.array(z4.string()).optional(),
1842
+ normalization: z4.object({
1843
+ remapped: z4.record(z4.string()).optional(),
1844
+ rejected: z4.array(z4.string()).optional()
1151
1845
  }).optional(),
1152
- expectedFields: z2.array(z2.object({
1153
- key: z2.string(),
1154
- type: z2.string(),
1155
- required: z2.boolean().optional()
1846
+ expectedFields: z4.array(z4.object({
1847
+ key: z4.string(),
1848
+ type: z4.string(),
1849
+ required: z4.boolean().optional()
1156
1850
  })).optional(),
1157
1851
  // TEN-2365: capture-time authority-domain proposal (PENDING ratification), when one was filed.
1158
- authorityDomain: z2.object({
1159
- slug: z2.string(),
1160
- status: z2.literal("proposal-pending")
1852
+ authorityDomain: z4.object({
1853
+ slug: z4.string(),
1854
+ status: z4.literal("proposal-pending")
1161
1855
  }).optional(),
1162
1856
  // WP-465 surface parity: structured coherency refusal when an auto-commit is gate-refused.
1163
1857
  // Loose record (matching the qualityVerdict convention above) — the CoherencyRefusal contract
1164
1858
  // is authored in convex/lib/gates/coherencyControls.ts; re-declaring its shape here would create
1165
1859
  // a second source of truth. Required because the schema is `.strict()` (an undeclared key throws).
1166
- coherencyRefusal: z2.record(z2.unknown()).optional(),
1860
+ coherencyRefusal: z4.record(z4.unknown()).optional(),
1167
1861
  // WP-485 Slice 2b round 4 (Codex P2, FEAT-1370): the server's contradiction advisory
1168
1862
  // (ContradictionAdvisory, declared below) is emitted into structuredContent at line ~2203
1169
1863
  // but was missing here — since this schema is `.strict()`, any real capture response
1170
1864
  // carrying the advisory failed validation outright with `unrecognized_keys`. Loose record,
1171
1865
  // same single-source-of-truth rationale as coherencyRefusal above.
1172
- contradictionAdvisory: z2.record(z2.unknown()).optional()
1866
+ contradictionAdvisory: z4.record(z4.unknown()).optional()
1173
1867
  }).strict();
1174
- var captureClassifierOnlyOutputSchema = z2.object({
1868
+ var captureClassifierOnlyOutputSchema = z4.object({
1175
1869
  classifier: captureClassifierSchema
1176
1870
  }).strict();
1177
- var captureOutputSchema = z2.union([
1871
+ var captureOutputSchema = z4.union([
1178
1872
  captureSuccessOutputSchema,
1873
+ captureSinglePreviewOutputSchema,
1179
1874
  captureClassifierOnlyOutputSchema
1180
1875
  ]);
1181
- var batchCaptureOutputSchema = z2.object({
1182
- captured: z2.array(z2.object({
1183
- entryId: z2.string(),
1184
- collection: z2.string(),
1185
- name: z2.string(),
1186
- // "draft_on_failure" is the status emitted when an auto-commit is REFUSED/failed (the entry
1187
- // stays a draft) — the same path that now also emits coherencyRefusal. The strict schema must
1188
- // accept it or a refused response fails to validate on `status` (codex review, completing the
1189
- // coherencyRefusal contract fix).
1190
- status: z2.enum(["draft", "committed", "proposed", "draft_on_failure"]),
1191
- classifiedBy: z2.enum(["llm", "heuristic", "explicit"]).optional(),
1192
- confidence: z2.number().optional(),
1193
- confidenceTier: z2.enum(["high", "medium", "low"]).optional(),
1194
- warnings: z2.array(z2.string()).optional(),
1195
- normalization: z2.object({
1196
- remapped: z2.record(z2.string()).optional(),
1197
- rejected: z2.array(z2.string()).optional()
1198
- }).optional(),
1199
- // TEN-2365: capture-time authority-domain proposal slug (PENDING ratification), when filed.
1200
- domain: z2.string().optional(),
1201
- // WP-465 surface parity: structured coherency refusal for a gate-refused auto-commit (batch
1202
- // shape). Loose record — same single-source rationale as captureSuccessOutputSchema above.
1203
- coherencyRefusal: z2.record(z2.unknown()).optional(),
1204
- // WP-485 Slice 2b round 4 (Codex P2, FEAT-1370): per-entry contradiction advisory, emitted
1205
- // into structuredContent at line ~2967 but undeclared here. Not `.strict()` so this one was
1206
- // silently stripped rather than rejected — declared anyway so batch consumers actually see it.
1207
- contradictionAdvisory: z2.record(z2.unknown()).optional()
1208
- })),
1209
- total: z2.number(),
1210
- failed: z2.number(),
1211
- committed: z2.number(),
1212
- proposed: z2.number(),
1213
- drafts: z2.number(),
1214
- classified: z2.number().optional(),
1215
- autoCommitApplied: z2.boolean(),
1216
- skippedLowConfidence: z2.array(z2.object({
1217
- index: z2.number(),
1218
- name: z2.string(),
1219
- suggestedCollection: z2.string().optional(),
1220
- confidence: z2.number().optional(),
1221
- alternatives: z2.array(z2.object({
1222
- collection: z2.string(),
1223
- confidence: z2.number()
1224
- })).optional()
1225
- })).optional(),
1226
- failedEntries: z2.array(z2.object({
1227
- index: z2.number(),
1228
- collection: z2.string(),
1229
- name: z2.string(),
1230
- error: z2.string()
1231
- })).optional()
1232
- });
1233
1876
  function shouldAutoCommitCapture(autoCommit, governanceMode) {
1234
1877
  if (governanceMode !== "open") return false;
1235
1878
  return autoCommit === true || autoCommit === void 0;
@@ -1245,94 +1888,42 @@ function buildDataFromFields(fields, descriptionField, descriptionValue) {
1245
1888
  }
1246
1889
  return data;
1247
1890
  }
1248
- function isEmptyValue(v) {
1249
- return v == null || (Array.isArray(v) ? v.length === 0 : String(v).trim() === "");
1250
- }
1251
- function isNonEmptyValue(v) {
1252
- return v != null && (Array.isArray(v) ? v.length > 0 : String(v).trim() !== "");
1253
- }
1254
- function levenshtein(a, b) {
1255
- const m = a.length;
1256
- const n = b.length;
1257
- const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
1258
- for (let i = 0; i <= m; i++) dp[i][0] = i;
1259
- for (let j = 0; j <= n; j++) dp[0][j] = j;
1260
- for (let i = 1; i <= m; i++) {
1261
- for (let j = 1; j <= n; j++) {
1262
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
1263
- dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
1264
- }
1265
- }
1266
- return dp[m][n];
1267
- }
1268
- var APPETITE_OPTIONS = ["small", "medium", "large"];
1269
- function findClosestOption(value, options) {
1270
- const lower = value.toLowerCase();
1271
- const exact = options.find((o) => o.toLowerCase() === lower);
1272
- if (exact) return { opt: exact, dist: 0 };
1273
- return options.reduce(
1274
- (acc, opt) => {
1275
- const d = levenshtein(lower, opt.toLowerCase());
1276
- return d < acc.dist ? { opt, dist: d } : acc;
1277
- },
1278
- { opt: options[0], dist: Infinity }
1279
- );
1280
- }
1281
- function canonicalizeSelects(data, fields, isBet) {
1282
- if (isBet && data.appetite != null && typeof data.appetite === "string") {
1283
- const val = data.appetite.trim();
1284
- if (val) {
1285
- const { opt, dist } = findClosestOption(val, APPETITE_OPTIONS);
1286
- if (dist <= 4) data.appetite = opt;
1287
- }
1288
- }
1289
- for (const field of fields) {
1290
- if (field.type !== "select" || !field.options?.length) continue;
1291
- if (field.key === "appetite" && isBet) continue;
1292
- const val = data[field.key];
1293
- if (val == null || typeof val !== "string") continue;
1294
- const trimmed = val.trim();
1295
- if (!trimmed) continue;
1296
- const { opt, dist } = findClosestOption(trimmed, field.options);
1297
- if (dist <= 4) data[field.key] = opt;
1298
- }
1299
- }
1300
1891
  var CAPTURE_ACTIONS = ["capture", "batch"];
1301
1892
  var captureItemSchema = batchCaptureSchema.shape.entries.element;
1302
- var captureCompoundSchema = z2.object({
1303
- action: z2.enum(CAPTURE_ACTIONS).optional().default("capture").describe("'capture': create a single knowledge entry (the original capture behavior). 'batch': create multiple entries in one call via `items[]` (absorbs batch-capture; each item may carry inline `relations`)."),
1893
+ var captureCompoundSchema = z4.object({
1894
+ action: z4.enum(CAPTURE_ACTIONS).optional().default("capture").describe("'capture': create a single knowledge entry (the original capture behavior). 'batch': create multiple entries in one call via `items[]` (absorbs batch-capture; each item may carry inline `relations`)."),
1304
1895
  // For 'capture' — mirrors captureSchema, relaxed to optional (batch omits these).
1305
- collection: z2.string().max(200).optional().describe("For 'capture': collection slug, e.g. 'tensions', 'business-rules', 'glossary', 'decisions'. Optional \u2014 classifier auto-routes when omitted."),
1306
- name: z2.string().max(500).optional().describe("For 'capture': display name \u2014 required for this action."),
1307
- description: z2.string().max(2e4).optional().describe("For 'capture': full context \u2014 required for this action."),
1308
- context: z2.string().max(5e3).optional().describe("For 'capture': optional additional context."),
1896
+ collection: z4.string().max(200).optional().describe("For 'capture': collection slug, e.g. 'tensions', 'business-rules', 'glossary', 'decisions'. Optional \u2014 classifier auto-routes when omitted."),
1897
+ name: z4.string().max(500).optional().describe("For 'capture': display name \u2014 required for this action."),
1898
+ description: z4.string().max(2e4).optional().describe("For 'capture': full context \u2014 required for this action."),
1899
+ context: z4.string().max(5e3).optional().describe("For 'capture': optional additional context."),
1309
1900
  entryId: entryIdSchema,
1310
- canonicalKey: z2.string().max(200).optional().describe("For 'capture': semantic type (e.g. 'decision', 'tension', 'vision'). Auto-assigned from collection if omitted."),
1311
- data: z2.record(z2.unknown()).optional().describe("For 'capture': explicit field values. Merged with inferred values; user-provided wins."),
1312
- links: z2.array(z2.object({
1313
- to: z2.string().max(200).describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
1314
- type: z2.string().max(200).describe("Relation type (e.g. 'governs', 'related_to', 'informs')")
1901
+ canonicalKey: z4.string().max(200).optional().describe("For 'capture': semantic type (e.g. 'decision', 'tension', 'vision'). Auto-assigned from collection if omitted."),
1902
+ data: z4.record(z4.unknown()).optional().describe("For 'capture': explicit field values. Merged with inferred values; user-provided wins."),
1903
+ links: z4.array(z4.object({
1904
+ to: z4.string().max(200).describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
1905
+ type: z4.string().max(200).describe("Relation type (e.g. 'governs', 'related_to', 'informs')")
1315
1906
  })).max(20).optional().describe("For 'capture': relations to create after capture. Skips auto-link discovery when provided."),
1316
- autoCommit: z2.boolean().optional().describe("For 'capture'/'batch': if true, commits immediately after capture + linking."),
1317
- sourceRef: z2.string().max(2e3).optional().describe("For 'capture': URI or path of the source document backing this entry."),
1318
- sourceExcerpt: z2.string().max(5e3).optional().describe("For 'capture': verbatim excerpt from the source backing this entry's claims."),
1319
- preview: z2.boolean().optional().describe("For 'capture'/'batch': if true, validates without writing."),
1320
- suggestOnly: z2.boolean().optional().describe("For 'capture': if true, runs pre-write grounding and returns a groundingReport WITHOUT creating any entry."),
1321
- format: z2.enum(["agent", "human"]).optional().describe("For 'capture': response format for grounding data."),
1907
+ autoCommit: z4.boolean().optional().describe("For 'capture'/'batch': if true, commits immediately after capture + linking."),
1908
+ sourceRef: z4.string().max(2e3).optional().describe("For 'capture': URI or path of the source document backing this entry."),
1909
+ sourceExcerpt: z4.string().max(5e3).optional().describe("For 'capture': verbatim excerpt from the source backing this entry's claims."),
1910
+ preview: z4.boolean().optional().describe("For 'capture'/'batch': if true, validates without writing."),
1911
+ suggestOnly: z4.boolean().optional().describe("For 'capture': if true, runs pre-write grounding and returns a groundingReport WITHOUT creating any entry."),
1912
+ format: z4.enum(["agent", "human"]).optional().describe("For 'capture': response format for grounding data."),
1322
1913
  // For 'batch' — mirrors batchCaptureSchema's `entries`, renamed `items` per §3.
1323
- items: z2.array(captureItemSchema).min(1).max(50).optional().describe("For 'batch': array of entries to capture, each may carry inline `relations`."),
1914
+ items: z4.array(captureItemSchema).min(1).max(50).optional().describe("For 'batch': array of entries to capture, each may carry inline `relations`."),
1324
1915
  // WP-513: team+role to create AS OWNER of (rung 2 only).
1325
- ownerTeamEntryId: z2.string().max(200).optional().describe("For 'capture': owning team (rung-2)."),
1326
- ownerRoleEntryId: z2.string().max(200).optional().describe("For 'capture': owning role (rung-2).")
1916
+ ownerTeamEntryId: z4.string().max(200).optional().describe("For 'capture': owning team (rung-2)."),
1917
+ ownerRoleEntryId: z4.string().max(200).optional().describe("For 'capture': owning role (rung-2).")
1327
1918
  });
1328
- var captureSingleVariant = captureSchema.extend({ action: z2.literal("capture") });
1329
- var captureBatchVariant = z2.object({
1330
- action: z2.literal("batch"),
1331
- items: z2.array(captureItemSchema).min(1).max(50),
1332
- autoCommit: z2.boolean().optional(),
1333
- preview: z2.boolean().optional()
1919
+ var captureSingleVariant = captureSchema.extend({ action: z4.literal("capture") });
1920
+ var captureBatchVariant = z4.object({
1921
+ action: z4.literal("batch"),
1922
+ items: z4.array(captureItemSchema).min(1).max(50),
1923
+ autoCommit: z4.boolean().optional(),
1924
+ preview: z4.boolean().optional()
1334
1925
  });
1335
- var captureActionUnion = z2.discriminatedUnion("action", [
1926
+ var captureActionUnion = z4.discriminatedUnion("action", [
1336
1927
  captureSingleVariant,
1337
1928
  captureBatchVariant
1338
1929
  ]);
@@ -1500,7 +2091,23 @@ ${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.colle
1500
2091
  ...success(
1501
2092
  summaryText,
1502
2093
  { groundingReport, outcome: "suggest_only" },
1503
- [{ tool: "capture", description: "Capture for real", parameters: { collection: resolvedCollection, name, description } }]
2094
+ // Fix 3 sibling (TEN-2918 follow-up): thread the caller's full original payload
2095
+ // see lib/captureForRealAction.ts's doc comment.
2096
+ buildCaptureForRealNextAction({
2097
+ collection: resolvedCollection,
2098
+ name,
2099
+ description,
2100
+ context,
2101
+ entryId,
2102
+ canonicalKey,
2103
+ data: userData,
2104
+ links,
2105
+ autoCommit,
2106
+ sourceRef,
2107
+ sourceExcerpt,
2108
+ ownerTeamEntryId,
2109
+ ownerRoleEntryId
2110
+ })
1504
2111
  )
1505
2112
  }
1506
2113
  };
@@ -1607,7 +2214,7 @@ ${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.colle
1607
2214
  // accepted shape as the CLI dying between create and re-eval).
1608
2215
  ...links && links.length > 0 ? { deferLLMSchedule: true } : {}
1609
2216
  });
1610
- if (result2 && "preview" in result2 && result2.preview) {
2217
+ if (result2 && isPreviewCreateEntryResult(result2)) {
1611
2218
  const hasGrounding = groundingReport.related.length > 0 || groundingReport.duplicates.length > 0 || groundingReport.governance.length > 0;
1612
2219
  const groundingSummary = hasGrounding ? `
1613
2220
 
@@ -1623,7 +2230,10 @@ ${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.colle
1623
2230
  {
1624
2231
  entryId: result2.entryId,
1625
2232
  name,
1626
- collection: resolvedCollection,
2233
+ // P0 round 4 (fix 1/3, root): see resolveEffectiveCollection's doc comment
2234
+ // (lib/createEntryPreviewResult.ts) for why this must be the server's EFFECTIVE
2235
+ // post-routing collection, never the caller's pre-routing `resolvedCollection`.
2236
+ collection: resolveEffectiveCollection(result2, preview, resolvedCollection),
1627
2237
  outcome: wouldBlock ? "blocked" : "preview",
1628
2238
  ...wouldBlock && result2.blockingReason ? { blockingReason: result2.blockingReason } : {},
1629
2239
  warnings: result2.warnings ?? [],
@@ -1631,7 +2241,26 @@ ${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.colle
1631
2241
  // TEN-2458: thread task-alignment verdict when kernel computed it for this preview.
1632
2242
  ...result2.taskAlignment ? { taskAlignment: result2.taskAlignment } : {}
1633
2243
  },
1634
- [{ tool: "capture", description: "Capture for real", parameters: { collection: resolvedCollection, name, description } }]
2244
+ // Fix 3 (WP-577 review re-review, TEN-2918 follow-up): thread the caller's full
2245
+ // original payload so a follow-up "capture for real" creates the SAME entry the
2246
+ // preview described — see lib/captureForRealAction.ts's doc comment for the bug
2247
+ // this closes (a bare {collection,name,description} dropped `data`/`links`/etc.,
2248
+ // so a required WHY supplied via `data` silently vanished on retry).
2249
+ buildCaptureForRealNextAction({
2250
+ collection: resolvedCollection,
2251
+ name,
2252
+ description,
2253
+ context,
2254
+ entryId,
2255
+ canonicalKey,
2256
+ data: userData,
2257
+ links,
2258
+ autoCommit,
2259
+ sourceRef,
2260
+ sourceExcerpt,
2261
+ ownerTeamEntryId,
2262
+ ownerRoleEntryId
2263
+ })
1635
2264
  );
1636
2265
  if (result2.contract) {
1637
2266
  previewEnvelope.contract = result2.contract;
@@ -2294,6 +2923,7 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2294
2923
  }
2295
2924
  }
2296
2925
  const results = [];
2926
+ const previewDupTracker = createBatchPreviewDuplicateTracker();
2297
2927
  const skippedLowConfidence = [];
2298
2928
  await server.sendLoggingMessage({
2299
2929
  level: "info",
@@ -2328,20 +2958,15 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2328
2958
  await pending.finish(scores);
2329
2959
  } catch (error) {
2330
2960
  const msg = error instanceof Error ? error.message : String(error);
2331
- results.push({
2961
+ results.push(buildBatchEntryFailure({
2332
2962
  entryIdx: pending.entryIdx,
2333
2963
  name: pending.entry.name,
2334
2964
  collection: pending.resolvedSlug,
2335
- entryId: "",
2336
- ok: false,
2337
- autoLinks: 0,
2338
- advisedLinks: 0,
2339
- status: "draft",
2340
2965
  classifiedBy: pending.classifiedBy,
2341
2966
  confidence: pending.confidence,
2342
2967
  confidenceTier: pending.confidenceTier,
2343
2968
  error: msg
2344
- });
2969
+ }));
2345
2970
  }
2346
2971
  }
2347
2972
  }
@@ -2388,38 +3013,28 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2388
3013
  const profile = await getProfile(resolvedSlug);
2389
3014
  const col = collCache.get(resolvedSlug);
2390
3015
  if (!col) {
2391
- results.push({
3016
+ results.push(buildBatchEntryFailure({
2392
3017
  entryIdx,
2393
3018
  name: entry.name,
2394
3019
  collection: resolvedSlug,
2395
- entryId: "",
2396
- ok: false,
2397
- autoLinks: 0,
2398
- advisedLinks: 0,
2399
- status: "draft",
2400
3020
  classifiedBy,
2401
3021
  confidence,
2402
3022
  confidenceTier,
2403
3023
  error: `Collection "${resolvedSlug}" not found`
2404
- });
3024
+ }));
2405
3025
  continue;
2406
3026
  }
2407
3027
  if (entry.entryId && resolvedSlug !== "business-rules" && resolvedSlug !== "standards") {
2408
- results.push({
3028
+ results.push(buildBatchEntryFailure({
2409
3029
  entryIdx,
2410
3030
  name: entry.name,
2411
3031
  collection: resolvedSlug,
2412
- entryId: "",
2413
- ok: false,
2414
- autoLinks: 0,
2415
- advisedLinks: 0,
2416
- status: "draft",
2417
3032
  classifiedBy,
2418
3033
  confidence,
2419
3034
  confidenceTier,
2420
3035
  // BR-111
2421
3036
  error: `entryId only allowed for business-rules and standards. Omit for ${resolvedSlug}.`
2422
- });
3037
+ }));
2423
3038
  continue;
2424
3039
  }
2425
3040
  const data = buildDataFromFields(col.fields ?? [], profile.descriptionField, entry.description);
@@ -2484,8 +3099,22 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2484
3099
  }
2485
3100
  }
2486
3101
  canonicalizeSelects(data, col.fields ?? [], batchIsBet);
3102
+ const previewDuplicate = checkBatchPreviewDuplicate(previewDupTracker, {
3103
+ preview,
3104
+ entryIdx,
3105
+ name: entry.name,
3106
+ collection: resolvedSlug,
3107
+ callerEntryId: entry.entryId,
3108
+ classifiedBy,
3109
+ confidence,
3110
+ confidenceTier
3111
+ });
3112
+ if (previewDuplicate) {
3113
+ results.push(previewDuplicate);
3114
+ continue;
3115
+ }
2487
3116
  try {
2488
- const result2 = await kernelMutation("chain.createEntry", {
3117
+ const rawResult = await kernelMutation("chain.createEntry", {
2489
3118
  collectionSlug: resolvedSlug,
2490
3119
  entryId: entry.entryId ?? void 0,
2491
3120
  name: entry.name,
@@ -2503,13 +3132,30 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2503
3132
  ...entry.ownerTeamEntryId ? { ownerTeamEntryId: entry.ownerTeamEntryId } : {},
2504
3133
  ...entry.ownerRoleEntryId ? { ownerRoleEntryId: entry.ownerRoleEntryId } : {}
2505
3134
  });
3135
+ const previewWouldBlock = extractPreviewWouldBlock(rawResult, preview);
3136
+ const effectiveCollection = resolveEffectiveCollection(rawResult, preview, resolvedSlug);
3137
+ const result2 = rawResult;
3138
+ const postRoutingDuplicate = reconcileBatchPreviewDuplicate(previewDupTracker, {
3139
+ wouldCapture: Boolean(preview && previewWouldBlock && !previewWouldBlock.wouldBlock),
3140
+ effectiveCollection,
3141
+ entryIdx,
3142
+ name: entry.name,
3143
+ callerEntryId: entry.entryId,
3144
+ classifiedBy,
3145
+ confidence,
3146
+ confidenceTier
3147
+ });
3148
+ if (postRoutingDuplicate) {
3149
+ results.push(postRoutingDuplicate);
3150
+ continue;
3151
+ }
2506
3152
  const internalId = result2.docId;
2507
3153
  const finalEntryId = result2.entryId;
2508
3154
  const batchEntryWarnings = [
2509
3155
  ...batchDecomposeWarning ? [batchDecomposeWarning] : [],
2510
3156
  ...result2.warnings ?? []
2511
3157
  ];
2512
- resolveGapsForEntry(entry.name, result2.entryId);
3158
+ if (!preview) resolveGapsForEntry(entry.name, result2.entryId);
2513
3159
  const batchWasAutoCommittedServerSide = result2.status === "active";
2514
3160
  let finalStatus = batchWasAutoCommittedServerSide ? "committed" : "draft";
2515
3161
  let commitError;
@@ -2595,47 +3241,22 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2595
3241
  } catch {
2596
3242
  }
2597
3243
  }
2598
- let relationsCreatedCount = 0;
2599
- let relationsPreviewedCount = 0;
2600
- let relationsProposedCount = 0;
2601
- const relationsFailedList = [];
2602
- if (entry.relations && entry.relations.length > 0) {
2603
- for (const rel of entry.relations) {
2604
- try {
2605
- const relResult = await kernelMutation(
2606
- "chain.createEntryRelation",
2607
- {
2608
- fromEntryId: finalEntryId,
2609
- toEntryId: rel.to,
2610
- type: rel.type,
2611
- proposedBy: "user",
2612
- sessionId: agentId ?? void 0,
2613
- ...preview ? { preview: true } : {}
2614
- }
2615
- );
2616
- if (relResult?.preview) {
2617
- relationsPreviewedCount++;
2618
- } else if (relResult?.status === "agent_proposal_created") {
2619
- relationsProposedCount++;
2620
- } else {
2621
- relationsCreatedCount++;
2622
- }
2623
- } catch (relErr) {
2624
- const relMsg = relErr instanceof Error ? relErr.message : String(relErr);
2625
- relationsFailedList.push(`${rel.to} (${rel.type}): ${relMsg}`);
2626
- }
2627
- }
2628
- if (relationsFailedList.length > 0) {
2629
- batchEntryWarnings.push(`${relationsFailedList.length} inline relation(s) failed: ${relationsFailedList.join("; ")}`);
2630
- }
2631
- if (relationsPreviewedCount > 0) {
2632
- batchEntryWarnings.push(`${relationsPreviewedCount} inline relation(s) would be created (preview \u2014 no DB writes).`);
2633
- }
2634
- if (relationsProposedCount > 0) {
2635
- batchEntryWarnings.push(`${relationsProposedCount} inline relation(s) converted to an agent proposal (misuse pattern) \u2014 review in Cortex UI.`);
2636
- }
3244
+ const {
3245
+ relationsCreatedCount,
3246
+ relationsProposedCount,
3247
+ relationsNotValidatedCount,
3248
+ relationsFailedList
3249
+ } = await applyBatchInlineRelations(entry.relations, finalEntryId, preview, agentId);
3250
+ if (relationsFailedList.length > 0) {
3251
+ batchEntryWarnings.push(`${relationsFailedList.length} inline relation(s) failed: ${relationsFailedList.join("; ")}`);
3252
+ }
3253
+ if (relationsNotValidatedCount > 0) {
3254
+ batchEntryWarnings.push(`${relationsNotValidatedCount} inline relation(s) not validated in preview (target existence and relation policy are checked at capture).`);
3255
+ }
3256
+ if (relationsProposedCount > 0) {
3257
+ batchEntryWarnings.push(`${relationsProposedCount} inline relation(s) converted to an agent proposal (misuse pattern) \u2014 review in Cortex UI.`);
2637
3258
  }
2638
- if (autoCommitApplied && !batchWasAutoCommittedServerSide) {
3259
+ if (!preview && autoCommitApplied && !batchWasAutoCommittedServerSide) {
2639
3260
  try {
2640
3261
  const semanticConflicts = await discoverSemanticConflicts(entry.name, entry.description, resolvedSlug);
2641
3262
  const commitResult = await kernelMutation("chain.commitEntry", {
@@ -2672,7 +3293,9 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2672
3293
  results.push({
2673
3294
  entryIdx,
2674
3295
  name: entry.name,
2675
- collection: resolvedSlug,
3296
+ // P0 round 4 (fix 1/3, root): EFFECTIVE (post-routing) collection — see
3297
+ // `effectiveCollection`'s declaration above, ~2 screens up.
3298
+ collection: effectiveCollection,
2676
3299
  entryId: finalEntryId,
2677
3300
  ok: true,
2678
3301
  autoLinks: autoLinkCount,
@@ -2681,6 +3304,11 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2681
3304
  classifiedBy,
2682
3305
  confidence,
2683
3306
  confidenceTier,
3307
+ ...previewWouldBlock ? { wouldBlock: previewWouldBlock.wouldBlock } : {},
3308
+ ...previewWouldBlock?.blockingReason ? { blockingReason: previewWouldBlock.blockingReason } : {},
3309
+ // Fix 1 (TEN-2918 follow-up): not caller-supplied — the preview projection
3310
+ // must not report this predicted-but-duplicable ID as concrete.
3311
+ ...!entry.entryId ? { entryIdAssignedAtCapture: true } : {},
2684
3312
  ...commitError ? { commitError } : {},
2685
3313
  // WP-465 surface parity: thread full refusal payload for coherency-refused batch entries.
2686
3314
  ...commitRefusal ? { commitRefusal } : {},
@@ -2705,20 +3333,15 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2705
3333
  if (job) chunkBytes += prospectiveJobBytes;
2706
3334
  } catch (error) {
2707
3335
  const msg = error instanceof Error ? error.message : String(error);
2708
- results.push({
3336
+ results.push(buildBatchEntryFailure({
2709
3337
  entryIdx,
2710
3338
  name: entry.name,
2711
3339
  collection: resolvedSlug,
2712
- entryId: "",
2713
- ok: false,
2714
- autoLinks: 0,
2715
- advisedLinks: 0,
2716
- status: "draft",
2717
3340
  classifiedBy,
2718
3341
  confidence,
2719
3342
  confidenceTier,
2720
3343
  error: msg
2721
- });
3344
+ }));
2722
3345
  }
2723
3346
  }
2724
3347
  await flushPendingChunk(pendingFinish);
@@ -2734,6 +3357,9 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2734
3357
  data: `Batch complete. ${created.length} succeeded, ${failed.length} failed, ${skippedLowConfidence.length} skipped (low confidence).`,
2735
3358
  logger: "product-brain"
2736
3359
  });
3360
+ if (preview) {
3361
+ return buildBatchPreviewFromResults(created, failed, skippedLowConfidence, entries.length, entries, autoCommit);
3362
+ }
2737
3363
  const totalAutoLinks = created.reduce((sum, r) => sum + r.autoLinks, 0);
2738
3364
  const totalAdvisedLinks = created.reduce((sum, r) => sum + r.advisedLinks, 0);
2739
3365
  const byCollection = /* @__PURE__ */ new Map();
@@ -2992,92 +3618,6 @@ async function recordCommitFailure({
2992
3618
  }
2993
3619
  }
2994
3620
  }
2995
- var STOP_WORDS = /* @__PURE__ */ new Set([
2996
- "the",
2997
- "and",
2998
- "for",
2999
- "are",
3000
- "but",
3001
- "not",
3002
- "you",
3003
- "all",
3004
- "can",
3005
- "has",
3006
- "her",
3007
- "was",
3008
- "one",
3009
- "our",
3010
- "out",
3011
- "day",
3012
- "had",
3013
- "hot",
3014
- "how",
3015
- "its",
3016
- "may",
3017
- "new",
3018
- "now",
3019
- "old",
3020
- "see",
3021
- "way",
3022
- "who",
3023
- "did",
3024
- "get",
3025
- "let",
3026
- "say",
3027
- "she",
3028
- "too",
3029
- "use",
3030
- "from",
3031
- "have",
3032
- "been",
3033
- "each",
3034
- "that",
3035
- "this",
3036
- "with",
3037
- "will",
3038
- "they",
3039
- "what",
3040
- "when",
3041
- "make",
3042
- "like",
3043
- "long",
3044
- "look",
3045
- "many",
3046
- "some",
3047
- "them",
3048
- "than",
3049
- "most",
3050
- "only",
3051
- "over",
3052
- "such",
3053
- "into",
3054
- "also",
3055
- "back",
3056
- "just",
3057
- "much",
3058
- "must",
3059
- "name",
3060
- "very",
3061
- "your",
3062
- "after",
3063
- "which",
3064
- "their",
3065
- "about",
3066
- "would",
3067
- "there",
3068
- "should",
3069
- "could",
3070
- "other",
3071
- "these",
3072
- "first",
3073
- "being",
3074
- "those",
3075
- "still",
3076
- "where"
3077
- ]);
3078
- function tokenizeText(input) {
3079
- return input.toLowerCase().replace(/[^\p{L}\p{N}\s]+/gu, " ").split(/\s+/).filter(Boolean);
3080
- }
3081
3621
  async function runContradictionCheck(name, description) {
3082
3622
  const warnings = [];
3083
3623
  try {
@@ -3131,91 +3671,6 @@ async function discoverSemanticConflicts(name, description, collectionHint) {
3131
3671
  return [];
3132
3672
  }
3133
3673
  }
3134
- function verdictQualityPhrase(result2) {
3135
- const v = result2?.verdict;
3136
- const criteria = v?.criteria ?? [];
3137
- if (!v || criteria.length === 0) {
3138
- return "Quality: not evaluated (no rubric for this type).";
3139
- }
3140
- const total = criteria.length;
3141
- const passed = criteria.filter((c) => c.passed).length;
3142
- return v.passed ? `Quality: all ${total} rubric criteria pass.` : `Quality: ${passed}/${total} rubric criteria pass \u2014 see the coaching above.`;
3143
- }
3144
- function formatRubricCoaching(result2) {
3145
- const { verdict, rogerMartin } = result2;
3146
- if (!verdict || verdict.criteria.length === 0) return "";
3147
- const lines = ["## Semantic Quality"];
3148
- const failed = (verdict.criteria ?? []).filter((c) => !c.passed);
3149
- const total = verdict.criteria?.length ?? 0;
3150
- const passedCount = total - failed.length;
3151
- if (verdict.passed) {
3152
- lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier).`);
3153
- } else {
3154
- lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier)`);
3155
- lines.push("");
3156
- for (const c of verdict.criteria) {
3157
- const icon = c.passed ? "[x]" : "[ ]";
3158
- const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
3159
- lines.push(`${icon} ${c.id}${extra}`);
3160
- }
3161
- if (verdict.weakest) {
3162
- lines.push("");
3163
- lines.push(`**Coaching hint:** ${verdict.weakest.hint}`);
3164
- lines.push(`_Question to consider:_ ${verdict.weakest.questionTemplate}`);
3165
- }
3166
- }
3167
- if (rogerMartin) {
3168
- lines.push("");
3169
- lines.push("### Roger Martin Test");
3170
- if (rogerMartin.isStrategicChoice) {
3171
- lines.push("This principle passes \u2014 the opposite is a reasonable strategic choice.");
3172
- } else {
3173
- lines.push(`This principle may not be a strategic choice. ${rogerMartin.reasoning}`);
3174
- if (rogerMartin.suggestion) {
3175
- lines.push(`_Suggestion:_ ${rogerMartin.suggestion}`);
3176
- }
3177
- }
3178
- }
3179
- return lines.join("\n");
3180
- }
3181
- function formatRubricVerdictSection(verdict) {
3182
- if (!verdict || !verdict.criteria || verdict.criteria.length === 0) return "";
3183
- const lines = ["## Semantic Quality"];
3184
- const failed = verdict.criteria.filter((c) => !c.passed);
3185
- const total = verdict.criteria.length;
3186
- const passedCount = total - failed.length;
3187
- const durationSuffix = verdict.llmDurationMs ? ` in ${(verdict.llmDurationMs / 1e3).toFixed(1)}s` : "";
3188
- const statusNote = verdict.llmStatus === "pending" ? " \u2014 LLM evaluation in progress..." : verdict.llmStatus === "failed" ? ` \u2014 LLM evaluation failed${verdict.llmError ? `: ${verdict.llmError}` : ""}, showing heuristic results` : verdict.source === "llm" && durationSuffix ? ` \u2014 evaluated${durationSuffix}` : "";
3189
- if (failed.length === 0) {
3190
- lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation).${statusNote}`);
3191
- } else {
3192
- lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation)${statusNote}`);
3193
- lines.push("");
3194
- for (const c of verdict.criteria) {
3195
- const icon = c.passed ? "[x]" : "[ ]";
3196
- const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
3197
- lines.push(`${icon} ${c.id}${extra}`);
3198
- }
3199
- if (verdict.weakest) {
3200
- lines.push("");
3201
- lines.push(`**Top improvement:** ${verdict.weakest.hint}`);
3202
- }
3203
- }
3204
- if (verdict.rogerMartin) {
3205
- const rm = verdict.rogerMartin;
3206
- lines.push("");
3207
- lines.push("### Roger Martin Test");
3208
- if (rm.isStrategicChoice) {
3209
- lines.push(`This is a real strategic choice \u2014 the opposite is reasonable. ${rm.reasoning}`);
3210
- } else {
3211
- lines.push(`This may not be a strategic choice. ${rm.reasoning}`);
3212
- if (rm.suggestion) {
3213
- lines.push(`_Suggestion:_ ${rm.suggestion}`);
3214
- }
3215
- }
3216
- }
3217
- return lines.join("\n");
3218
- }
3219
3674
 
3220
3675
  // src/tools/conflict-preflight.ts
3221
3676
  async function runConflictPreflight(name, description, collectionHint) {
@@ -3271,44 +3726,44 @@ var WORKFLOW_STATUS_VALUES = [
3271
3726
  "evidenced"
3272
3727
  ];
3273
3728
  var LEGACY_WORKFLOW_STATUSES = new Set(WORKFLOW_STATUS_VALUES);
3274
- var updateEntrySchema = z3.object({
3275
- entryId: z3.string().describe("Entry ID to update, e.g. 'T-SUPPLIER', '<PREFIX>-<n>'"),
3276
- name: z3.string().optional().describe("New display name"),
3277
- status: z3.union([
3278
- z3.enum(["draft", "active", "deprecated", "archived"]),
3729
+ var updateEntrySchema = z5.object({
3730
+ entryId: z5.string().describe("Entry ID to update, e.g. 'T-SUPPLIER', '<PREFIX>-<n>'"),
3731
+ name: z5.string().optional().describe("New display name"),
3732
+ status: z5.union([
3733
+ z5.enum(["draft", "active", "deprecated", "archived"]),
3279
3734
  // BET-68 legacy shim: frozen historical workflow values still pass through
3280
3735
  // `status` (auto-routed with a warning) until the ~2026-09-03 sunset.
3281
- z3.enum(WORKFLOW_STATUS_VALUES)
3736
+ z5.enum(WORKFLOW_STATUS_VALUES)
3282
3737
  ]).optional().describe("Lifecycle status: draft | active | deprecated | archived. **Workflow values are deprecated here \u2014 use `workflowStatus` instead. Passing a workflow value as `status` will be auto-routed with a warning until 2026-09-03, then hard-errored.**"),
3283
- workflowStatus: z3.string().optional().describe("Collection workflow state. Valid values are collection-specific and server-owned \u2014 discover them via `collections action=describe` for the target collection. The server rejects invalid values and returns the valid set in the error."),
3284
- data: z3.record(z3.unknown()).optional().describe("Fields to update (merged with existing data)"),
3285
- order: z3.number().optional().describe("New sort order"),
3286
- canonicalKey: z3.string().optional().describe("Semantic type (e.g. 'decision', 'tension'). Only changeable on draft/uncommitted entries."),
3287
- autoPublish: z3.boolean().optional().default(false).describe("Only true when user explicitly asks to publish. Default false = draft. Never auto-publish without user confirmation."),
3288
- changeNote: z3.string().optional().describe("Strongly recommended: short human-readable rationale for WHY this change was made (e.g. 'Aligned description with F1-themed copy'). Surfaces in activity feed and pb get. If omitted, falls back to session purpose or auto-generated field summary."),
3289
- sourceRef: z3.string().optional().describe("URI or path of the source document backing this entry. Write-once: can only be set if currently empty."),
3290
- sourceExcerpt: z3.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Write-once: can only be set if currently empty."),
3738
+ workflowStatus: z5.string().optional().describe("Collection workflow state. Valid values are collection-specific and server-owned \u2014 discover them via `collections action=describe` for the target collection. The server rejects invalid values and returns the valid set in the error."),
3739
+ data: z5.record(z5.unknown()).optional().describe("Fields to update (merged with existing data)"),
3740
+ order: z5.number().optional().describe("New sort order"),
3741
+ canonicalKey: z5.string().optional().describe("Semantic type (e.g. 'decision', 'tension'). Only changeable on draft/uncommitted entries."),
3742
+ autoPublish: z5.boolean().optional().default(false).describe("Only true when user explicitly asks to publish. Default false = draft. Never auto-publish without user confirmation."),
3743
+ changeNote: z5.string().optional().describe("Strongly recommended: short human-readable rationale for WHY this change was made (e.g. 'Aligned description with F1-themed copy'). Surfaces in activity feed and pb get. If omitted, falls back to session purpose or auto-generated field summary."),
3744
+ sourceRef: z5.string().optional().describe("URI or path of the source document backing this entry. Write-once: can only be set if currently empty."),
3745
+ sourceExcerpt: z5.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Write-once: can only be set if currently empty."),
3291
3746
  // WP-465 slice ⑤ — relay-only (TEN-2233): validation/min-length/recording live in Convex.
3292
- steeringOverrideReason: z3.string().optional().describe("Typed override (\u226512 chars) that clears a steering coherency block on a misaligned governance write \u2014 always recorded with author attribution."),
3293
- coherencyAcknowledgement: z3.object({
3294
- response: z3.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
3295
- entryId: z3.string().optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
3296
- reason: z3.string().optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
3747
+ steeringOverrideReason: z5.string().optional().describe("Typed override (\u226512 chars) that clears a steering coherency block on a misaligned governance write \u2014 always recorded with author attribution."),
3748
+ coherencyAcknowledgement: z5.object({
3749
+ response: z5.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
3750
+ entryId: z5.string().optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
3751
+ reason: z5.string().optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
3297
3752
  }).optional().describe("Explicit response to a coherency challenge (standard/strict workspace modes). One acknowledgement per challenge per entry per session.")
3298
3753
  });
3299
- var getHistorySchema = z3.object({
3300
- entryId: z3.string().describe("Entry ID, e.g. 'T-SUPPLIER', '<PREFIX>-<n>'")
3754
+ var getHistorySchema = z5.object({
3755
+ entryId: z5.string().describe("Entry ID, e.g. 'T-SUPPLIER', '<PREFIX>-<n>'")
3301
3756
  });
3302
- var commitEntrySchema = z3.object({
3303
- entryId: z3.string().describe("Entry ID to accept, e.g. 'TEN-abc123', '<PREFIX>-<n>'"),
3757
+ var commitEntrySchema = z5.object({
3758
+ entryId: z5.string().describe("Entry ID to accept, e.g. 'TEN-abc123', '<PREFIX>-<n>'"),
3304
3759
  // WP-316 S3: Preview gate — dry-run mode. Returns would-succeed result, no DB writes.
3305
- preview: z3.boolean().optional().describe("If true, validates the accept without writing. Returns what would happen. Default false."),
3760
+ preview: z5.boolean().optional().describe("If true, validates the accept without writing. Returns what would happen. Default false."),
3306
3761
  // WP-465 slice ⑤ — relay-only (TEN-2233): validation/recording live in Convex.
3307
- steeringOverrideReason: z3.string().optional().describe("Typed override (\u226512 chars) that clears a steering coherency block at the publish chokepoint \u2014 always recorded with author attribution."),
3308
- coherencyAcknowledgement: z3.object({
3309
- response: z3.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
3310
- entryId: z3.string().optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
3311
- reason: z3.string().optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
3762
+ steeringOverrideReason: z5.string().optional().describe("Typed override (\u226512 chars) that clears a steering coherency block at the publish chokepoint \u2014 always recorded with author attribution."),
3763
+ coherencyAcknowledgement: z5.object({
3764
+ response: z5.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
3765
+ entryId: z5.string().optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
3766
+ reason: z5.string().optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
3312
3767
  }).optional().describe("Explicit response to a coherency challenge (standard/strict workspace modes).")
3313
3768
  });
3314
3769
  async function handleUpdateEntry({ entryId, name, status: rawStatus, workflowStatus: rawWorkflowStatus, data, order, canonicalKey, autoPublish, changeNote, sourceRef, sourceExcerpt, steeringOverrideReason, coherencyAcknowledgement }, toolName = "entries") {
@@ -3713,7 +4168,7 @@ No DB writes \u2014 call without \`preview:true\` to accept for real.` }],
3713
4168
  // src/tools/verify.ts
3714
4169
  import { existsSync as existsSync2, readFileSync } from "fs";
3715
4170
  import { resolve as resolve2 } from "path";
3716
- import { z as z4 } from "zod/v3";
4171
+ import { z as z6 } from "zod/v3";
3717
4172
 
3718
4173
  // src/lib/resolve-project-root.ts
3719
4174
  import { existsSync } from "fs";
@@ -3865,12 +4320,12 @@ function formatTrustReport(collection, entryCount, mappings, refs, fixes, mode,
3865
4320
  lines.push("", "---", `_Schema: ${schemaTableCount} tables parsed from convex/schema.ts. Project root: ${projectRoot}_`);
3866
4321
  return lines.join("\n");
3867
4322
  }
3868
- var verifySchema = z4.object({
3869
- collection: z4.string().max(200).default("glossary").describe("Collection slug to verify (default: glossary)"),
3870
- mode: z4.enum(["report", "fix"]).default("report").describe("'report' = read-only trust report. 'fix' = also update drifted codeMapping statuses.")
4323
+ var verifySchema = z6.object({
4324
+ collection: z6.string().max(200).default("glossary").describe("Collection slug to verify (default: glossary)"),
4325
+ mode: z6.enum(["report", "fix"]).default("report").describe("'report' = read-only trust report. 'fix' = also update drifted codeMapping statuses.")
3871
4326
  });
3872
- var verifyEntrySchema = z4.object({
3873
- entryId: z4.string().max(200).describe("Human entry ID (e.g. '<PREFIX>-<n>') to mark as verified")
4327
+ var verifyEntrySchema = z6.object({
4328
+ entryId: z6.string().max(200).describe("Human entry ID (e.g. '<PREFIX>-<n>') to mark as verified")
3874
4329
  });
3875
4330
  async function handleVerifyChain(server, { collection, mode }) {
3876
4331
  const projectRoot = resolveProjectRoot();
@@ -4087,10 +4542,10 @@ async function handleVerifyEntry({ entryId }) {
4087
4542
  }
4088
4543
 
4089
4544
  // src/tools/entry-move.ts
4090
- import { z as z5 } from "zod/v3";
4091
- var moveEntrySchema = z5.object({
4092
- entryId: z5.string().describe("Entry ID to move, e.g. '<PREFIX>-<n>'"),
4093
- toCollection: z5.string().describe("Target collection slug, e.g. 'decisions', 'architecture'")
4545
+ import { z as z7 } from "zod/v3";
4546
+ var moveEntrySchema = z7.object({
4547
+ entryId: z7.string().describe("Entry ID to move, e.g. '<PREFIX>-<n>'"),
4548
+ toCollection: z7.string().describe("Target collection slug, e.g. 'decisions', 'architecture'")
4094
4549
  });
4095
4550
  async function handleMoveEntry(entryId, toCollection) {
4096
4551
  try {
@@ -4201,89 +4656,89 @@ var ENTRIES_ACTIONS = [
4201
4656
  "move",
4202
4657
  "verify"
4203
4658
  ];
4204
- var coherencyAcknowledgementFlatSchema = z6.object({
4205
- response: z6.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
4206
- entryId: z6.string().max(200).optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
4207
- reason: z6.string().max(2e3).optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
4659
+ var coherencyAcknowledgementFlatSchema = z8.object({
4660
+ response: z8.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
4661
+ entryId: z8.string().max(200).optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
4662
+ reason: z8.string().max(2e3).optional().describe("Divergence rationale (required for 'diverged', \u226512 chars).")
4208
4663
  });
4209
- var entriesSchema = z6.object({
4210
- action: z6.enum(ENTRIES_ACTIONS).describe(
4664
+ var entriesSchema = z8.object({
4665
+ action: z8.enum(ENTRIES_ACTIONS).describe(
4211
4666
  "'list': browse entries with filters. 'get': fetch one entry by ID. 'batch': fetch multiple entries. 'search': full-text search. 'update': change fields on an existing entry (draft by default). 'commit': accept a draft entry onto the Chain. 'history': audit trail for an entry. 'move': reclassify an entry to a different collection. 'verify': mark an entry as verified (lightweight \u2014 no codebase scan; see `quality action=verify-chain` for the codebase-scanning check)."
4212
4667
  ),
4213
- entryId: z6.string().max(200).optional().describe(
4668
+ entryId: z8.string().max(200).optional().describe(
4214
4669
  "Entry ID, e.g. '<PREFIX>-<n>'. Required for: get, update, commit, history, move, verify."
4215
4670
  ),
4216
- entryIds: z6.array(z6.string().max(200)).min(1).max(20).optional().describe("Entry IDs for 'batch', e.g. ['TYPE-strategy', 'STR-jljeg7']"),
4217
- collection: z6.string().max(200).optional().describe("Collection slug \u2014 for 'list'/'search': scope filter, e.g. 'glossary', 'tracking-events'."),
4218
- status: z6.string().max(200).optional().describe(
4671
+ entryIds: z8.array(z8.string().max(200)).min(1).max(20).optional().describe("Entry IDs for 'batch', e.g. ['TYPE-strategy', 'STR-jljeg7']"),
4672
+ collection: z8.string().max(200).optional().describe("Collection slug \u2014 for 'list'/'search': scope filter, e.g. 'glossary', 'tracking-events'."),
4673
+ status: z8.string().max(200).optional().describe(
4219
4674
  "For 'list'/'search': filter string (draft | active | deprecated | archived). For 'update': lifecycle value to set (draft | active | deprecated | archived \u2014 legacy workflow values still route through here with a deprecation warning until 2026-09-03; use `workflowStatus` instead)."
4220
4675
  ),
4221
- tag: z6.string().max(200).optional().describe("For 'list': filter by internal tag."),
4222
- label: z6.string().max(200).optional().describe("For 'list': filter by label slug \u2014 matches entries across all collections."),
4223
- query: z6.string().min(2).max(500).optional().describe("For 'search': search text (min 2 characters)."),
4224
- name: z6.string().max(500).optional().describe("For 'update': new display name."),
4225
- workflowStatus: z6.string().max(200).optional().describe(
4676
+ tag: z8.string().max(200).optional().describe("For 'list': filter by internal tag."),
4677
+ label: z8.string().max(200).optional().describe("For 'list': filter by label slug \u2014 matches entries across all collections."),
4678
+ query: z8.string().min(2).max(500).optional().describe("For 'search': search text (min 2 characters)."),
4679
+ name: z8.string().max(500).optional().describe("For 'update': new display name."),
4680
+ workflowStatus: z8.string().max(200).optional().describe(
4226
4681
  "For 'update': collection workflow state. Valid values are collection-specific and server-owned \u2014 discover via `collections action=describe`. Invalid values are rejected with the valid set."
4227
4682
  ),
4228
- data: z6.record(z6.unknown()).optional().describe("For 'update': fields to update (merged with existing data)."),
4229
- order: z6.number().optional().describe("For 'update': new sort order."),
4230
- canonicalKey: z6.string().max(200).optional().describe(
4683
+ data: z8.record(z8.unknown()).optional().describe("For 'update': fields to update (merged with existing data)."),
4684
+ order: z8.number().optional().describe("For 'update': new sort order."),
4685
+ canonicalKey: z8.string().max(200).optional().describe(
4231
4686
  "For 'update': semantic type (e.g. 'decision', 'tension'). Only changeable on draft/uncommitted entries."
4232
4687
  ),
4233
- autoPublish: z6.boolean().optional().default(false).describe(
4688
+ autoPublish: z8.boolean().optional().default(false).describe(
4234
4689
  "For 'update': only true when the user explicitly asks to publish. Default false = draft."
4235
4690
  ),
4236
- changeNote: z6.string().max(2e3).optional().describe(
4691
+ changeNote: z8.string().max(2e3).optional().describe(
4237
4692
  "For 'update': short human-readable rationale for WHY this change was made. Surfaces in activity feed."
4238
4693
  ),
4239
- sourceRef: z6.string().max(2e3).optional().describe(
4694
+ sourceRef: z8.string().max(2e3).optional().describe(
4240
4695
  "For 'update': URI or path of the source document backing this entry. Write-once."
4241
4696
  ),
4242
- sourceExcerpt: z6.string().max(5e3).optional().describe(
4697
+ sourceExcerpt: z8.string().max(5e3).optional().describe(
4243
4698
  "For 'update': verbatim excerpt from the source backing this entry's claims. Write-once."
4244
4699
  ),
4245
- steeringOverrideReason: z6.string().max(2e3).optional().describe(
4700
+ steeringOverrideReason: z8.string().max(2e3).optional().describe(
4246
4701
  "For 'update'/'commit': typed override (\u226512 chars) that clears a steering coherency block."
4247
4702
  ),
4248
4703
  coherencyAcknowledgement: coherencyAcknowledgementFlatSchema.optional().describe(
4249
4704
  "For 'update'/'commit': explicit response to a coherency challenge (standard/strict workspace modes)."
4250
4705
  ),
4251
- preview: z6.boolean().optional().describe(
4706
+ preview: z8.boolean().optional().describe(
4252
4707
  "For 'commit': if true, validates the accept without writing \u2014 returns what would happen."
4253
4708
  ),
4254
- toCollection: z6.string().max(200).optional().describe("For 'move': target collection slug, e.g. 'decisions', 'architecture'.")
4709
+ toCollection: z8.string().max(200).optional().describe("For 'move': target collection slug, e.g. 'decisions', 'architecture'.")
4255
4710
  });
4256
- var entriesListVariant = z6.object({
4257
- action: z6.literal("list"),
4258
- collection: z6.string().max(200).optional(),
4259
- status: z6.string().max(200).optional(),
4260
- tag: z6.string().max(200).optional(),
4261
- label: z6.string().max(200).optional()
4711
+ var entriesListVariant = z8.object({
4712
+ action: z8.literal("list"),
4713
+ collection: z8.string().max(200).optional(),
4714
+ status: z8.string().max(200).optional(),
4715
+ tag: z8.string().max(200).optional(),
4716
+ label: z8.string().max(200).optional()
4262
4717
  });
4263
- var entriesGetVariant = z6.object({
4264
- action: z6.literal("get"),
4265
- entryId: z6.string().max(200)
4718
+ var entriesGetVariant = z8.object({
4719
+ action: z8.literal("get"),
4720
+ entryId: z8.string().max(200)
4266
4721
  });
4267
- var entriesBatchVariant = z6.object({
4268
- action: z6.literal("batch"),
4269
- entryIds: z6.array(z6.string().max(200)).min(1).max(20)
4722
+ var entriesBatchVariant = z8.object({
4723
+ action: z8.literal("batch"),
4724
+ entryIds: z8.array(z8.string().max(200)).min(1).max(20)
4270
4725
  });
4271
- var entriesSearchVariant = z6.object({
4272
- action: z6.literal("search"),
4273
- query: z6.string().min(2).max(500),
4274
- collection: z6.string().max(200).optional(),
4275
- status: z6.string().max(200).optional()
4726
+ var entriesSearchVariant = z8.object({
4727
+ action: z8.literal("search"),
4728
+ query: z8.string().min(2).max(500),
4729
+ collection: z8.string().max(200).optional(),
4730
+ status: z8.string().max(200).optional()
4276
4731
  });
4277
- var entriesUpdateVariant = updateEntrySchema.extend({ action: z6.literal("update") });
4278
- var entriesCommitVariant = commitEntrySchema.extend({ action: z6.literal("commit") });
4279
- var entriesHistoryVariant = getHistorySchema.extend({ action: z6.literal("history") });
4280
- var entriesMoveVariant = z6.object({
4281
- action: z6.literal("move"),
4282
- entryId: z6.string().max(200),
4283
- toCollection: z6.string().max(200)
4732
+ var entriesUpdateVariant = updateEntrySchema.extend({ action: z8.literal("update") });
4733
+ var entriesCommitVariant = commitEntrySchema.extend({ action: z8.literal("commit") });
4734
+ var entriesHistoryVariant = getHistorySchema.extend({ action: z8.literal("history") });
4735
+ var entriesMoveVariant = z8.object({
4736
+ action: z8.literal("move"),
4737
+ entryId: z8.string().max(200),
4738
+ toCollection: z8.string().max(200)
4284
4739
  });
4285
- var entriesVerifyVariant = verifyEntrySchema.extend({ action: z6.literal("verify") });
4286
- var entriesActionUnion = z6.discriminatedUnion("action", [
4740
+ var entriesVerifyVariant = verifyEntrySchema.extend({ action: z8.literal("verify") });
4741
+ var entriesActionUnion = z8.discriminatedUnion("action", [
4287
4742
  entriesListVariant,
4288
4743
  entriesGetVariant,
4289
4744
  entriesBatchVariant,
@@ -4305,15 +4760,15 @@ var ENTRIES_ACTION_SPECS = {
4305
4760
  move: { params: ["entryId", "toCollection"], description: "Both entryId and toCollection are required." },
4306
4761
  verify: { params: ["entryId"], description: "entryId is required." }
4307
4762
  };
4308
- var entriesGetOutputSchema = z6.object({
4309
- entryId: z6.string(),
4310
- name: z6.string(),
4311
- collection: z6.string(),
4312
- status: z6.string(),
4313
- capturedAt: z6.number().optional(),
4314
- origin: z6.string().optional(),
4315
- originDetail: z6.string().optional(),
4316
- verificationStatus: z6.string().optional(),
4763
+ var entriesGetOutputSchema = z8.object({
4764
+ entryId: z8.string(),
4765
+ name: z8.string(),
4766
+ collection: z8.string(),
4767
+ status: z8.string(),
4768
+ capturedAt: z8.number().optional(),
4769
+ origin: z8.string().optional(),
4770
+ originDetail: z8.string().optional(),
4771
+ verificationStatus: z8.string().optional(),
4317
4772
  // Attestation-model finding (PR #341 review): the server's honest verifier label and
4318
4773
  // derived attestation strength/basis — connectors NEVER re-derive strength (spec §5),
4319
4774
  // they only render what chain.getEntry ships. Mirrors packages/cli EntryFromApi.
@@ -4322,72 +4777,72 @@ var entriesGetOutputSchema = z6.object({
4322
4777
  // attestation.ts's AttestationStrength SSOT (allowlisted in Check D —
4323
4778
  // scripts/check-collection-ssot.mjs's CHECK_D_ALLOWLIST — with the full
4324
4779
  // reasoning for why this can't just import that module). Update both together.
4325
- verifiedBy: z6.string().optional(),
4326
- attestation: z6.object({
4327
- strength: z6.enum(["human-direct", "delegated", "system", "unattested"]),
4328
- basis: z6.string().optional()
4780
+ verifiedBy: z8.string().optional(),
4781
+ attestation: z8.object({
4782
+ strength: z8.enum(["human-direct", "delegated", "system", "unattested"]),
4783
+ basis: z8.string().optional()
4329
4784
  }).optional(),
4330
- sourceRef: z6.string().optional(),
4331
- sourceExcerpt: z6.string().optional(),
4332
- why: z6.string().optional(),
4785
+ sourceRef: z8.string().optional(),
4786
+ sourceExcerpt: z8.string().optional(),
4787
+ why: z8.string().optional(),
4333
4788
  // TEN-2191: quality of the captured WHY — 'rationale' | 'missing' | 'restated'.
4334
- whyQuality: z6.enum(["rationale", "missing", "restated"]).optional(),
4335
- data: z6.record(z6.unknown()).optional(),
4336
- relations: z6.array(z6.object({
4337
- entryId: z6.string().optional(),
4338
- name: z6.string(),
4339
- type: z6.string(),
4340
- direction: z6.string()
4789
+ whyQuality: z8.enum(["rationale", "missing", "restated"]).optional(),
4790
+ data: z8.record(z8.unknown()).optional(),
4791
+ relations: z8.array(z8.object({
4792
+ entryId: z8.string().optional(),
4793
+ name: z8.string(),
4794
+ type: z8.string(),
4795
+ direction: z8.string()
4341
4796
  })).optional(),
4342
- labels: z6.array(z6.string()).optional()
4797
+ labels: z8.array(z8.string()).optional()
4343
4798
  }).passthrough();
4344
- var entriesListOutputSchema = z6.object({
4345
- entries: z6.array(z6.object({
4346
- entryId: z6.string(),
4347
- name: z6.string(),
4348
- collection: z6.string(),
4349
- status: z6.string()
4799
+ var entriesListOutputSchema = z8.object({
4800
+ entries: z8.array(z8.object({
4801
+ entryId: z8.string(),
4802
+ name: z8.string(),
4803
+ collection: z8.string(),
4804
+ status: z8.string()
4350
4805
  })),
4351
- total: z6.number()
4806
+ total: z8.number()
4352
4807
  });
4353
- var entriesSearchOutputSchema = z6.object({
4354
- results: z6.array(z6.object({
4355
- entryId: z6.string(),
4356
- name: z6.string(),
4357
- collection: z6.string(),
4358
- status: z6.string(),
4359
- score: z6.number().optional()
4808
+ var entriesSearchOutputSchema = z8.object({
4809
+ results: z8.array(z8.object({
4810
+ entryId: z8.string(),
4811
+ name: z8.string(),
4812
+ collection: z8.string(),
4813
+ status: z8.string(),
4814
+ score: z8.number().optional()
4360
4815
  })),
4361
- total: z6.number(),
4362
- query: z6.string()
4816
+ total: z8.number(),
4817
+ query: z8.string()
4363
4818
  });
4364
- var entriesBatchOutputSchema = z6.object({
4365
- entries: z6.array(z6.object({
4366
- entryId: z6.string(),
4367
- name: z6.string(),
4368
- collection: z6.string(),
4369
- status: z6.string(),
4370
- capturedAt: z6.number().optional(),
4371
- origin: z6.string().optional(),
4372
- originDetail: z6.string().optional(),
4373
- verificationStatus: z6.string().optional(),
4819
+ var entriesBatchOutputSchema = z8.object({
4820
+ entries: z8.array(z8.object({
4821
+ entryId: z8.string(),
4822
+ name: z8.string(),
4823
+ collection: z8.string(),
4824
+ status: z8.string(),
4825
+ capturedAt: z8.number().optional(),
4826
+ origin: z8.string().optional(),
4827
+ originDetail: z8.string().optional(),
4828
+ verificationStatus: z8.string().optional(),
4374
4829
  // Attestation-model finding (PR #341 review): mirror entriesGetOutputSchema — batch
4375
4830
  // entries now carry the same honest verifiedBy/attestation fields. Literal set is
4376
4831
  // the same hand-kept SSOT mirror — see entriesGetOutputSchema's attestation
4377
4832
  // comment above for the full Check D / kernel-import reasoning.
4378
- verifiedBy: z6.string().optional(),
4379
- attestation: z6.object({
4380
- strength: z6.enum(["human-direct", "delegated", "system", "unattested"]),
4381
- basis: z6.string().optional()
4833
+ verifiedBy: z8.string().optional(),
4834
+ attestation: z8.object({
4835
+ strength: z8.enum(["human-direct", "delegated", "system", "unattested"]),
4836
+ basis: z8.string().optional()
4382
4837
  }).optional(),
4383
- sourceRef: z6.string().optional(),
4384
- sourceExcerpt: z6.string().optional(),
4838
+ sourceRef: z8.string().optional(),
4839
+ sourceExcerpt: z8.string().optional(),
4385
4840
  // TEN-2191: mirror entriesGetOutputSchema — batch entries now carry why/whyQuality.
4386
- why: z6.string().optional(),
4387
- whyQuality: z6.enum(["rationale", "missing", "restated"]).optional(),
4388
- data: z6.record(z6.unknown()).optional()
4841
+ why: z8.string().optional(),
4842
+ whyQuality: z8.enum(["rationale", "missing", "restated"]).optional(),
4843
+ data: z8.record(z8.unknown()).optional()
4389
4844
  }).passthrough()),
4390
- total: z6.number()
4845
+ total: z8.number()
4391
4846
  });
4392
4847
  function registerEntriesTools(server) {
4393
4848
  const entriesHandlers = {
@@ -4779,41 +5234,41 @@ ${footer}` }],
4779
5234
  }
4780
5235
 
4781
5236
  // src/tools/relations.ts
4782
- import { z as z8 } from "zod/v3";
5237
+ import { z as z10 } from "zod/v3";
4783
5238
 
4784
5239
  // src/tools/graph.ts
4785
- import { z as z7 } from "zod/v3";
5240
+ import { z as z9 } from "zod/v3";
4786
5241
  var GRAPH_ACTIONS = ["find", "suggest"];
4787
- var graphSchema = z7.object({
4788
- action: z7.enum(GRAPH_ACTIONS).describe(
5242
+ var graphSchema = z9.object({
5243
+ action: z9.enum(GRAPH_ACTIONS).describe(
4789
5244
  "'find': traverse relations from an entry (graph walk). 'suggest': discover potential connections for an entry."
4790
5245
  ),
4791
- entryId: z7.string().max(200).describe("Entry ID, e.g. '<PREFIX>-<n>'"),
4792
- direction: z7.enum(["incoming", "outgoing", "both"]).default("both").optional().describe("For find: 'incoming' = what references this, 'outgoing' = what this references"),
4793
- limit: z7.number().min(1).max(20).default(10).optional().describe("For suggest: max suggestions to return"),
4794
- depth: z7.number().min(1).max(3).default(2).optional().describe("For suggest: graph traversal depth")
5246
+ entryId: z9.string().max(200).describe("Entry ID, e.g. '<PREFIX>-<n>'"),
5247
+ direction: z9.enum(["incoming", "outgoing", "both"]).default("both").optional().describe("For find: 'incoming' = what references this, 'outgoing' = what this references"),
5248
+ limit: z9.number().min(1).max(20).default(10).optional().describe("For suggest: max suggestions to return"),
5249
+ depth: z9.number().min(1).max(3).default(2).optional().describe("For suggest: graph traversal depth")
4795
5250
  });
4796
- var graphFindOutputSchema = z7.object({
4797
- entryId: z7.string(),
4798
- relations: z7.array(z7.object({
4799
- entryId: z7.string().optional(),
4800
- name: z7.string(),
4801
- type: z7.string(),
4802
- direction: z7.enum(["outgoing", "incoming"])
5251
+ var graphFindOutputSchema = z9.object({
5252
+ entryId: z9.string(),
5253
+ relations: z9.array(z9.object({
5254
+ entryId: z9.string().optional(),
5255
+ name: z9.string(),
5256
+ type: z9.string(),
5257
+ direction: z9.enum(["outgoing", "incoming"])
4803
5258
  })),
4804
- total: z7.number()
5259
+ total: z9.number()
4805
5260
  });
4806
- var graphSuggestOutputSchema = z7.object({
4807
- entryId: z7.string(),
4808
- suggestions: z7.array(z7.object({
4809
- targetEntryId: z7.string().optional(),
4810
- targetName: z7.string(),
4811
- relationType: z7.string(),
4812
- direction: z7.string(),
4813
- confidence: z7.number(),
4814
- reason: z7.string()
5261
+ var graphSuggestOutputSchema = z9.object({
5262
+ entryId: z9.string(),
5263
+ suggestions: z9.array(z9.object({
5264
+ targetEntryId: z9.string().optional(),
5265
+ targetName: z9.string(),
5266
+ relationType: z9.string(),
5267
+ direction: z9.string(),
5268
+ confidence: z9.number(),
5269
+ reason: z9.string()
4815
5270
  })),
4816
- total: z7.number()
5271
+ total: z9.number()
4817
5272
  });
4818
5273
  async function handleFind(entryId, direction) {
4819
5274
  const relations = await kernelQuery("chain.listEntryRelations", { entryId });
@@ -5004,64 +5459,64 @@ async function handleSuggest(entryId, limit, depth) {
5004
5459
 
5005
5460
  // src/tools/relations.ts
5006
5461
  var RELATIONS_ACTIONS = ["create", "batch-create", "dismiss", "delete", "find", "suggest"];
5007
- var relationItemSchema = z8.object({
5008
- from: z8.string().max(200),
5009
- to: z8.string().max(200),
5010
- type: z8.string().max(200)
5462
+ var relationItemSchema = z10.object({
5463
+ from: z10.string().max(200),
5464
+ to: z10.string().max(200),
5465
+ type: z10.string().max(200)
5011
5466
  });
5012
- var relationsSchema = z8.object({
5013
- action: z8.enum(RELATIONS_ACTIONS).describe(
5467
+ var relationsSchema = z10.object({
5468
+ action: z10.enum(RELATIONS_ACTIONS).describe(
5014
5469
  "'create': link two entries. 'batch-create': create multiple relations (validates every item before writing any). 'dismiss': record that a suggestion was not relevant. 'delete': remove a relation. 'find': traverse relations from an entry (graph walk, absorbs graph action=find). 'suggest': discover potential connections for an entry (absorbs graph action=suggest)."
5015
5470
  ),
5016
- from: z8.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': source entry ID."),
5017
- to: z8.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': target entry ID."),
5018
- type: z8.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': relation type."),
5019
- score: z8.number().optional().describe("For 'dismiss': suggestion score from action=suggest."),
5020
- relations: z8.array(relationItemSchema).min(1).max(20).optional().describe("For 'batch-create': array of {from, to, type}."),
5471
+ from: z10.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': source entry ID."),
5472
+ to: z10.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': target entry ID."),
5473
+ type: z10.string().max(200).optional().describe("For 'create'/'dismiss'/'delete': relation type."),
5474
+ score: z10.number().optional().describe("For 'dismiss': suggestion score from action=suggest."),
5475
+ relations: z10.array(relationItemSchema).min(1).max(20).optional().describe("For 'batch-create': array of {from, to, type}."),
5021
5476
  // WP-316 S3: Preview gate — dry-run mode for action=create.
5022
- preview: z8.boolean().optional().describe("For 'create': if true, validates the relation without writing. Returns what would happen. Default false."),
5023
- entryId: z8.string().max(200).optional().describe("For 'find'/'suggest': entry ID, e.g. '<PREFIX>-<n>'."),
5024
- direction: z8.enum(["incoming", "outgoing", "both"]).optional().describe("For 'find': 'incoming' = what references this, 'outgoing' = what this references. Default 'both'."),
5025
- limit: z8.number().min(1).max(20).optional().describe("For 'suggest': max suggestions to return. Default 10."),
5026
- depth: z8.number().min(1).max(3).optional().describe("For 'suggest': graph traversal depth. Default 2.")
5477
+ preview: z10.boolean().optional().describe("For 'create': if true, validates the relation without writing. Returns what would happen. Default false."),
5478
+ entryId: z10.string().max(200).optional().describe("For 'find'/'suggest': entry ID, e.g. '<PREFIX>-<n>'."),
5479
+ direction: z10.enum(["incoming", "outgoing", "both"]).optional().describe("For 'find': 'incoming' = what references this, 'outgoing' = what this references. Default 'both'."),
5480
+ limit: z10.number().min(1).max(20).optional().describe("For 'suggest': max suggestions to return. Default 10."),
5481
+ depth: z10.number().min(1).max(3).optional().describe("For 'suggest': graph traversal depth. Default 2.")
5027
5482
  });
5028
- var relationsCreateVariant = z8.object({
5029
- action: z8.literal("create"),
5030
- from: z8.string().max(200),
5031
- to: z8.string().max(200),
5032
- type: z8.string().max(200),
5033
- score: z8.number().optional(),
5034
- preview: z8.boolean().optional()
5483
+ var relationsCreateVariant = z10.object({
5484
+ action: z10.literal("create"),
5485
+ from: z10.string().max(200),
5486
+ to: z10.string().max(200),
5487
+ type: z10.string().max(200),
5488
+ score: z10.number().optional(),
5489
+ preview: z10.boolean().optional()
5035
5490
  });
5036
- var relationsBatchCreateVariant = z8.object({
5037
- action: z8.literal("batch-create"),
5038
- relations: z8.array(relationItemSchema).min(1).max(20)
5491
+ var relationsBatchCreateVariant = z10.object({
5492
+ action: z10.literal("batch-create"),
5493
+ relations: z10.array(relationItemSchema).min(1).max(20)
5039
5494
  });
5040
- var relationsDismissVariant = z8.object({
5041
- action: z8.literal("dismiss"),
5042
- from: z8.string().max(200),
5043
- to: z8.string().max(200),
5044
- type: z8.string().max(200).optional(),
5045
- score: z8.number().optional()
5495
+ var relationsDismissVariant = z10.object({
5496
+ action: z10.literal("dismiss"),
5497
+ from: z10.string().max(200),
5498
+ to: z10.string().max(200),
5499
+ type: z10.string().max(200).optional(),
5500
+ score: z10.number().optional()
5046
5501
  });
5047
- var relationsDeleteVariant = z8.object({
5048
- action: z8.literal("delete"),
5049
- from: z8.string().max(200),
5050
- to: z8.string().max(200),
5051
- type: z8.string().max(200)
5502
+ var relationsDeleteVariant = z10.object({
5503
+ action: z10.literal("delete"),
5504
+ from: z10.string().max(200),
5505
+ to: z10.string().max(200),
5506
+ type: z10.string().max(200)
5052
5507
  });
5053
- var relationsFindVariant = z8.object({
5054
- action: z8.literal("find"),
5055
- entryId: z8.string().max(200),
5056
- direction: z8.enum(["incoming", "outgoing", "both"]).optional().default("both")
5508
+ var relationsFindVariant = z10.object({
5509
+ action: z10.literal("find"),
5510
+ entryId: z10.string().max(200),
5511
+ direction: z10.enum(["incoming", "outgoing", "both"]).optional().default("both")
5057
5512
  });
5058
- var relationsSuggestVariant = z8.object({
5059
- action: z8.literal("suggest"),
5060
- entryId: z8.string().max(200),
5061
- limit: z8.number().min(1).max(20).optional().default(10),
5062
- depth: z8.number().min(1).max(3).optional().default(2)
5513
+ var relationsSuggestVariant = z10.object({
5514
+ action: z10.literal("suggest"),
5515
+ entryId: z10.string().max(200),
5516
+ limit: z10.number().min(1).max(20).optional().default(10),
5517
+ depth: z10.number().min(1).max(3).optional().default(2)
5063
5518
  });
5064
- var relationsActionUnion = z8.discriminatedUnion("action", [
5519
+ var relationsActionUnion = z10.discriminatedUnion("action", [
5065
5520
  relationsCreateVariant,
5066
5521
  relationsBatchCreateVariant,
5067
5522
  relationsDismissVariant,
@@ -5345,19 +5800,19 @@ async function handleDelete(from, to, type) {
5345
5800
  }
5346
5801
 
5347
5802
  // src/tools/context.ts
5348
- import { z as z10 } from "zod/v3";
5803
+ import { z as z12 } from "zod/v3";
5349
5804
 
5350
5805
  // src/tools/documents.ts
5351
- import { z as z9 } from "zod/v3";
5806
+ import { z as z11 } from "zod/v3";
5352
5807
  var DOCUMENTS_ACTIONS = ["get-last-verified-brief"];
5353
- var documentsSchema = z9.object({
5354
- action: z9.enum(DOCUMENTS_ACTIONS).describe(
5808
+ var documentsSchema = z11.object({
5809
+ action: z11.enum(DOCUMENTS_ACTIONS).describe(
5355
5810
  "'get-last-verified-brief': fetch the most recent verified brief snapshot for a (templateId, scopeKey) pair. Returns the verified summary so agents can build delta narratives ('since you last verified, X workstreams advanced')."
5356
5811
  ),
5357
- templateId: z9.string().max(200).describe(
5812
+ templateId: z11.string().max(200).describe(
5358
5813
  "Brief template identifier \u2014 currently 'steering-brief' is the only registered template."
5359
5814
  ),
5360
- scopeKey: z9.string().max(200).describe(
5815
+ scopeKey: z11.string().max(200).describe(
5361
5816
  "Canonical scope key. Use 'workspace:<workspaceId>' for the full workspace brief, or 'initiative:<INI-ID>' for an initiative-scoped brief. The same formula is applied at write time (chainwork/docKernel/scopeKey.ts), so passing the wrong shape returns exists:false."
5362
5817
  )
5363
5818
  });
@@ -5437,89 +5892,89 @@ function epistemicCollectionHint(collectionName) {
5437
5892
  return "";
5438
5893
  }
5439
5894
  var CONTEXT_ACTIONS = ["gather", "build", "neighborhood", "changes", "chain", "cross-cut", "incremental", "brief", "last-verified-brief"];
5440
- var contextSchema = z10.object({
5895
+ var contextSchema = z12.object({
5441
5896
  // provenance: neighborhood BET-142; changes/chain/cross-cut/incremental/brief BET-239 (E4, E6)
5442
- action: z10.enum(CONTEXT_ACTIONS).describe(
5897
+ action: z12.enum(CONTEXT_ACTIONS).describe(
5443
5898
  "'gather': assemble knowledge context (entry graph, task auto-load, journey mode, or graph mode). 'build': structured build spec for an entry. 'neighborhood': typed graph neighborhood for an entry \u2014 blocking chain, dependencies, parent context, tensions, staleness. 'changes': entries modified and relations created since a timestamp. Requires 'since' parameter. 'chain': directed traversal along one relation type to depth 4. Requires entryId. Optional: direction, relationType, maxHops (1-4). 'cross-cut': structural aggregation \u2014 all relations of a given type grouped by source collection. Requires 'relationType' parameter. 'incremental': delta since last brief run for a skill. Requires 'skill' parameter. Returns only entries changed since the skill's last brief. 'brief': compound intelligence query. Requires 'briefType' parameter: 'steering' (changes + structure + delta + readiness), 'confidence' (changes + active bets + tensions), or 'delta' (changes + relations since timestamp). Optional 'since' for delta type. 'last-verified-brief': fetch the most recent verified brief snapshot for a (templateId, scopeKey) pair (absorbs documents action=get-last-verified-brief). Requires templateId and scopeKey."
5444
5899
  ),
5445
- entryId: z10.string().max(200).optional().describe("For 'build'/'neighborhood'/'chain': entry ID, e.g. '<PREFIX>-<n>'. For 'gather': optional entry ID for entry-graph mode."),
5446
- mapEntryId: z10.string().max(200).optional().describe(
5900
+ entryId: z12.string().max(200).optional().describe("For 'build'/'neighborhood'/'chain': entry ID, e.g. '<PREFIX>-<n>'. For 'gather': optional entry ID for entry-graph mode."),
5901
+ mapEntryId: z12.string().max(200).optional().describe(
5447
5902
  "For 'gather': journey map entry ID for journey-aware context. Returns context organised by journey stage. Takes precedence over entryId when both are supplied. Example: '<PREFIX>-<n>'."
5448
5903
  ),
5449
- task: z10.string().max(2e3).optional().describe("For 'gather': natural-language task description for loading task-relevant governance, binding constraints, and supporting context."),
5450
- since: z10.string().max(200).optional().describe(
5904
+ task: z12.string().max(2e3).optional().describe("For 'gather': natural-language task description for loading task-relevant governance, binding constraints, and supporting context."),
5905
+ since: z12.string().max(200).optional().describe(
5451
5906
  "For 'changes': ISO 8601 timestamp \u2014 returns entries/relations modified since this time. For 'brief' briefType='delta': optional custom timestamp. Example: '2026-03-24T00:00:00Z'."
5452
5907
  ),
5453
- direction: z10.enum(["outgoing", "incoming"]).default("outgoing").optional().describe("For 'chain' action: traversal direction. 'outgoing' follows relations from source, 'incoming' follows relations to source. Default: outgoing."),
5454
- relationType: z10.string().max(200).optional().describe(
5908
+ direction: z12.enum(["outgoing", "incoming"]).default("outgoing").optional().describe("For 'chain' action: traversal direction. 'outgoing' follows relations from source, 'incoming' follows relations to source. Default: outgoing."),
5909
+ relationType: z12.string().max(200).optional().describe(
5455
5910
  "Relation type filter. For 'chain': optional filter to traverse only this relation type. For 'cross-cut': required \u2014 scans all relations of this type across the workspace. Examples: 'part_of', 'informs', 'governs', 'blocks', 'depends_on'."
5456
5911
  ),
5457
- mode: z10.enum(["search", "graph"]).default("search").optional().describe("For gather: 'search' (default) or 'graph' (enhanced with provenance paths). Ignored when mapEntryId is provided."),
5458
- maxHops: z10.number().min(1).max(4).default(2).describe("Relation traversal depth (1=direct only, 2=default, 3=wide net, 4=deep chain walk)"),
5459
- maxResults: z10.number().min(1).max(25).default(10).optional().describe("Max entries to return in gather task mode (default 10)"),
5460
- strategy: z10.enum(["hybrid", "keyword"]).default("keyword").optional().describe("Seed strategy for task-based gather: 'keyword' (FTS only, default) or 'hybrid' (vector + FTS). Only affects task mode."),
5461
- skill: z10.string().max(200).optional().describe(
5912
+ mode: z12.enum(["search", "graph"]).default("search").optional().describe("For gather: 'search' (default) or 'graph' (enhanced with provenance paths). Ignored when mapEntryId is provided."),
5913
+ maxHops: z12.number().min(1).max(4).default(2).describe("Relation traversal depth (1=direct only, 2=default, 3=wide net, 4=deep chain walk)"),
5914
+ maxResults: z12.number().min(1).max(25).default(10).optional().describe("Max entries to return in gather task mode (default 10)"),
5915
+ strategy: z12.enum(["hybrid", "keyword"]).default("keyword").optional().describe("Seed strategy for task-based gather: 'keyword' (FTS only, default) or 'hybrid' (vector + FTS). Only affects task mode."),
5916
+ skill: z12.string().max(200).optional().describe(
5462
5917
  "Skill name for 'incremental' action \u2014 identifies which skill's brief history to compare against. Examples: 'preflight', 'shaping', 'review'. Required when action is 'incremental'."
5463
5918
  ),
5464
- briefType: z10.enum(["steering", "confidence", "delta"]).optional().describe(
5919
+ briefType: z12.enum(["steering", "confidence", "delta"]).optional().describe(
5465
5920
  "Compound query type for 'brief' action. 'steering': 7d changes + structural aggregation (part_of, depends_on, constrains) + incremental delta + workspace readiness. 'confidence': 7d changes + active bets summary + active tensions breakdown. 'delta': changes + relations since a custom timestamp (use 'since' param). Required when action is 'brief'."
5466
5921
  ),
5467
- templateId: z10.string().max(200).optional().describe(
5922
+ templateId: z12.string().max(200).optional().describe(
5468
5923
  "For 'last-verified-brief': brief template identifier \u2014 currently 'steering-brief' is the only registered template."
5469
5924
  ),
5470
- scopeKey: z10.string().max(200).optional().describe(
5925
+ scopeKey: z12.string().max(200).optional().describe(
5471
5926
  "For 'last-verified-brief': canonical scope key \u2014 'workspace:<workspaceId>' or 'initiative:<INI-ID>'."
5472
5927
  )
5473
5928
  });
5474
- var contextGatherVariant = z10.object({
5475
- action: z10.literal("gather"),
5476
- entryId: z10.string().max(200).optional(),
5477
- mapEntryId: z10.string().max(200).optional(),
5478
- task: z10.string().max(2e3).optional(),
5479
- mode: z10.enum(["search", "graph"]).optional().default("search"),
5480
- maxHops: z10.number().min(1).max(4).optional().default(2),
5481
- maxResults: z10.number().min(1).max(25).optional().default(10),
5482
- strategy: z10.enum(["hybrid", "keyword"]).optional().default("keyword")
5929
+ var contextGatherVariant = z12.object({
5930
+ action: z12.literal("gather"),
5931
+ entryId: z12.string().max(200).optional(),
5932
+ mapEntryId: z12.string().max(200).optional(),
5933
+ task: z12.string().max(2e3).optional(),
5934
+ mode: z12.enum(["search", "graph"]).optional().default("search"),
5935
+ maxHops: z12.number().min(1).max(4).optional().default(2),
5936
+ maxResults: z12.number().min(1).max(25).optional().default(10),
5937
+ strategy: z12.enum(["hybrid", "keyword"]).optional().default("keyword")
5483
5938
  });
5484
- var contextBuildVariant = z10.object({
5485
- action: z10.literal("build"),
5486
- entryId: z10.string().max(200),
5487
- maxHops: z10.number().min(1).max(4).optional().default(2)
5939
+ var contextBuildVariant = z12.object({
5940
+ action: z12.literal("build"),
5941
+ entryId: z12.string().max(200),
5942
+ maxHops: z12.number().min(1).max(4).optional().default(2)
5488
5943
  });
5489
- var contextNeighborhoodVariant = z10.object({
5490
- action: z10.literal("neighborhood"),
5491
- entryId: z10.string().max(200)
5944
+ var contextNeighborhoodVariant = z12.object({
5945
+ action: z12.literal("neighborhood"),
5946
+ entryId: z12.string().max(200)
5492
5947
  });
5493
- var contextChangesVariant = z10.object({
5494
- action: z10.literal("changes"),
5495
- since: z10.string().max(200)
5948
+ var contextChangesVariant = z12.object({
5949
+ action: z12.literal("changes"),
5950
+ since: z12.string().max(200)
5496
5951
  });
5497
- var contextChainVariant = z10.object({
5498
- action: z10.literal("chain"),
5499
- entryId: z10.string().max(200),
5500
- direction: z10.enum(["outgoing", "incoming"]).optional().default("outgoing"),
5501
- maxHops: z10.number().min(1).max(4).optional().default(2),
5502
- relationType: z10.string().max(200).optional()
5952
+ var contextChainVariant = z12.object({
5953
+ action: z12.literal("chain"),
5954
+ entryId: z12.string().max(200),
5955
+ direction: z12.enum(["outgoing", "incoming"]).optional().default("outgoing"),
5956
+ maxHops: z12.number().min(1).max(4).optional().default(2),
5957
+ relationType: z12.string().max(200).optional()
5503
5958
  });
5504
- var contextCrossCutVariant = z10.object({
5505
- action: z10.literal("cross-cut"),
5506
- relationType: z10.string().max(200)
5959
+ var contextCrossCutVariant = z12.object({
5960
+ action: z12.literal("cross-cut"),
5961
+ relationType: z12.string().max(200)
5507
5962
  });
5508
- var contextIncrementalVariant = z10.object({
5509
- action: z10.literal("incremental"),
5510
- skill: z10.string().max(200)
5963
+ var contextIncrementalVariant = z12.object({
5964
+ action: z12.literal("incremental"),
5965
+ skill: z12.string().max(200)
5511
5966
  });
5512
- var contextBriefVariant = z10.object({
5513
- action: z10.literal("brief"),
5514
- briefType: z10.enum(["steering", "confidence", "delta"]),
5515
- since: z10.string().max(200).optional()
5967
+ var contextBriefVariant = z12.object({
5968
+ action: z12.literal("brief"),
5969
+ briefType: z12.enum(["steering", "confidence", "delta"]),
5970
+ since: z12.string().max(200).optional()
5516
5971
  });
5517
- var contextLastVerifiedBriefVariant = z10.object({
5518
- action: z10.literal("last-verified-brief"),
5519
- templateId: z10.string().max(200),
5520
- scopeKey: z10.string().max(200)
5972
+ var contextLastVerifiedBriefVariant = z12.object({
5973
+ action: z12.literal("last-verified-brief"),
5974
+ templateId: z12.string().max(200),
5975
+ scopeKey: z12.string().max(200)
5521
5976
  });
5522
- var contextActionUnion = z10.discriminatedUnion("action", [
5977
+ var contextActionUnion = z12.discriminatedUnion("action", [
5523
5978
  contextGatherVariant,
5524
5979
  contextBuildVariant,
5525
5980
  contextNeighborhoodVariant,
@@ -6560,20 +7015,20 @@ function formatTimeAgo(ms) {
6560
7015
  }
6561
7016
 
6562
7017
  // src/tools/collections.ts
6563
- import { z as z12 } from "zod/v3";
7018
+ import { z as z14 } from "zod/v3";
6564
7019
 
6565
7020
  // src/tools/labels.ts
6566
- import { z as z11 } from "zod/v3";
6567
- var labelsSchema = z11.object({
6568
- action: z11.enum(["list", "create", "update", "delete", "apply", "remove"]).describe("Action: list all labels, create/update/delete a label, or apply/remove a label on an entry"),
6569
- slug: z11.string().max(200).optional().describe("Label slug (required for create/update/delete/apply/remove)"),
6570
- name: z11.string().max(500).optional().describe("Display name (required for create)"),
6571
- color: z11.string().max(50).optional().describe("Hex color, e.g. '#ef4444'"),
6572
- description: z11.string().max(2e3).optional().describe("What this label means"),
6573
- parentSlug: z11.string().max(200).optional().describe("Parent group slug for label hierarchy"),
6574
- isGroup: z11.boolean().optional().describe("True if this is a group container, not a taggable label"),
6575
- order: z11.number().optional().describe("Sort order within its group"),
6576
- entryId: z11.string().max(200).optional().describe("Entry ID for apply/remove actions")
7021
+ import { z as z13 } from "zod/v3";
7022
+ var labelsSchema = z13.object({
7023
+ action: z13.enum(["list", "create", "update", "delete", "apply", "remove"]).describe("Action: list all labels, create/update/delete a label, or apply/remove a label on an entry"),
7024
+ slug: z13.string().max(200).optional().describe("Label slug (required for create/update/delete/apply/remove)"),
7025
+ name: z13.string().max(500).optional().describe("Display name (required for create)"),
7026
+ color: z13.string().max(50).optional().describe("Hex color, e.g. '#ef4444'"),
7027
+ description: z13.string().max(2e3).optional().describe("What this label means"),
7028
+ parentSlug: z13.string().max(200).optional().describe("Parent group slug for label hierarchy"),
7029
+ isGroup: z13.boolean().optional().describe("True if this is a group container, not a taggable label"),
7030
+ order: z13.number().optional().describe("Sort order within its group"),
7031
+ entryId: z13.string().max(200).optional().describe("Entry ID for apply/remove actions")
6577
7032
  });
6578
7033
  async function handleLabelsList() {
6579
7034
  const labels = await kernelQuery("chain.listLabels");
@@ -6678,128 +7133,128 @@ var COLLECTIONS_ACTIONS = [
6678
7133
  "label-apply",
6679
7134
  "label-remove"
6680
7135
  ];
6681
- var qualityCriterionSchema = z12.object({
6682
- field: z12.string().max(200).describe("Entry data field key this criterion applies to, e.g. 'description', 'owner'"),
7136
+ var qualityCriterionSchema = z14.object({
7137
+ field: z14.string().max(200).describe("Entry data field key this criterion applies to, e.g. 'description', 'owner'"),
6683
7138
  // WP-480 S1: `max_length` — must mirror the Convex rule union, or the tool rejects a
6684
7139
  // valid criterion before the request ever reaches the server.
6685
- rule: z12.enum(["required", "min_length", "max_length", "pattern"]).describe("'required': field must be non-empty (blocks accept). 'min_length': minimum string length (warns). 'max_length': maximum string length (warns). 'pattern': regex match (warns)."),
6686
- value: z12.string().max(500).optional().describe("For min_length/max_length: the length bound as a string integer. For pattern: the regex string. Unused for 'required'.")
7140
+ rule: z14.enum(["required", "min_length", "max_length", "pattern"]).describe("'required': field must be non-empty (blocks accept). 'min_length': minimum string length (warns). 'max_length': maximum string length (warns). 'pattern': regex match (warns)."),
7141
+ value: z14.string().max(500).optional().describe("For min_length/max_length: the length bound as a string integer. For pattern: the regex string. Unused for 'required'.")
6687
7142
  });
6688
- var fieldSchema = z12.object({
6689
- key: z12.string().max(200).describe("Field key, e.g. 'description', 'severity', 'status'"),
6690
- label: z12.string().max(200).describe("Display label, e.g. 'Description', 'Severity'"),
6691
- type: z12.string().max(50).describe("Field type: 'string', 'select', 'array', 'number', 'boolean'"),
6692
- required: z12.boolean().optional().describe("Whether this field is required"),
6693
- options: z12.array(z12.string().max(200)).max(200).optional().describe("Options for 'select' type fields"),
6694
- searchable: z12.boolean().optional().describe("Whether this field is included in full-text search"),
6695
- displayHint: z12.enum(["hero", "badge", "meta", "section", "hidden", "inline-meta"]).optional().describe("V2 rendering hint: how the field should be displayed in Cortex"),
6696
- zone: z12.enum(["header", "body", "meta"]).optional().describe("V2 layout zone: where the field appears in the entry view"),
6697
- colorMap: z12.record(z12.string().max(50)).optional().describe("V2 value-to-semantic-color mapping, e.g. { critical: 'danger', low: 'success' }"),
7143
+ var fieldSchema = z14.object({
7144
+ key: z14.string().max(200).describe("Field key, e.g. 'description', 'severity', 'status'"),
7145
+ label: z14.string().max(200).describe("Display label, e.g. 'Description', 'Severity'"),
7146
+ type: z14.string().max(50).describe("Field type: 'string', 'select', 'array', 'number', 'boolean'"),
7147
+ required: z14.boolean().optional().describe("Whether this field is required"),
7148
+ options: z14.array(z14.string().max(200)).max(200).optional().describe("Options for 'select' type fields"),
7149
+ searchable: z14.boolean().optional().describe("Whether this field is included in full-text search"),
7150
+ displayHint: z14.enum(["hero", "badge", "meta", "section", "hidden", "inline-meta"]).optional().describe("V2 rendering hint: how the field should be displayed in Cortex"),
7151
+ zone: z14.enum(["header", "body", "meta"]).optional().describe("V2 layout zone: where the field appears in the entry view"),
7152
+ colorMap: z14.record(z14.string().max(50)).optional().describe("V2 value-to-semantic-color mapping, e.g. { critical: 'danger', low: 'success' }"),
6698
7153
  // ENT-61
6699
- accentSource: z12.boolean().optional().describe("When true, this field's colorMap value drives the card-level accent styling"),
7154
+ accentSource: z14.boolean().optional().describe("When true, this field's colorMap value drives the card-level accent styling"),
6700
7155
  // ENT-61
6701
- iconMap: z12.record(z12.string(), z12.string().max(50)).optional().describe("Maps field values to icons (emoji/symbol), prepended to badge text"),
6702
- helpText: z12.string().max(2e3).optional().describe("Help text shown in editors and describe output"),
6703
- optionDescriptions: z12.record(z12.string().max(500)).optional().describe("Per-option guidance for select fields"),
7156
+ iconMap: z14.record(z14.string(), z14.string().max(50)).optional().describe("Maps field values to icons (emoji/symbol), prepended to badge text"),
7157
+ helpText: z14.string().max(2e3).optional().describe("Help text shown in editors and describe output"),
7158
+ optionDescriptions: z14.record(z14.string().max(500)).optional().describe("Per-option guidance for select fields"),
6704
7159
  // BET-136
6705
- semanticRole: z12.enum(["problem", "appetite", "elements", "architecture", "done_when", "risks", "exclusions"]).optional().describe("Semantic role for schema-driven consumers \u2014 enables field-key-independent validation and rendering"),
7160
+ semanticRole: z14.enum(["problem", "appetite", "elements", "architecture", "done_when", "risks", "exclusions"]).optional().describe("Semantic role for schema-driven consumers \u2014 enables field-key-independent validation and rendering"),
6706
7161
  // BET-196
6707
- maxLength: z12.number().optional().describe("Maximum character length for field values. Three-tier resolution: explicit > displayHint > type fallback."),
7162
+ maxLength: z14.number().optional().describe("Maximum character length for field values. Three-tier resolution: explicit > displayHint > type fallback."),
6708
7163
  // BET-196
6709
- minLength: z12.number().optional().describe("Minimum character length for field values. Only explicit \u2014 no defaults.")
7164
+ minLength: z14.number().optional().describe("Minimum character length for field values. Only explicit \u2014 no defaults.")
6710
7165
  });
6711
- var collectionsSchema = z12.object({
6712
- action: z12.enum(COLLECTIONS_ACTIONS).describe(
7166
+ var collectionsSchema = z14.object({
7167
+ action: z14.enum(COLLECTIONS_ACTIONS).describe(
6713
7168
  "'list': browse all collections. 'create': create a new collection. 'update': update an existing collection. 'describe': full documentation for one collection \u2014 fields, option guides, usage guidance, examples. 'audit': health report for all collections \u2014 missing classification, icon, displayHint coverage, and field schema gaps. 'export': full system_collection_definitions export with classification metadata (thinkingLayer, classificationPriority, classificationCheck, classificationSignals, governanceRole, governanceFunction, timelineRole, canBeElementOf, descriptionFieldKey). Admin only. 'label-list'/'label-create'/'label-update'/'label-delete'/'label-apply'/'label-remove': manage workspace labels (absorbs the `labels` tool)."
6714
7169
  ),
6715
- slug: z12.string().max(200).optional().describe("URL-safe identifier for create/update, e.g. 'glossary', 'tech-debt'. For label-*: label slug."),
6716
- name: z12.string().max(500).optional().describe("Display name for create, or new name for update. For label-create: label display name."),
6717
- description: z12.string().max(2e4).optional().describe("What this collection is for. For label-create/label-update: what the label means."),
6718
- purpose: z12.string().max(2e3).optional().describe("Why this collection exists \u2014 strategic reason"),
6719
- icon: z12.string().max(50).optional().describe("Emoji icon for the collection"),
6720
- navGroup: z12.enum(["daily", "strategic", "governance", "reference", "collections"]).optional().describe("Sidebar placement: 'daily', 'strategic', 'governance', 'reference', 'collections'"),
6721
- fields: z12.array(fieldSchema).max(200).optional().describe("Field definitions for create, or replacement schema for update (replaces all fields)"),
7170
+ slug: z14.string().max(200).optional().describe("URL-safe identifier for create/update, e.g. 'glossary', 'tech-debt'. For label-*: label slug."),
7171
+ name: z14.string().max(500).optional().describe("Display name for create, or new name for update. For label-create: label display name."),
7172
+ description: z14.string().max(2e4).optional().describe("What this collection is for. For label-create/label-update: what the label means."),
7173
+ purpose: z14.string().max(2e3).optional().describe("Why this collection exists \u2014 strategic reason"),
7174
+ icon: z14.string().max(50).optional().describe("Emoji icon for the collection"),
7175
+ navGroup: z14.enum(["daily", "strategic", "governance", "reference", "collections"]).optional().describe("Sidebar placement: 'daily', 'strategic', 'governance', 'reference', 'collections'"),
7176
+ fields: z14.array(fieldSchema).max(200).optional().describe("Field definitions for create, or replacement schema for update (replaces all fields)"),
6722
7177
  // ENT-62
6723
- defaultCanonicalKey: z12.string().max(200).optional().describe("The canonical_key entries in this collection default to (e.g. 'decision', 'insight'). Consumers read from collection doc; code map is fallback."),
7178
+ defaultCanonicalKey: z14.string().max(200).optional().describe("The canonical_key entries in this collection default to (e.g. 'decision', 'insight'). Consumers read from collection doc; code map is fallback."),
6724
7179
  // ENT-67
6725
- defaultWorkflowStatus: z12.string().max(200).optional().describe("Default workflowStatus for new entries. Must be in validWorkflowStatuses when set (e.g. 'hypothesis' for insights)."),
7180
+ defaultWorkflowStatus: z14.string().max(200).optional().describe("Default workflowStatus for new entries. Must be in validWorkflowStatuses when set (e.g. 'hypothesis' for insights)."),
6726
7181
  // ENT-65
6727
- validWorkflowStatuses: z12.array(z12.string().max(200)).max(50).optional().describe("The allowed workflowStatus values for entries in this collection. New entries are validated against this list. Empty array means no constraint."),
7182
+ validWorkflowStatuses: z14.array(z14.string().max(200)).max(50).optional().describe("The allowed workflowStatus values for entries in this collection. New entries are validated against this list. Empty array means no constraint."),
6728
7183
  // ENT-65, FEAT-200
6729
- classificationCheck: z12.string().max(500).optional().describe("LLM decision-tree check for this collection (3\u2013500 chars). Guides the classifier in routing entries here."),
7184
+ classificationCheck: z14.string().max(500).optional().describe("LLM decision-tree check for this collection (3\u2013500 chars). Guides the classifier in routing entries here."),
6730
7185
  // ENT-65, FEAT-200
6731
- classificationPriority: z12.number().optional().describe("Classifier priority (1\u20139, lower = higher priority). Used with classificationCheck to order the decision tree."),
7186
+ classificationPriority: z14.number().optional().describe("Classifier priority (1\u20139, lower = higher priority). Used with classificationCheck to order the decision tree."),
6732
7187
  // FEAT-301 Slice 2: quality gate criteria and usage guidance.
6733
7188
  // FEAT-257
6734
- qualityCriteria: z12.array(qualityCriterionSchema).max(50).optional().describe("Per-collection accept gate rules. 'required' rule hard-blocks accepts on empty fields; 'min_length'/'pattern' rules warn. Pass an empty array to clear all criteria."),
6735
- usageGuidance: z12.string().max(2e4).optional().describe("Plain-text guidance shown to agents and users: when to use this collection, when not to, and what makes a good entry."),
7189
+ qualityCriteria: z14.array(qualityCriterionSchema).max(50).optional().describe("Per-collection accept gate rules. 'required' rule hard-blocks accepts on empty fields; 'min_length'/'pattern' rules warn. Pass an empty array to clear all criteria."),
7190
+ usageGuidance: z14.string().max(2e4).optional().describe("Plain-text guidance shown to agents and users: when to use this collection, when not to, and what makes a good entry."),
6736
7191
  // For label-*
6737
- color: z12.string().max(50).optional().describe("For label-create/label-update: hex color, e.g. '#ef4444'."),
6738
- parentSlug: z12.string().max(200).optional().describe("For label-create: parent group slug for label hierarchy."),
6739
- isGroup: z12.boolean().optional().describe("For label-create/label-update: true if this is a group container, not a taggable label."),
6740
- order: z12.number().optional().describe("For label-create/label-update: sort order within its group."),
6741
- entryId: z12.string().max(200).optional().describe("For label-apply/label-remove: entry ID.")
7192
+ color: z14.string().max(50).optional().describe("For label-create/label-update: hex color, e.g. '#ef4444'."),
7193
+ parentSlug: z14.string().max(200).optional().describe("For label-create: parent group slug for label hierarchy."),
7194
+ isGroup: z14.boolean().optional().describe("For label-create/label-update: true if this is a group container, not a taggable label."),
7195
+ order: z14.number().optional().describe("For label-create/label-update: sort order within its group."),
7196
+ entryId: z14.string().max(200).optional().describe("For label-apply/label-remove: entry ID.")
6742
7197
  });
6743
- var collectionsListVariant = z12.object({ action: z12.literal("list") });
6744
- var collectionsDescribeVariant = z12.object({ action: z12.literal("describe"), slug: z12.string().max(200) });
6745
- var collectionsCreateVariant = z12.object({
6746
- action: z12.literal("create"),
6747
- slug: z12.string().max(200),
6748
- name: z12.string().max(500),
6749
- description: z12.string().max(2e4).optional(),
6750
- purpose: z12.string().max(2e3).optional(),
6751
- icon: z12.string().max(50).optional(),
6752
- navGroup: z12.enum(["daily", "strategic", "governance", "reference", "collections"]).optional(),
6753
- fields: z12.array(fieldSchema).min(1),
6754
- defaultCanonicalKey: z12.string().max(200).optional(),
6755
- defaultWorkflowStatus: z12.string().max(200).optional(),
6756
- validWorkflowStatuses: z12.array(z12.string().max(200)).optional(),
6757
- classificationCheck: z12.string().max(500).optional(),
6758
- classificationPriority: z12.number().optional()
7198
+ var collectionsListVariant = z14.object({ action: z14.literal("list") });
7199
+ var collectionsDescribeVariant = z14.object({ action: z14.literal("describe"), slug: z14.string().max(200) });
7200
+ var collectionsCreateVariant = z14.object({
7201
+ action: z14.literal("create"),
7202
+ slug: z14.string().max(200),
7203
+ name: z14.string().max(500),
7204
+ description: z14.string().max(2e4).optional(),
7205
+ purpose: z14.string().max(2e3).optional(),
7206
+ icon: z14.string().max(50).optional(),
7207
+ navGroup: z14.enum(["daily", "strategic", "governance", "reference", "collections"]).optional(),
7208
+ fields: z14.array(fieldSchema).min(1),
7209
+ defaultCanonicalKey: z14.string().max(200).optional(),
7210
+ defaultWorkflowStatus: z14.string().max(200).optional(),
7211
+ validWorkflowStatuses: z14.array(z14.string().max(200)).optional(),
7212
+ classificationCheck: z14.string().max(500).optional(),
7213
+ classificationPriority: z14.number().optional()
6759
7214
  });
6760
- var collectionsUpdateVariant = z12.object({
6761
- action: z12.literal("update"),
6762
- slug: z12.string().max(200),
6763
- name: z12.string().max(500).optional(),
6764
- description: z12.string().max(2e4).optional(),
6765
- purpose: z12.string().max(2e3).optional(),
6766
- icon: z12.string().max(50).optional(),
6767
- navGroup: z12.enum(["daily", "strategic", "governance", "reference", "collections"]).optional(),
6768
- fields: z12.array(fieldSchema).optional(),
6769
- defaultCanonicalKey: z12.string().max(200).optional(),
6770
- defaultWorkflowStatus: z12.string().max(200).optional(),
6771
- validWorkflowStatuses: z12.array(z12.string().max(200)).optional(),
6772
- classificationCheck: z12.string().max(500).optional(),
6773
- classificationPriority: z12.number().optional(),
6774
- qualityCriteria: z12.array(qualityCriterionSchema).optional(),
6775
- usageGuidance: z12.string().max(2e4).optional()
7215
+ var collectionsUpdateVariant = z14.object({
7216
+ action: z14.literal("update"),
7217
+ slug: z14.string().max(200),
7218
+ name: z14.string().max(500).optional(),
7219
+ description: z14.string().max(2e4).optional(),
7220
+ purpose: z14.string().max(2e3).optional(),
7221
+ icon: z14.string().max(50).optional(),
7222
+ navGroup: z14.enum(["daily", "strategic", "governance", "reference", "collections"]).optional(),
7223
+ fields: z14.array(fieldSchema).optional(),
7224
+ defaultCanonicalKey: z14.string().max(200).optional(),
7225
+ defaultWorkflowStatus: z14.string().max(200).optional(),
7226
+ validWorkflowStatuses: z14.array(z14.string().max(200)).optional(),
7227
+ classificationCheck: z14.string().max(500).optional(),
7228
+ classificationPriority: z14.number().optional(),
7229
+ qualityCriteria: z14.array(qualityCriterionSchema).optional(),
7230
+ usageGuidance: z14.string().max(2e4).optional()
6776
7231
  });
6777
- var collectionsAuditVariant = z12.object({ action: z12.literal("audit") });
6778
- var collectionsExportVariant = z12.object({ action: z12.literal("export") });
6779
- var collectionsLabelListVariant = z12.object({ action: z12.literal("label-list") });
6780
- var collectionsLabelCreateVariant = z12.object({
6781
- action: z12.literal("label-create"),
6782
- slug: z12.string().max(200),
6783
- name: z12.string().max(500),
6784
- color: z12.string().max(50).optional(),
6785
- description: z12.string().max(2e3).optional(),
6786
- parentSlug: z12.string().max(200).optional(),
6787
- isGroup: z12.boolean().optional(),
6788
- order: z12.number().optional()
7232
+ var collectionsAuditVariant = z14.object({ action: z14.literal("audit") });
7233
+ var collectionsExportVariant = z14.object({ action: z14.literal("export") });
7234
+ var collectionsLabelListVariant = z14.object({ action: z14.literal("label-list") });
7235
+ var collectionsLabelCreateVariant = z14.object({
7236
+ action: z14.literal("label-create"),
7237
+ slug: z14.string().max(200),
7238
+ name: z14.string().max(500),
7239
+ color: z14.string().max(50).optional(),
7240
+ description: z14.string().max(2e3).optional(),
7241
+ parentSlug: z14.string().max(200).optional(),
7242
+ isGroup: z14.boolean().optional(),
7243
+ order: z14.number().optional()
6789
7244
  });
6790
- var collectionsLabelUpdateVariant = z12.object({
6791
- action: z12.literal("label-update"),
6792
- slug: z12.string().max(200),
6793
- name: z12.string().max(500).optional(),
6794
- color: z12.string().max(50).optional(),
6795
- description: z12.string().max(2e3).optional(),
6796
- isGroup: z12.boolean().optional(),
6797
- order: z12.number().optional()
7245
+ var collectionsLabelUpdateVariant = z14.object({
7246
+ action: z14.literal("label-update"),
7247
+ slug: z14.string().max(200),
7248
+ name: z14.string().max(500).optional(),
7249
+ color: z14.string().max(50).optional(),
7250
+ description: z14.string().max(2e3).optional(),
7251
+ isGroup: z14.boolean().optional(),
7252
+ order: z14.number().optional()
6798
7253
  });
6799
- var collectionsLabelDeleteVariant = z12.object({ action: z12.literal("label-delete"), slug: z12.string().max(200) });
6800
- var collectionsLabelApplyVariant = z12.object({ action: z12.literal("label-apply"), slug: z12.string().max(200), entryId: z12.string().max(200) });
6801
- var collectionsLabelRemoveVariant = z12.object({ action: z12.literal("label-remove"), slug: z12.string().max(200), entryId: z12.string().max(200) });
6802
- var collectionsActionUnion = z12.discriminatedUnion("action", [
7254
+ var collectionsLabelDeleteVariant = z14.object({ action: z14.literal("label-delete"), slug: z14.string().max(200) });
7255
+ var collectionsLabelApplyVariant = z14.object({ action: z14.literal("label-apply"), slug: z14.string().max(200), entryId: z14.string().max(200) });
7256
+ var collectionsLabelRemoveVariant = z14.object({ action: z14.literal("label-remove"), slug: z14.string().max(200), entryId: z14.string().max(200) });
7257
+ var collectionsActionUnion = z14.discriminatedUnion("action", [
6803
7258
  collectionsListVariant,
6804
7259
  collectionsDescribeVariant,
6805
7260
  collectionsCreateVariant,
@@ -7184,7 +7639,7 @@ async function handleExport() {
7184
7639
  }
7185
7640
 
7186
7641
  // src/tools/orient.ts
7187
- import { z as z16 } from "zod/v3";
7642
+ import { z as z18 } from "zod/v3";
7188
7643
 
7189
7644
  // src/tools/planned-work.ts
7190
7645
  function buildPlannedWork(allEntries) {
@@ -8112,12 +8567,12 @@ function replaceVocabTokens(body, workspaceCtx, collectionCtxMap) {
8112
8567
  }
8113
8568
 
8114
8569
  // src/tools/start_pb.ts
8115
- import { z as z14 } from "zod/v3";
8570
+ import { z as z16 } from "zod/v3";
8116
8571
 
8117
8572
  // src/tools/skills.ts
8118
- import { z as z13 } from "zod/v3";
8119
- var skillsSchema = z13.object({
8120
- entryId: z13.string().min(1).describe(
8573
+ import { z as z15 } from "zod/v3";
8574
+ var skillsSchema = z15.object({
8575
+ entryId: z15.string().min(1).describe(
8121
8576
  "Workspace-scoped skill entry id (e.g. 'SKILL-pb-setup'). The tool refuses non-skill entries (canonicalKey !== 'skill') with INVALID_KIND."
8122
8577
  )
8123
8578
  });
@@ -8130,8 +8585,8 @@ async function loadSkillBody(entryId) {
8130
8585
  }
8131
8586
 
8132
8587
  // src/tools/start_pb.ts
8133
- var startPbSchema = z14.object({
8134
- task: z14.string().max(2e3).optional().describe(
8588
+ var startPbSchema = z16.object({
8589
+ task: z16.string().max(2e3).optional().describe(
8135
8590
  "What you're about to work on (e.g. 'implementing auth middleware'). Grounded/connected workspaces: filters governance to show relevant principles, standards, and business rules. Blank/seeded workspaces: ignored (setup flow takes over)."
8136
8591
  )
8137
8592
  // TEN-2431: no `scope` param — start_pb's governance matches orient's scope-BLIND RENDERED
@@ -8490,15 +8945,15 @@ ${FEEDBACK_HINT}` }],
8490
8945
  }
8491
8946
 
8492
8947
  // src/tools/record_activation.ts
8493
- import { z as z15 } from "zod/v3";
8494
- var recordActivationSchema = z15.object({
8495
- confirmedEntryCount: z15.number().int().min(0).describe(
8948
+ import { z as z17 } from "zod/v3";
8949
+ var recordActivationSchema = z17.object({
8950
+ confirmedEntryCount: z17.number().int().min(0).describe(
8496
8951
  "Confirmed-entry count from the Phase 4 capture loop. The mutation enforces >=10."
8497
8952
  ),
8498
- entriesAcrossCollections: z15.number().int().min(0).describe(
8953
+ entriesAcrossCollections: z17.number().int().min(0).describe(
8499
8954
  "Number of distinct collections those entries span. The mutation enforces >=2 (diversity soft-gate)."
8500
8955
  ),
8501
- retrievalDemoConfirmed: z15.boolean().describe(
8956
+ retrievalDemoConfirmed: z17.boolean().describe(
8502
8957
  "True if the retrieval round-trip ran successfully in Phase 4. The mutation rejects false."
8503
8958
  )
8504
8959
  });
@@ -8589,65 +9044,65 @@ async function markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapsho
8589
9044
  }
8590
9045
  }
8591
9046
  var ORIENT_ACTIONS = ["start", "task", "record-activation"];
8592
- var orientSchema = z16.object({
8593
- action: z16.enum(ORIENT_ACTIONS).optional().default("task").describe(
9047
+ var orientSchema = z18.object({
9048
+ action: z18.enum(ORIENT_ACTIONS).optional().default("task").describe(
8594
9049
  "'start': universal session opener (absorbs start_pb) \u2014 stage-aware setup skill or standup briefing. 'task': task-grounded context loader \u2014 the original orient behavior. 'record-activation': chat-only activation receipt writer (absorbs record_activation)."
8595
9050
  ),
8596
- mode: z16.enum(["full", "brief"]).optional().default("full").describe("For 'task': full = full context (default). brief = compact summary for mid-session re-orientation. Prefer using the `tier` param for depth control."),
8597
- tier: z16.enum(["summary", "standard", "full"]).optional().describe(
9051
+ mode: z18.enum(["full", "brief"]).optional().default("full").describe("For 'task': full = full context (default). brief = compact summary for mid-session re-orientation. Prefer using the `tier` param for depth control."),
9052
+ tier: z18.enum(["summary", "standard", "full"]).optional().describe(
8598
9053
  "For 'task': payload depth. Defaults to summary (~10 KB) when task is provided; standard (~256 KB) when task is absent. Pass summary, standard, or full to override."
8599
9054
  ),
8600
- task: z16.string().max(2e3).optional().describe(
9055
+ task: z18.string().max(2e3).optional().describe(
8601
9056
  "For 'task': natural-language task description for task-scoped context. For 'start': what you're about to work on. When provided to 'task', orient returns scored, relevant entries for the task."
8602
9057
  ),
8603
- scope: z16.string().max(200).optional().describe("For 'task': optional domain scope to filter governance to entries relevant for this domain. Forwarded to Convex for workspace-specific validation."),
9058
+ scope: z18.string().max(200).optional().describe("For 'task': optional domain scope to filter governance to entries relevant for this domain. Forwarded to Convex for workspace-specific validation."),
8604
9059
  // WP-486 Slice 1 (FEAT-1371, TEN-2724): the startup-signal envelope `resolveStartupDomain` already
8605
9060
  // consumes (`startupResolver.ts:344-379`) but this tool never sent. Nested to match the server's
8606
9061
  // `StartupResolutionSignals` shape exactly — every field optional, sanitized server-side.
8607
- startupSignals: z16.object({
8608
- changedPaths: z16.array(z16.string()).max(25).optional().describe("Paths changed in the current working tree, if known (e.g. from a prior git status/diff tool call)."),
8609
- reviewedArtifactRefs: z16.array(z16.string()).max(25).optional().describe("Chain entry IDs the caller has already reviewed this session, if tracked."),
8610
- branchName: z16.string().max(120).optional().describe("Current git branch name, if known."),
8611
- worktreeName: z16.string().max(120).optional().describe("Current worktree/directory name, if known.")
9062
+ startupSignals: z18.object({
9063
+ changedPaths: z18.array(z18.string()).max(25).optional().describe("Paths changed in the current working tree, if known (e.g. from a prior git status/diff tool call)."),
9064
+ reviewedArtifactRefs: z18.array(z18.string()).max(25).optional().describe("Chain entry IDs the caller has already reviewed this session, if tracked."),
9065
+ branchName: z18.string().max(120).optional().describe("Current git branch name, if known."),
9066
+ worktreeName: z18.string().max(120).optional().describe("Current worktree/directory name, if known.")
8612
9067
  }).optional().describe("For 'task': best-effort startup signals for domain resolution \u2014 changedPaths/reviewedArtifactRefs/branchName/worktreeName. All optional; omit fields you don't know."),
8613
- invocationPath: z16.enum(["session-start", "session-close", "manual-orient", "handshake", "unknown"]).optional().describe("For 'task': how this orient was invoked. Defaults to 'manual-orient' (the direct `orient task=...` call shape) when omitted."),
8614
- confirmedEntryCount: z16.number().int().min(0).optional().describe(
9068
+ invocationPath: z18.enum(["session-start", "session-close", "manual-orient", "handshake", "unknown"]).optional().describe("For 'task': how this orient was invoked. Defaults to 'manual-orient' (the direct `orient task=...` call shape) when omitted."),
9069
+ confirmedEntryCount: z18.number().int().min(0).optional().describe(
8615
9070
  "For 'record-activation': confirmed-entry count from the Phase 4 capture loop. The mutation enforces >=10."
8616
9071
  ),
8617
- entriesAcrossCollections: z16.number().int().min(0).optional().describe(
9072
+ entriesAcrossCollections: z18.number().int().min(0).optional().describe(
8618
9073
  "For 'record-activation': number of distinct collections those entries span. The mutation enforces >=2 (diversity soft-gate)."
8619
9074
  ),
8620
- retrievalDemoConfirmed: z16.boolean().optional().describe(
9075
+ retrievalDemoConfirmed: z18.boolean().optional().describe(
8621
9076
  "For 'record-activation': true if the retrieval round-trip ran successfully in Phase 4. The mutation rejects false."
8622
9077
  )
8623
9078
  });
8624
- var orientStartVariant = z16.object({
8625
- action: z16.literal("start"),
8626
- task: z16.string().max(2e3).optional()
9079
+ var orientStartVariant = z18.object({
9080
+ action: z18.literal("start"),
9081
+ task: z18.string().max(2e3).optional()
8627
9082
  });
8628
- var orientTaskVariant = z16.object({
8629
- action: z16.literal("task"),
8630
- mode: z16.enum(["full", "brief"]).optional().default("full"),
8631
- tier: z16.enum(["summary", "standard", "full"]).optional(),
8632
- task: z16.string().max(2e3).optional(),
8633
- scope: z16.string().max(200).optional(),
9083
+ var orientTaskVariant = z18.object({
9084
+ action: z18.literal("task"),
9085
+ mode: z18.enum(["full", "brief"]).optional().default("full"),
9086
+ tier: z18.enum(["summary", "standard", "full"]).optional(),
9087
+ task: z18.string().max(2e3).optional(),
9088
+ scope: z18.string().max(200).optional(),
8634
9089
  // WP-486 Slice 1 (FEAT-1371) — mirrors orientSchema's top-level declaration above; see its
8635
9090
  // doc comment for the shape rationale.
8636
- startupSignals: z16.object({
8637
- changedPaths: z16.array(z16.string()).max(25).optional(),
8638
- reviewedArtifactRefs: z16.array(z16.string()).max(25).optional(),
8639
- branchName: z16.string().max(120).optional(),
8640
- worktreeName: z16.string().max(120).optional()
9091
+ startupSignals: z18.object({
9092
+ changedPaths: z18.array(z18.string()).max(25).optional(),
9093
+ reviewedArtifactRefs: z18.array(z18.string()).max(25).optional(),
9094
+ branchName: z18.string().max(120).optional(),
9095
+ worktreeName: z18.string().max(120).optional()
8641
9096
  }).optional(),
8642
- invocationPath: z16.enum(["session-start", "session-close", "manual-orient", "handshake", "unknown"]).optional()
9097
+ invocationPath: z18.enum(["session-start", "session-close", "manual-orient", "handshake", "unknown"]).optional()
8643
9098
  });
8644
- var orientRecordActivationVariant = z16.object({
8645
- action: z16.literal("record-activation"),
8646
- confirmedEntryCount: z16.number().int().min(0),
8647
- entriesAcrossCollections: z16.number().int().min(0),
8648
- retrievalDemoConfirmed: z16.boolean()
9099
+ var orientRecordActivationVariant = z18.object({
9100
+ action: z18.literal("record-activation"),
9101
+ confirmedEntryCount: z18.number().int().min(0),
9102
+ entriesAcrossCollections: z18.number().int().min(0),
9103
+ retrievalDemoConfirmed: z18.boolean()
8649
9104
  });
8650
- var orientActionUnion = z16.discriminatedUnion("action", [
9105
+ var orientActionUnion = z18.discriminatedUnion("action", [
8651
9106
  orientStartVariant,
8652
9107
  orientTaskVariant,
8653
9108
  orientRecordActivationVariant
@@ -9488,7 +9943,7 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
9488
9943
  }
9489
9944
 
9490
9945
  // src/tools/workflows.ts
9491
- import { z as z17 } from "zod/v3";
9946
+ import { z as z19 } from "zod/v3";
9492
9947
 
9493
9948
  // src/workflows/descriptor.ts
9494
9949
  function cloneWorkflowQuestion(question) {
@@ -10328,75 +10783,75 @@ function workflowRunOutputToText(output) {
10328
10783
 
10329
10784
  // src/tools/workflows.ts
10330
10785
  var WORKFLOWS_ACTIONS = ["list", "start", "checkpoint", "get-run", "load-skill"];
10331
- var jsonValueSchema = z17.lazy(
10332
- () => z17.union([
10333
- z17.string(),
10334
- z17.number(),
10335
- z17.boolean(),
10336
- z17.null(),
10337
- z17.array(jsonValueSchema),
10338
- z17.record(jsonValueSchema)
10786
+ var jsonValueSchema = z19.lazy(
10787
+ () => z19.union([
10788
+ z19.string(),
10789
+ z19.number(),
10790
+ z19.boolean(),
10791
+ z19.null(),
10792
+ z19.array(jsonValueSchema),
10793
+ z19.record(jsonValueSchema)
10339
10794
  ])
10340
10795
  );
10341
- var workflowRunOutputInputSchema = z17.union([
10342
- z17.object({
10343
- format: z17.literal("freetext"),
10344
- value: z17.string()
10796
+ var workflowRunOutputInputSchema = z19.union([
10797
+ z19.object({
10798
+ format: z19.literal("freetext"),
10799
+ value: z19.string()
10345
10800
  }),
10346
- z17.object({
10347
- format: z17.literal("list"),
10348
- value: z17.array(z17.string())
10801
+ z19.object({
10802
+ format: z19.literal("list"),
10803
+ value: z19.array(z19.string())
10349
10804
  }),
10350
- z17.object({
10351
- format: z17.literal("choice"),
10352
- value: z17.union([z17.string(), z17.array(z17.string())])
10805
+ z19.object({
10806
+ format: z19.literal("choice"),
10807
+ value: z19.union([z19.string(), z19.array(z19.string())])
10353
10808
  }),
10354
- z17.object({
10355
- format: z17.literal("structured"),
10809
+ z19.object({
10810
+ format: z19.literal("structured"),
10356
10811
  value: jsonValueSchema
10357
10812
  })
10358
10813
  ]);
10359
- var workflowsSchema = z17.object({
10360
- action: z17.enum(WORKFLOWS_ACTIONS).describe(
10814
+ var workflowsSchema = z19.object({
10815
+ action: z19.enum(WORKFLOWS_ACTIONS).describe(
10361
10816
  "'list': browse available workflows. 'start': start or resume a workflow \u2014 returns first (or current) round and next-step checkpoint call. 'checkpoint': record round output or final summary. 'get-run': inspect a persisted workflow run. 'load-skill': load the markdown body of a SKILL-* entry from the workspace (absorbs the `skills` tool). Requires entryId."
10362
10817
  ),
10363
- workflowId: z17.string().max(200).optional().describe("Workflow ID for start, checkpoint, or get-run, e.g. 'retro', 'implementation-review'"),
10364
- runId: z17.string().max(200).optional().describe("Workflow run ID: for get-run, which run to load; for checkpoint, target this run (avoids session drift \u2014 pass runId from get-run)."),
10365
- roundId: z17.string().max(200).optional().describe("Round ID for checkpoint, e.g. 'what-went-well'"),
10366
- output: z17.union([z17.string(), workflowRunOutputInputSchema]).optional().describe("The round's output \u2014 either legacy synthesized text or a typed workflow run payload."),
10367
- isFinal: z17.boolean().optional().describe("If true, finalize an existing durable workflow run from its terminal round and create the summary chain entry."),
10368
- restart: z17.boolean().optional().describe("If true, start a new durable run from the workflow's first round in the current session."),
10369
- summaryName: z17.string().max(500).optional().describe("Optional name for final chain entry. If omitted, the workflow summary template is used."),
10370
- summaryDescription: z17.string().max(2e4).optional().describe("Optional override for the final chain entry description. Defaults to the final round output text."),
10371
- summaryEntryId: z17.string().max(200).optional().describe("Link an existing entry as the run's summary instead of creating one. Used by facilitated workflows (e.g. shape) where the primary record is created by the specialized tool."),
10372
- entryId: z17.string().max(200).optional().describe("For 'load-skill': workspace-scoped skill entry id (e.g. 'SKILL-pb-setup'). Refuses non-skill entries (canonicalKey !== 'skill') with INVALID_KIND."),
10818
+ workflowId: z19.string().max(200).optional().describe("Workflow ID for start, checkpoint, or get-run, e.g. 'retro', 'implementation-review'"),
10819
+ runId: z19.string().max(200).optional().describe("Workflow run ID: for get-run, which run to load; for checkpoint, target this run (avoids session drift \u2014 pass runId from get-run)."),
10820
+ roundId: z19.string().max(200).optional().describe("Round ID for checkpoint, e.g. 'what-went-well'"),
10821
+ output: z19.union([z19.string(), workflowRunOutputInputSchema]).optional().describe("The round's output \u2014 either legacy synthesized text or a typed workflow run payload."),
10822
+ isFinal: z19.boolean().optional().describe("If true, finalize an existing durable workflow run from its terminal round and create the summary chain entry."),
10823
+ restart: z19.boolean().optional().describe("If true, start a new durable run from the workflow's first round in the current session."),
10824
+ summaryName: z19.string().max(500).optional().describe("Optional name for final chain entry. If omitted, the workflow summary template is used."),
10825
+ summaryDescription: z19.string().max(2e4).optional().describe("Optional override for the final chain entry description. Defaults to the final round output text."),
10826
+ summaryEntryId: z19.string().max(200).optional().describe("Link an existing entry as the run's summary instead of creating one. Used by facilitated workflows (e.g. shape) where the primary record is created by the specialized tool."),
10827
+ entryId: z19.string().max(200).optional().describe("For 'load-skill': workspace-scoped skill entry id (e.g. 'SKILL-pb-setup'). Refuses non-skill entries (canonicalKey !== 'skill') with INVALID_KIND."),
10373
10828
  // WP-513: team+role to create the finalize summary AS OWNER of (rung 2 only).
10374
- ownerTeamEntryId: z17.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning team (rung-2)."),
10375
- ownerRoleEntryId: z17.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning role (rung-2).")
10829
+ ownerTeamEntryId: z19.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning team (rung-2)."),
10830
+ ownerRoleEntryId: z19.string().max(200).optional().describe("For 'checkpoint' (isFinal): owning role (rung-2).")
10376
10831
  });
10377
- var workflowsListVariant = z17.object({ action: z17.literal("list") });
10378
- var workflowsGetRunVariant = z17.object({
10379
- action: z17.literal("get-run"),
10380
- runId: z17.string().max(200).optional(),
10381
- workflowId: z17.string().max(200).optional()
10832
+ var workflowsListVariant = z19.object({ action: z19.literal("list") });
10833
+ var workflowsGetRunVariant = z19.object({
10834
+ action: z19.literal("get-run"),
10835
+ runId: z19.string().max(200).optional(),
10836
+ workflowId: z19.string().max(200).optional()
10382
10837
  });
10383
- var workflowsStartVariant = z17.object({ action: z17.literal("start"), workflowId: z17.string().max(200) });
10384
- var workflowsCheckpointVariant = z17.object({
10385
- action: z17.literal("checkpoint"),
10386
- workflowId: z17.string().max(200),
10387
- roundId: z17.string().max(200),
10388
- output: z17.union([z17.string(), workflowRunOutputInputSchema]),
10389
- isFinal: z17.boolean().optional(),
10390
- restart: z17.boolean().optional(),
10391
- summaryName: z17.string().max(500).optional(),
10392
- summaryDescription: z17.string().max(2e4).optional(),
10393
- summaryEntryId: z17.string().max(200).optional(),
10394
- runId: z17.string().max(200).optional(),
10395
- ownerTeamEntryId: z17.string().max(200).optional(),
10396
- ownerRoleEntryId: z17.string().max(200).optional()
10838
+ var workflowsStartVariant = z19.object({ action: z19.literal("start"), workflowId: z19.string().max(200) });
10839
+ var workflowsCheckpointVariant = z19.object({
10840
+ action: z19.literal("checkpoint"),
10841
+ workflowId: z19.string().max(200),
10842
+ roundId: z19.string().max(200),
10843
+ output: z19.union([z19.string(), workflowRunOutputInputSchema]),
10844
+ isFinal: z19.boolean().optional(),
10845
+ restart: z19.boolean().optional(),
10846
+ summaryName: z19.string().max(500).optional(),
10847
+ summaryDescription: z19.string().max(2e4).optional(),
10848
+ summaryEntryId: z19.string().max(200).optional(),
10849
+ runId: z19.string().max(200).optional(),
10850
+ ownerTeamEntryId: z19.string().max(200).optional(),
10851
+ ownerRoleEntryId: z19.string().max(200).optional()
10397
10852
  });
10398
- var workflowsLoadSkillVariant = z17.object({ action: z17.literal("load-skill"), entryId: z17.string().max(200).min(1) });
10399
- var workflowsActionUnion = z17.discriminatedUnion("action", [
10853
+ var workflowsLoadSkillVariant = z19.object({ action: z19.literal("load-skill"), entryId: z19.string().max(200).min(1) });
10854
+ var workflowsActionUnion = z19.discriminatedUnion("action", [
10400
10855
  workflowsListVariant,
10401
10856
  workflowsGetRunVariant,
10402
10857
  workflowsStartVariant,
@@ -11136,10 +11591,10 @@ function parseListOutput(output) {
11136
11591
  }
11137
11592
 
11138
11593
  // src/tools/quality.ts
11139
- import { z as z19 } from "zod/v3";
11594
+ import { z as z21 } from "zod/v3";
11140
11595
 
11141
11596
  // src/tools/audit.ts
11142
- import { z as z18 } from "zod/v3";
11597
+ import { z as z20 } from "zod/v3";
11143
11598
  var VOCAB_TTL_MS = 5 * 60 * 1e3;
11144
11599
  var MAX_VOCAB_KEYS = 100;
11145
11600
  var vocabCache = /* @__PURE__ */ new Map();
@@ -11169,12 +11624,12 @@ function evictVocabIfFull() {
11169
11624
  }
11170
11625
  }
11171
11626
  var AUDIT_ACTIONS = ["run"];
11172
- var auditSchema = z18.object({
11173
- action: z18.enum(AUDIT_ACTIONS).describe(
11627
+ var auditSchema = z20.object({
11628
+ action: z20.enum(AUDIT_ACTIONS).describe(
11174
11629
  "'run': run the hygiene audit for a bet entry."
11175
11630
  ),
11176
- entryId: z18.string().describe("Bet entry ID to audit, e.g. '<PREFIX>-<n>'"),
11177
- phase: z18.enum(["shaping", "handoff"]).default("shaping").optional().describe(
11631
+ entryId: z20.string().describe("Bet entry ID to audit, e.g. '<PREFIX>-<n>'"),
11632
+ phase: z20.enum(["shaping", "handoff"]).default("shaping").optional().describe(
11178
11633
  "'shaping': check shaping-phase fields only. 'handoff': check all required fields including buildContract/buildSequence/exclusions/risks. Default: shaping."
11179
11634
  )
11180
11635
  });
@@ -11290,35 +11745,35 @@ async function handleAuditRun(entryId, phase) {
11290
11745
 
11291
11746
  // src/tools/quality.ts
11292
11747
  var QUALITY_ACTIONS = ["check", "re-evaluate", "verify-chain", "audit"];
11293
- var qualitySchema = z19.object({
11294
- action: z19.enum(QUALITY_ACTIONS).describe(
11748
+ var qualitySchema = z21.object({
11749
+ action: z21.enum(QUALITY_ACTIONS).describe(
11295
11750
  "'check': read the entry's server quality verdict (tier + criteria). 're-evaluate': trigger fresh evaluation. 'verify-chain': verify entries against the codebase (codeMapping drift, cross-references) \u2014 absorbs `verify`. 'audit': hygiene audit for a bet entry \u2014 absorbs `audit`."
11296
11751
  ),
11297
- entryId: z19.string().max(200).optional().describe("For 'check'/'re-evaluate'/'audit': entry ID, e.g. 'TEN-graph-db', '<PREFIX>-<n>'."),
11298
- context: z19.enum(["capture", "commit", "review"]).default("review").optional().describe("For re-evaluate: evaluation context"),
11299
- collection: z19.string().max(200).optional().describe("For 'verify-chain': collection slug to verify (default: glossary)."),
11300
- mode: z19.enum(["report", "fix"]).optional().describe("For 'verify-chain': 'report' = read-only trust report (default). 'fix' = also update drifted codeMapping statuses."),
11301
- phase: z19.enum(["shaping", "handoff"]).optional().describe(
11752
+ entryId: z21.string().max(200).optional().describe("For 'check'/'re-evaluate'/'audit': entry ID, e.g. 'TEN-graph-db', '<PREFIX>-<n>'."),
11753
+ context: z21.enum(["capture", "commit", "review"]).default("review").optional().describe("For re-evaluate: evaluation context"),
11754
+ collection: z21.string().max(200).optional().describe("For 'verify-chain': collection slug to verify (default: glossary)."),
11755
+ mode: z21.enum(["report", "fix"]).optional().describe("For 'verify-chain': 'report' = read-only trust report (default). 'fix' = also update drifted codeMapping statuses."),
11756
+ phase: z21.enum(["shaping", "handoff"]).optional().describe(
11302
11757
  "For 'audit': 'shaping' checks shaping-phase fields only (default). 'handoff' checks all required fields including buildContract/buildSequence/exclusions/risks."
11303
11758
  )
11304
11759
  });
11305
- var qualityCheckVariant = z19.object({ action: z19.literal("check"), entryId: z19.string().max(200) });
11306
- var qualityReEvaluateVariant = z19.object({
11307
- action: z19.literal("re-evaluate"),
11308
- entryId: z19.string().max(200),
11309
- context: z19.enum(["capture", "commit", "review"]).optional().default("review")
11760
+ var qualityCheckVariant = z21.object({ action: z21.literal("check"), entryId: z21.string().max(200) });
11761
+ var qualityReEvaluateVariant = z21.object({
11762
+ action: z21.literal("re-evaluate"),
11763
+ entryId: z21.string().max(200),
11764
+ context: z21.enum(["capture", "commit", "review"]).optional().default("review")
11310
11765
  });
11311
- var qualityVerifyChainVariant = z19.object({
11312
- action: z19.literal("verify-chain"),
11313
- collection: z19.string().max(200).optional().default("glossary"),
11314
- mode: z19.enum(["report", "fix"]).optional().default("report")
11766
+ var qualityVerifyChainVariant = z21.object({
11767
+ action: z21.literal("verify-chain"),
11768
+ collection: z21.string().max(200).optional().default("glossary"),
11769
+ mode: z21.enum(["report", "fix"]).optional().default("report")
11315
11770
  });
11316
- var qualityAuditVariant = z19.object({
11317
- action: z19.literal("audit"),
11318
- entryId: z19.string().max(200),
11319
- phase: z19.enum(["shaping", "handoff"]).optional().default("shaping")
11771
+ var qualityAuditVariant = z21.object({
11772
+ action: z21.literal("audit"),
11773
+ entryId: z21.string().max(200),
11774
+ phase: z21.enum(["shaping", "handoff"]).optional().default("shaping")
11320
11775
  });
11321
- var qualityActionUnion = z19.discriminatedUnion("action", [
11776
+ var qualityActionUnion = z21.discriminatedUnion("action", [
11322
11777
  qualityCheckVariant,
11323
11778
  qualityReEvaluateVariant,
11324
11779
  qualityVerifyChainVariant,
@@ -11330,27 +11785,27 @@ var QUALITY_ACTION_SPECS = {
11330
11785
  "verify-chain": { params: ["collection", "mode"], description: "All params optional; collection defaults to 'glossary'." },
11331
11786
  audit: { params: ["entryId", "phase"], description: "entryId is required." }
11332
11787
  };
11333
- var qualityCheckOutputSchema = z19.object({
11334
- entryId: z19.string(),
11788
+ var qualityCheckOutputSchema = z21.object({
11789
+ entryId: z21.string(),
11335
11790
  /** WP-480 S1: false = the ID does not resolve to an entry (typo/deleted) — distinct from "no verdict yet". */
11336
- entryFound: z19.boolean().optional(),
11337
- hasVerdict: z19.boolean(),
11791
+ entryFound: z21.boolean().optional(),
11792
+ hasVerdict: z21.boolean(),
11338
11793
  /** WP-480 S1: the verdict was judged against content the entry no longer has — re-evaluate for a current one. */
11339
- stale: z19.boolean().optional(),
11340
- tier: z19.string().optional(),
11341
- passed: z19.boolean().optional(),
11342
- criteria: z19.array(z19.object({
11343
- id: z19.string(),
11344
- passed: z19.boolean(),
11345
- hint: z19.string().optional()
11794
+ stale: z21.boolean().optional(),
11795
+ tier: z21.string().optional(),
11796
+ passed: z21.boolean().optional(),
11797
+ criteria: z21.array(z21.object({
11798
+ id: z21.string(),
11799
+ passed: z21.boolean(),
11800
+ hint: z21.string().optional()
11346
11801
  }))
11347
11802
  });
11348
- var qualityReevaluateOutputSchema = z19.object({
11349
- entryId: z19.string(),
11350
- context: z19.string(),
11351
- score: z19.number(),
11352
- maxScore: z19.number(),
11353
- improved: z19.boolean()
11803
+ var qualityReevaluateOutputSchema = z21.object({
11804
+ entryId: z21.string(),
11805
+ context: z21.string(),
11806
+ score: z21.number(),
11807
+ maxScore: z21.number(),
11808
+ improved: z21.boolean()
11354
11809
  });
11355
11810
  function registerQualityTools(server) {
11356
11811
  const qualityHandlers = {
@@ -11531,10 +11986,10 @@ async function handleReEvaluate(entryId, context) {
11531
11986
  }
11532
11987
 
11533
11988
  // src/tools/session.ts
11534
- import { z as z22 } from "zod/v3";
11989
+ import { z as z24 } from "zod/v3";
11535
11990
 
11536
11991
  // src/tools/wrapup.ts
11537
- import { z as z20 } from "zod/v3";
11992
+ import { z as z22 } from "zod/v3";
11538
11993
 
11539
11994
  // src/lib/compose-wrapup-view.ts
11540
11995
  function toComposed(e) {
@@ -11987,8 +12442,8 @@ async function runWrapupCommitAll(data, cachedSuggestions) {
11987
12442
  overflowUnscanned
11988
12443
  };
11989
12444
  }
11990
- var wrapupSchema = z20.object({
11991
- action: z20.enum(["review", "commit-all"]).optional().describe(
12445
+ var wrapupSchema = z22.object({
12446
+ action: z22.enum(["review", "commit-all"]).optional().describe(
11992
12447
  "Action to perform. 'review' (default) shows the wrapup summary. 'commit-all' accepts all uncommitted drafts and creates suggested links."
11993
12448
  )
11994
12449
  });
@@ -12089,26 +12544,26 @@ ${text}` : text;
12089
12544
  }
12090
12545
 
12091
12546
  // src/tools/facilitate.ts
12092
- import { z as z21 } from "zod/v3";
12547
+ import { z as z23 } from "zod/v3";
12093
12548
  var FACILITATE_ACTIONS = ["resume", "commit-constellation"];
12094
- var coherencyAcknowledgementSchema = z21.object({
12095
- response: z21.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
12096
- entryId: z21.string().max(200).optional().describe("Entry the acknowledgement links to (e.g. the strategic spine entry)."),
12097
- reason: z21.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
12098
- subjectEntryId: z21.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
12549
+ var coherencyAcknowledgementSchema = z23.object({
12550
+ response: z23.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
12551
+ entryId: z23.string().max(200).optional().describe("Entry the acknowledgement links to (e.g. the strategic spine entry)."),
12552
+ reason: z23.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
12553
+ subjectEntryId: z23.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
12099
12554
  });
12100
- var facilitateSchema = z21.object({
12101
- action: z21.enum(FACILITATE_ACTIONS).describe(
12555
+ var facilitateSchema = z23.object({
12556
+ action: z23.enum(FACILITATE_ACTIONS).describe(
12102
12557
  "'resume': load session state from an existing bet entry. 'commit-constellation': atomically accept a bet and all its linked draft entries in one call. Requires betEntryId."
12103
12558
  ),
12104
- betEntryId: z21.string().max(200).optional().describe("Bet entry ID. Required for both actions."),
12105
- operationId: z21.string().max(200).optional().describe("Optional idempotency key for commit-constellation retries."),
12559
+ betEntryId: z23.string().max(200).optional().describe("Bet entry ID. Required for both actions."),
12560
+ operationId: z23.string().max(200).optional().describe("Optional idempotency key for commit-constellation retries."),
12106
12561
  // WP-465 slice ⑤: coherency retry controls for a COHERENCY_REFUSED constellation hold.
12107
12562
  // Forwarded verbatim to agentKnowledge.facilitateEnvelope (validation lives at the gate).
12108
- coherencyAcknowledgements: z21.array(coherencyAcknowledgementSchema).max(20).optional().describe(
12563
+ coherencyAcknowledgements: z23.array(coherencyAcknowledgementSchema).max(20).optional().describe(
12109
12564
  "Per-offender acknowledgements to retry a constellation held under standard/strict coherency mode. Each: {subjectEntryId, response: 'linked' | 'accepted-fix' | 'diverged', entryId?, reason?}."
12110
12565
  ),
12111
- steeringOverrideReason: z21.string().max(2e3).optional().describe(
12566
+ steeringOverrideReason: z23.string().max(2e3).optional().describe(
12112
12567
  "Typed override reason (>= 12 chars) to push a constellation past a coherency hold instead of acknowledging."
12113
12568
  )
12114
12569
  });
@@ -12361,33 +12816,33 @@ var SESSION_ACTIONS = [
12361
12816
  "resume",
12362
12817
  "commit-constellation"
12363
12818
  ];
12364
- var coherencyAcknowledgementFlatSchema2 = z22.object({
12365
- response: z22.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
12366
- entryId: z22.string().max(200).optional().describe("Entry the acknowledgement links to."),
12367
- reason: z22.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
12368
- subjectEntryId: z22.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
12819
+ var coherencyAcknowledgementFlatSchema2 = z24.object({
12820
+ response: z24.string().max(200).describe("Acknowledgement response per offender: 'linked' | 'accepted-fix' | 'diverged'."),
12821
+ entryId: z24.string().max(200).optional().describe("Entry the acknowledgement links to."),
12822
+ reason: z24.string().max(2e3).optional().describe("Free-text justification, required for a 'diverged' response."),
12823
+ subjectEntryId: z24.string().max(200).optional().describe("The refused entry this acknowledgement answers.")
12369
12824
  });
12370
- var sessionSchema = z22.object({
12371
- action: z22.enum(SESSION_ACTIONS).describe(
12825
+ var sessionSchema = z24.object({
12826
+ action: z24.enum(SESSION_ACTIONS).describe(
12372
12827
  "'start': begin a tracked session. 'close': end the session and record activity. 'status': check current session state. 'wrapup-review': review uncommitted drafts before closing (absorbs session-wrapup action=review). 'wrapup-commit': accept all uncommitted drafts (absorbs session-wrapup action=commit-all). 'resume': load session state from an existing bet entry (absorbs facilitate action=resume). 'commit-constellation': atomically accept a bet and its linked drafts (absorbs facilitate action=commit-constellation)."
12373
12828
  ),
12374
- betEntryId: z22.string().max(200).optional().describe("For 'resume'/'commit-constellation': bet entry ID. Required for both."),
12375
- operationId: z22.string().max(200).optional().describe("For 'commit-constellation': optional idempotency key for retries."),
12376
- coherencyAcknowledgements: z22.array(coherencyAcknowledgementFlatSchema2).max(20).optional().describe(
12829
+ betEntryId: z24.string().max(200).optional().describe("For 'resume'/'commit-constellation': bet entry ID. Required for both."),
12830
+ operationId: z24.string().max(200).optional().describe("For 'commit-constellation': optional idempotency key for retries."),
12831
+ coherencyAcknowledgements: z24.array(coherencyAcknowledgementFlatSchema2).max(20).optional().describe(
12377
12832
  "For 'commit-constellation': per-offender acknowledgements to retry a constellation held under standard/strict coherency mode."
12378
12833
  ),
12379
- steeringOverrideReason: z22.string().max(2e3).optional().describe(
12834
+ steeringOverrideReason: z24.string().max(2e3).optional().describe(
12380
12835
  "For 'commit-constellation': typed override reason (>= 12 chars) to push past a coherency hold instead of acknowledging."
12381
12836
  )
12382
12837
  });
12383
- var sessionStartVariant = z22.object({ action: z22.literal("start") });
12384
- var sessionCloseVariant = z22.object({ action: z22.literal("close") });
12385
- var sessionStatusVariant = z22.object({ action: z22.literal("status") });
12386
- var sessionWrapupReviewVariant = z22.object({ action: z22.literal("wrapup-review") });
12387
- var sessionWrapupCommitVariant = z22.object({ action: z22.literal("wrapup-commit") });
12388
- var sessionResumeVariant = facilitateSchema.omit({ action: true }).extend({ action: z22.literal("resume") });
12389
- var sessionCommitConstellationVariant = facilitateSchema.omit({ action: true }).extend({ action: z22.literal("commit-constellation") });
12390
- var sessionActionUnion = z22.discriminatedUnion("action", [
12838
+ var sessionStartVariant = z24.object({ action: z24.literal("start") });
12839
+ var sessionCloseVariant = z24.object({ action: z24.literal("close") });
12840
+ var sessionStatusVariant = z24.object({ action: z24.literal("status") });
12841
+ var sessionWrapupReviewVariant = z24.object({ action: z24.literal("wrapup-review") });
12842
+ var sessionWrapupCommitVariant = z24.object({ action: z24.literal("wrapup-commit") });
12843
+ var sessionResumeVariant = facilitateSchema.omit({ action: true }).extend({ action: z24.literal("resume") });
12844
+ var sessionCommitConstellationVariant = facilitateSchema.omit({ action: true }).extend({ action: z24.literal("commit-constellation") });
12845
+ var sessionActionUnion = z24.discriminatedUnion("action", [
12391
12846
  sessionStartVariant,
12392
12847
  sessionCloseVariant,
12393
12848
  sessionStatusVariant,
@@ -12611,7 +13066,7 @@ async function handleStatus() {
12611
13066
  }
12612
13067
 
12613
13068
  // src/tools/gitchain.ts
12614
- import { z as z23 } from "zod/v3";
13069
+ import { z as z25 } from "zod/v3";
12615
13070
 
12616
13071
  // src/lib/versionDisplay.ts
12617
13072
  function toVersionDisplay(version) {
@@ -12620,51 +13075,51 @@ function toVersionDisplay(version) {
12620
13075
  }
12621
13076
 
12622
13077
  // src/tools/gitchain.ts
12623
- var chainSchema = z23.object({
12624
- action: z23.enum(["create", "get", "list", "edit"]).describe("Action: create a process, get process details, list all processes, or edit a process link"),
12625
- chainEntryId: z23.string().max(200).optional().describe("Chain entry ID (required for get/edit)"),
12626
- title: z23.string().max(500).optional().describe("Process title (required for create)"),
12627
- chainTypeId: z23.string().max(200).optional().default("strategy-coherence").describe("Process template slug for create: 'strategy-coherence', 'idm-proposal', or any custom template slug"),
12628
- description: z23.string().max(2e4).optional().describe("Description (for create)"),
12629
- linkId: z23.string().max(200).optional().describe("Link to edit (for edit action): problem, insight, choice, action, outcome"),
12630
- content: z23.string().max(5e4).optional().describe("New content for the link (for edit action)"),
12631
- status: z23.string().max(200).optional().describe("Filter by status for list: 'draft' or 'active'"),
12632
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'."),
13078
+ var chainSchema = z25.object({
13079
+ action: z25.enum(["create", "get", "list", "edit"]).describe("Action: create a process, get process details, list all processes, or edit a process link"),
13080
+ chainEntryId: z25.string().max(200).optional().describe("Chain entry ID (required for get/edit)"),
13081
+ title: z25.string().max(500).optional().describe("Process title (required for create)"),
13082
+ chainTypeId: z25.string().max(200).optional().default("strategy-coherence").describe("Process template slug for create: 'strategy-coherence', 'idm-proposal', or any custom template slug"),
13083
+ description: z25.string().max(2e4).optional().describe("Description (for create)"),
13084
+ linkId: z25.string().max(200).optional().describe("Link to edit (for edit action): problem, insight, choice, action, outcome"),
13085
+ content: z25.string().max(5e4).optional().describe("New content for the link (for edit action)"),
13086
+ status: z25.string().max(200).optional().describe("Filter by status for list: 'draft' or 'active'"),
13087
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'."),
12633
13088
  // WP-513 review round 3 (P1): team+role to create AS OWNER of (rung 2 only) — entry ID or entryId (e.g. "TEAM-1").
12634
- ownerTeamEntryId: z23.string().max(200).optional().describe("For 'create': owning team (rung-2 workspaces)."),
12635
- ownerRoleEntryId: z23.string().max(200).optional().describe("For 'create': owning role (rung-2 workspaces).")
13089
+ ownerTeamEntryId: z25.string().max(200).optional().describe("For 'create': owning team (rung-2 workspaces)."),
13090
+ ownerRoleEntryId: z25.string().max(200).optional().describe("For 'create': owning role (rung-2 workspaces).")
12636
13091
  });
12637
- var chainVersionSchema = z23.object({
12638
- action: z23.enum(["commit", "list", "diff", "revert", "history"]).describe("Action: commit a snapshot, list commits, diff two versions, revert to a version, or view history"),
12639
- chainEntryId: z23.string().max(200).describe("The chain's entry ID"),
12640
- commitMessage: z23.string().max(2e3).optional().describe("Commit message (required for commit). Convention: type(link): description"),
12641
- versionA: z23.number().optional().describe("Earlier version for diff"),
12642
- versionB: z23.number().optional().describe("Later version for diff"),
12643
- toVersion: z23.number().optional().describe("Version number to revert to"),
12644
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
13092
+ var chainVersionSchema = z25.object({
13093
+ action: z25.enum(["commit", "list", "diff", "revert", "history"]).describe("Action: commit a snapshot, list commits, diff two versions, revert to a version, or view history"),
13094
+ chainEntryId: z25.string().max(200).describe("The chain's entry ID"),
13095
+ commitMessage: z25.string().max(2e3).optional().describe("Commit message (required for commit). Convention: type(link): description"),
13096
+ versionA: z25.number().optional().describe("Earlier version for diff"),
13097
+ versionB: z25.number().optional().describe("Later version for diff"),
13098
+ toVersion: z25.number().optional().describe("Version number to revert to"),
13099
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
12645
13100
  });
12646
- var chainBranchSchema = z23.object({
12647
- action: z23.enum(["create", "list", "merge", "conflicts"]).describe("Action: create a branch, list branches, merge a branch, or check for conflicts"),
12648
- chainEntryId: z23.string().max(200).describe("The chain's entry ID"),
12649
- branchName: z23.string().max(200).optional().describe("Branch name (required for merge/conflicts, optional for create)"),
12650
- strategy: z23.enum(["merge_commit", "squash"]).optional().describe("Merge strategy: 'merge_commit' (default) or 'squash'"),
12651
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
13101
+ var chainBranchSchema = z25.object({
13102
+ action: z25.enum(["create", "list", "merge", "conflicts"]).describe("Action: create a branch, list branches, merge a branch, or check for conflicts"),
13103
+ chainEntryId: z25.string().max(200).describe("The chain's entry ID"),
13104
+ branchName: z25.string().max(200).optional().describe("Branch name (required for merge/conflicts, optional for create)"),
13105
+ strategy: z25.enum(["merge_commit", "squash"]).optional().describe("Merge strategy: 'merge_commit' (default) or 'squash'"),
13106
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
12652
13107
  });
12653
- var chainReviewSchema = z23.object({
12654
- action: z23.enum(["gate", "comment", "resolve-comment", "list-comments"]).describe("Action: run coherence gate, add a comment, resolve a comment, or list comments"),
13108
+ var chainReviewSchema = z25.object({
13109
+ action: z25.enum(["gate", "comment", "resolve-comment", "list-comments"]).describe("Action: run coherence gate, add a comment, resolve a comment, or list comments"),
12655
13110
  // Finding #12: optional at the base (mirrors chainSchema's chainEntryId pattern at
12656
13111
  // line ~690) — resolve-comment resolves purely by commentId (handleChainReview never
12657
13112
  // reads chainEntryId in that branch) and the compound-tool's advertised schema
12658
13113
  // (chainReviewCompoundSchema below) already documents it as optional for that action.
12659
13114
  // Per-action variants that DO need it (gate/comment/list-comments) re-require it below,
12660
13115
  // same pattern as chainGetVariant/chainEditVariant re-requiring over chainSchema's base.
12661
- chainEntryId: z23.string().max(200).optional().describe("The chain's entry ID. Required for every action except 'resolve-comment'."),
12662
- commitMessage: z23.string().max(2e3).optional().describe("Commit message to lint (for gate action)"),
12663
- versionNumber: z23.number().optional().describe("Version to comment on or list comments for"),
12664
- linkId: z23.string().max(200).optional().describe("Link this comment targets (optional for comment)"),
12665
- body: z23.string().max(2e4).optional().describe("Comment text (required for comment action)"),
12666
- commentId: z23.string().max(200).optional().describe("Comment ID (required for resolve-comment)"),
12667
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
13116
+ chainEntryId: z25.string().max(200).optional().describe("The chain's entry ID. Required for every action except 'resolve-comment'."),
13117
+ commitMessage: z25.string().max(2e3).optional().describe("Commit message to lint (for gate action)"),
13118
+ versionNumber: z25.number().optional().describe("Version to comment on or list comments for"),
13119
+ linkId: z25.string().max(200).optional().describe("Link this comment targets (optional for comment)"),
13120
+ body: z25.string().max(2e4).optional().describe("Comment text (required for comment action)"),
13121
+ commentId: z25.string().max(200).optional().describe("Comment ID (required for resolve-comment)"),
13122
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
12668
13123
  });
12669
13124
  function linkSummary(links) {
12670
13125
  return Object.entries(links).map(([id, content]) => {
@@ -13169,57 +13624,57 @@ var CHAIN_REVIEW_ACTIONS = [
13169
13624
  "branch.merge",
13170
13625
  "branch.conflicts"
13171
13626
  ];
13172
- var chainCompoundSchema = z23.object({
13173
- action: z23.enum(CHAIN_ACTIONS).describe(
13627
+ var chainCompoundSchema = z25.object({
13628
+ action: z25.enum(CHAIN_ACTIONS).describe(
13174
13629
  "Unnamespaced: 'create'/'get'/'list'/'edit' \u2014 process CRUD (the original `chain` tool). 'version.*' (commit/list/diff/revert/history) \u2014 versioning, absorbs `chain-version`. Branching and review live on the sibling `chain-review` tool."
13175
13630
  ),
13176
- chainEntryId: z23.string().max(200).optional().describe("Chain entry ID. Required for get/edit and all version.* actions."),
13177
- title: z23.string().max(500).optional().describe("For 'create': process title (required)."),
13178
- chainTypeId: z23.string().max(200).optional().default("strategy-coherence").describe("For 'create'/'list': process template slug."),
13179
- description: z23.string().max(2e4).optional().describe("For 'create': description."),
13180
- linkId: z23.string().max(200).optional().describe("For 'edit': link to edit (required)."),
13181
- content: z23.string().max(5e4).optional().describe("For 'edit': new content for the link (required)."),
13182
- status: z23.string().max(200).optional().describe("For 'list': filter by status."),
13183
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'."),
13184
- commitMessage: z23.string().max(2e3).optional().describe("For 'version.commit': commit message (required)."),
13185
- versionA: z23.number().optional().describe("For 'version.diff': earlier version (required)."),
13186
- versionB: z23.number().optional().describe("For 'version.diff': later version (required)."),
13187
- toVersion: z23.number().optional().describe("For 'version.revert': version number to revert to (required)."),
13631
+ chainEntryId: z25.string().max(200).optional().describe("Chain entry ID. Required for get/edit and all version.* actions."),
13632
+ title: z25.string().max(500).optional().describe("For 'create': process title (required)."),
13633
+ chainTypeId: z25.string().max(200).optional().default("strategy-coherence").describe("For 'create'/'list': process template slug."),
13634
+ description: z25.string().max(2e4).optional().describe("For 'create': description."),
13635
+ linkId: z25.string().max(200).optional().describe("For 'edit': link to edit (required)."),
13636
+ content: z25.string().max(5e4).optional().describe("For 'edit': new content for the link (required)."),
13637
+ status: z25.string().max(200).optional().describe("For 'list': filter by status."),
13638
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'."),
13639
+ commitMessage: z25.string().max(2e3).optional().describe("For 'version.commit': commit message (required)."),
13640
+ versionA: z25.number().optional().describe("For 'version.diff': earlier version (required)."),
13641
+ versionB: z25.number().optional().describe("For 'version.diff': later version (required)."),
13642
+ toVersion: z25.number().optional().describe("For 'version.revert': version number to revert to (required)."),
13188
13643
  // WP-513 review round 3 (P1): team+role to create AS OWNER of (rung 2 only).
13189
- ownerTeamEntryId: z23.string().max(200).optional().describe("For 'create': owning team (rung-2 workspaces)."),
13190
- ownerRoleEntryId: z23.string().max(200).optional().describe("For 'create': owning role (rung-2 workspaces).")
13644
+ ownerTeamEntryId: z25.string().max(200).optional().describe("For 'create': owning team (rung-2 workspaces)."),
13645
+ ownerRoleEntryId: z25.string().max(200).optional().describe("For 'create': owning role (rung-2 workspaces).")
13191
13646
  });
13192
- var chainReviewCompoundSchema = z23.object({
13193
- action: z23.enum(CHAIN_REVIEW_ACTIONS).describe(
13647
+ var chainReviewCompoundSchema = z25.object({
13648
+ action: z25.enum(CHAIN_REVIEW_ACTIONS).describe(
13194
13649
  "'gate'/'comment'/'resolve-comment'/'list-comments' \u2014 quality gate + comments (the original `chain-review` tool, unchanged call shape). 'branch.*' (create/list/merge/conflicts) \u2014 branching, absorbs `chain-branch`. Process CRUD and versioning live on the sibling `chain` tool."
13195
13650
  ),
13196
- chainEntryId: z23.string().max(200).optional().describe("Chain entry ID. Required for every action except 'resolve-comment'."),
13197
- commitMessage: z23.string().max(2e3).optional().describe("For 'gate': commit message to lint."),
13198
- versionNumber: z23.number().optional().describe("For 'comment'/'list-comments': version to comment on or list comments for."),
13199
- linkId: z23.string().max(200).optional().describe("For 'comment': optional link this comment targets."),
13200
- body: z23.string().max(2e4).optional().describe("For 'comment': comment text (required)."),
13201
- commentId: z23.string().max(200).optional().describe("For 'resolve-comment': comment ID (required)."),
13202
- branchName: z23.string().max(200).optional().describe("For 'branch.merge'/'branch.conflicts': required. For 'branch.create': optional."),
13203
- strategy: z23.enum(["merge_commit", "squash"]).optional().describe("For 'branch.merge': merge strategy. Default 'merge_commit'."),
13204
- author: z23.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
13651
+ chainEntryId: z25.string().max(200).optional().describe("Chain entry ID. Required for every action except 'resolve-comment'."),
13652
+ commitMessage: z25.string().max(2e3).optional().describe("For 'gate': commit message to lint."),
13653
+ versionNumber: z25.number().optional().describe("For 'comment'/'list-comments': version to comment on or list comments for."),
13654
+ linkId: z25.string().max(200).optional().describe("For 'comment': optional link this comment targets."),
13655
+ body: z25.string().max(2e4).optional().describe("For 'comment': comment text (required)."),
13656
+ commentId: z25.string().max(200).optional().describe("For 'resolve-comment': comment ID (required)."),
13657
+ branchName: z25.string().max(200).optional().describe("For 'branch.merge'/'branch.conflicts': required. For 'branch.create': optional."),
13658
+ strategy: z25.enum(["merge_commit", "squash"]).optional().describe("For 'branch.merge': merge strategy. Default 'merge_commit'."),
13659
+ author: z25.string().max(200).optional().describe("Who is performing the action. Defaults to 'mcp'.")
13205
13660
  });
13206
- var chainCreateVariant = chainSchema.omit({ action: true }).extend({ action: z23.literal("create") });
13207
- var chainGetVariant = z23.object({ action: z23.literal("get"), chainEntryId: z23.string().max(200) });
13208
- var chainListVariant = z23.object({ action: z23.literal("list"), chainTypeId: z23.string().max(200).optional(), status: z23.string().max(200).optional() });
13209
- var chainEditVariant = z23.object({
13210
- action: z23.literal("edit"),
13211
- chainEntryId: z23.string().max(200),
13212
- linkId: z23.string().max(200),
13213
- content: z23.string().max(5e4),
13214
- author: z23.string().max(200).optional()
13661
+ var chainCreateVariant = chainSchema.omit({ action: true }).extend({ action: z25.literal("create") });
13662
+ var chainGetVariant = z25.object({ action: z25.literal("get"), chainEntryId: z25.string().max(200) });
13663
+ var chainListVariant = z25.object({ action: z25.literal("list"), chainTypeId: z25.string().max(200).optional(), status: z25.string().max(200).optional() });
13664
+ var chainEditVariant = z25.object({
13665
+ action: z25.literal("edit"),
13666
+ chainEntryId: z25.string().max(200),
13667
+ linkId: z25.string().max(200),
13668
+ content: z25.string().max(5e4),
13669
+ author: z25.string().max(200).optional()
13215
13670
  });
13216
13671
  var versionBase = chainVersionSchema.omit({ action: true });
13217
- var chainVersionCommitVariant = versionBase.extend({ action: z23.literal("version.commit"), commitMessage: z23.string().max(2e3) });
13218
- var chainVersionListVariant = versionBase.extend({ action: z23.literal("version.list") });
13219
- var chainVersionDiffVariant = versionBase.extend({ action: z23.literal("version.diff"), versionA: z23.number(), versionB: z23.number() });
13220
- var chainVersionRevertVariant = versionBase.extend({ action: z23.literal("version.revert"), toVersion: z23.number() });
13221
- var chainVersionHistoryVariant = versionBase.extend({ action: z23.literal("version.history") });
13222
- var chainActionUnion = z23.discriminatedUnion("action", [
13672
+ var chainVersionCommitVariant = versionBase.extend({ action: z25.literal("version.commit"), commitMessage: z25.string().max(2e3) });
13673
+ var chainVersionListVariant = versionBase.extend({ action: z25.literal("version.list") });
13674
+ var chainVersionDiffVariant = versionBase.extend({ action: z25.literal("version.diff"), versionA: z25.number(), versionB: z25.number() });
13675
+ var chainVersionRevertVariant = versionBase.extend({ action: z25.literal("version.revert"), toVersion: z25.number() });
13676
+ var chainVersionHistoryVariant = versionBase.extend({ action: z25.literal("version.history") });
13677
+ var chainActionUnion = z25.discriminatedUnion("action", [
13223
13678
  chainCreateVariant,
13224
13679
  chainGetVariant,
13225
13680
  chainListVariant,
@@ -13231,16 +13686,16 @@ var chainActionUnion = z23.discriminatedUnion("action", [
13231
13686
  chainVersionHistoryVariant
13232
13687
  ]);
13233
13688
  var reviewBase = chainReviewSchema.omit({ action: true });
13234
- var chainReviewGateVariant = reviewBase.extend({ action: z23.literal("gate"), chainEntryId: z23.string().max(200) });
13235
- var chainReviewCommentVariant = reviewBase.extend({ action: z23.literal("comment"), chainEntryId: z23.string().max(200), versionNumber: z23.number(), body: z23.string().max(2e4) });
13236
- var chainReviewResolveCommentVariant = reviewBase.extend({ action: z23.literal("resolve-comment"), commentId: z23.string().max(200) });
13237
- var chainReviewListCommentsVariant = reviewBase.extend({ action: z23.literal("list-comments"), chainEntryId: z23.string().max(200) });
13689
+ var chainReviewGateVariant = reviewBase.extend({ action: z25.literal("gate"), chainEntryId: z25.string().max(200) });
13690
+ var chainReviewCommentVariant = reviewBase.extend({ action: z25.literal("comment"), chainEntryId: z25.string().max(200), versionNumber: z25.number(), body: z25.string().max(2e4) });
13691
+ var chainReviewResolveCommentVariant = reviewBase.extend({ action: z25.literal("resolve-comment"), commentId: z25.string().max(200) });
13692
+ var chainReviewListCommentsVariant = reviewBase.extend({ action: z25.literal("list-comments"), chainEntryId: z25.string().max(200) });
13238
13693
  var branchBase = chainBranchSchema.omit({ action: true });
13239
- var chainBranchCreateVariant = branchBase.extend({ action: z23.literal("branch.create") });
13240
- var chainBranchListVariant = branchBase.extend({ action: z23.literal("branch.list") });
13241
- var chainBranchMergeVariant = branchBase.extend({ action: z23.literal("branch.merge"), branchName: z23.string().max(200) });
13242
- var chainBranchConflictsVariant = branchBase.extend({ action: z23.literal("branch.conflicts"), branchName: z23.string().max(200) });
13243
- var chainReviewActionUnion = z23.discriminatedUnion("action", [
13694
+ var chainBranchCreateVariant = branchBase.extend({ action: z25.literal("branch.create") });
13695
+ var chainBranchListVariant = branchBase.extend({ action: z25.literal("branch.list") });
13696
+ var chainBranchMergeVariant = branchBase.extend({ action: z25.literal("branch.merge"), branchName: z25.string().max(200) });
13697
+ var chainBranchConflictsVariant = branchBase.extend({ action: z25.literal("branch.conflicts"), branchName: z25.string().max(200) });
13698
+ var chainReviewActionUnion = z25.discriminatedUnion("action", [
13244
13699
  chainReviewGateVariant,
13245
13700
  chainReviewCommentVariant,
13246
13701
  chainReviewResolveCommentVariant,
@@ -13332,44 +13787,44 @@ function registerGitChainTools(server) {
13332
13787
  }
13333
13788
 
13334
13789
  // src/tools/maps.ts
13335
- import { z as z24 } from "zod/v3";
13336
- var createAudienceMapSetSchema = z24.object({
13337
- audienceEntryId: z24.string().max(200).describe("Entry ID of the audience (e.g. STR-fb7hje)"),
13790
+ import { z as z26 } from "zod/v3";
13791
+ var createAudienceMapSetSchema = z26.object({
13792
+ audienceEntryId: z26.string().max(200).describe("Entry ID of the audience (e.g. STR-fb7hje)"),
13338
13793
  // WP-513: team+role to create AS OWNER of (rung 2); ID or entryId (e.g. "TEAM-1"); no-op pre-rung-2.
13339
- ownerTeamEntryId: z24.string().max(200).optional().describe("Team entry ID/ref to own the created maps (required once the workspace is on rung 2)"),
13340
- ownerRoleEntryId: z24.string().max(200).optional().describe("Role entry ID/ref to own the created maps (required once the workspace is on rung 2)")
13794
+ ownerTeamEntryId: z26.string().max(200).optional().describe("Team entry ID/ref to own the created maps (required once the workspace is on rung 2)"),
13795
+ ownerRoleEntryId: z26.string().max(200).optional().describe("Role entry ID/ref to own the created maps (required once the workspace is on rung 2)")
13341
13796
  });
13342
- var mapSchema = z24.object({
13343
- action: z24.enum(["create", "get", "list"]).describe("Action: create a map, get map details, or list all maps"),
13344
- mapEntryId: z24.string().max(200).optional().describe("Map entry ID (for get)"),
13345
- title: z24.string().max(500).optional().describe("Map title (for create)"),
13346
- templateId: z24.string().max(200).optional().default("lean-canvas").describe("Template slug for create: 'lean-canvas' or any composed template"),
13347
- description: z24.string().max(2e4).optional().describe("Description (for create)"),
13348
- slotIds: z24.array(z24.string().max(200)).max(200).optional().describe("Slot IDs to initialize (for create; auto-populated from template if omitted)"),
13349
- status: z24.string().max(200).optional().describe("Filter by status for list"),
13797
+ var mapSchema = z26.object({
13798
+ action: z26.enum(["create", "get", "list"]).describe("Action: create a map, get map details, or list all maps"),
13799
+ mapEntryId: z26.string().max(200).optional().describe("Map entry ID (for get)"),
13800
+ title: z26.string().max(500).optional().describe("Map title (for create)"),
13801
+ templateId: z26.string().max(200).optional().default("lean-canvas").describe("Template slug for create: 'lean-canvas' or any composed template"),
13802
+ description: z26.string().max(2e4).optional().describe("Description (for create)"),
13803
+ slotIds: z26.array(z26.string().max(200)).max(200).optional().describe("Slot IDs to initialize (for create; auto-populated from template if omitted)"),
13804
+ status: z26.string().max(200).optional().describe("Filter by status for list"),
13350
13805
  // WP-513: team+role to create AS OWNER of (rung 2, action "create" only); no-op pre-rung-2.
13351
- ownerTeamEntryId: z24.string().max(200).optional().describe("Team entry ID/ref to own the created map (required once the workspace is on rung 2)"),
13352
- ownerRoleEntryId: z24.string().max(200).optional().describe("Role entry ID/ref to own the created map (required once the workspace is on rung 2)")
13806
+ ownerTeamEntryId: z26.string().max(200).optional().describe("Team entry ID/ref to own the created map (required once the workspace is on rung 2)"),
13807
+ ownerRoleEntryId: z26.string().max(200).optional().describe("Role entry ID/ref to own the created map (required once the workspace is on rung 2)")
13353
13808
  });
13354
- var mapSlotSchema = z24.object({
13355
- action: z24.enum(["add", "remove", "replace", "list"]).describe("Action: add/remove/replace an ingredient in a slot, or list slot contents"),
13356
- mapEntryId: z24.string().max(200).describe("Map entry ID"),
13357
- slotId: z24.string().max(200).optional().describe("Slot ID (e.g. 'problem', 'customer-segments')"),
13358
- ingredientEntryId: z24.string().max(200).optional().describe("Ingredient entry ID to add/remove"),
13359
- newIngredientEntryId: z24.string().max(200).optional().describe("New ingredient entry ID (for replace)"),
13360
- label: z24.string().max(500).optional().describe("Display label override"),
13361
- author: z24.string().max(200).optional().describe("Who is performing the action")
13809
+ var mapSlotSchema = z26.object({
13810
+ action: z26.enum(["add", "remove", "replace", "list"]).describe("Action: add/remove/replace an ingredient in a slot, or list slot contents"),
13811
+ mapEntryId: z26.string().max(200).describe("Map entry ID"),
13812
+ slotId: z26.string().max(200).optional().describe("Slot ID (e.g. 'problem', 'customer-segments')"),
13813
+ ingredientEntryId: z26.string().max(200).optional().describe("Ingredient entry ID to add/remove"),
13814
+ newIngredientEntryId: z26.string().max(200).optional().describe("New ingredient entry ID (for replace)"),
13815
+ label: z26.string().max(500).optional().describe("Display label override"),
13816
+ author: z26.string().max(200).optional().describe("Who is performing the action")
13362
13817
  });
13363
- var mapVersionSchema = z24.object({
13364
- action: z24.enum(["commit", "list", "history"]).describe("Action: commit the map, list commits, or view commit history"),
13365
- mapEntryId: z24.string().max(200).describe("Map entry ID"),
13366
- commitMessage: z24.string().max(2e3).optional().describe("Commit message (for commit action)"),
13367
- author: z24.string().max(200).optional().describe("Who is committing")
13818
+ var mapVersionSchema = z26.object({
13819
+ action: z26.enum(["commit", "list", "history"]).describe("Action: commit the map, list commits, or view commit history"),
13820
+ mapEntryId: z26.string().max(200).describe("Map entry ID"),
13821
+ commitMessage: z26.string().max(2e3).optional().describe("Commit message (for commit action)"),
13822
+ author: z26.string().max(200).optional().describe("Who is committing")
13368
13823
  });
13369
- var mapSuggestSchema = z24.object({
13370
- mapEntryId: z24.string().max(200).describe("Map entry ID to suggest ingredients for"),
13371
- slotId: z24.string().max(200).optional().describe("Specific slot to find ingredients for (or all empty slots)"),
13372
- query: z24.string().max(500).optional().describe("Optional search query to narrow ingredient suggestions")
13824
+ var mapSuggestSchema = z26.object({
13825
+ mapEntryId: z26.string().max(200).describe("Map entry ID to suggest ingredients for"),
13826
+ slotId: z26.string().max(200).optional().describe("Specific slot to find ingredients for (or all empty slots)"),
13827
+ query: z26.string().max(500).optional().describe("Optional search query to narrow ingredient suggestions")
13373
13828
  });
13374
13829
  function slotSummary(slots) {
13375
13830
  return Object.entries(slots).map(([id, refs]) => {
@@ -13749,43 +14204,43 @@ var MAP_ACTIONS = [
13749
14204
  "suggest",
13750
14205
  "create-audience-set"
13751
14206
  ];
13752
- var mapCompoundSchema = z24.object({
13753
- action: z24.enum(MAP_ACTIONS).describe(
14207
+ var mapCompoundSchema = z26.object({
14208
+ action: z26.enum(MAP_ACTIONS).describe(
13754
14209
  "Unnamespaced: 'create'/'get'/'list' \u2014 map CRUD (the original `map` tool). 'slot.*' (add/remove/replace/list) \u2014 ingredient slot management, absorbs `map-slot`. 'version.*' (commit/list/history) \u2014 versioning, absorbs `map-version`. 'suggest' \u2014 find ingredients to fill empty slots, absorbs `map-suggest`. 'create-audience-set' \u2014 create all three audience intelligence maps at once, absorbs `create-audience-map-set`."
13755
14210
  ),
13756
- mapEntryId: z24.string().max(200).optional().describe("Map entry ID. Required for get and all slot.*/version.*/suggest actions."),
13757
- title: z24.string().max(500).optional().describe("For 'create': map title (required)."),
13758
- templateId: z24.string().max(200).optional().default("lean-canvas").describe("For 'create': template slug."),
13759
- description: z24.string().max(2e4).optional().describe("For 'create': description."),
13760
- slotIds: z24.array(z24.string().max(200)).max(200).optional().describe("For 'create': slot IDs to initialize."),
13761
- status: z24.string().max(200).optional().describe("For 'list': filter by status."),
13762
- slotId: z24.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': slot ID (required). For 'suggest': specific slot (optional)."),
13763
- ingredientEntryId: z24.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': ingredient entry ID to add/remove (required)."),
13764
- newIngredientEntryId: z24.string().max(200).optional().describe("For 'slot.replace': new ingredient entry ID (required)."),
13765
- label: z24.string().max(500).optional().describe("For 'slot.add'/'slot.replace': display label override."),
13766
- author: z24.string().max(200).optional().describe("Who is performing the action."),
13767
- commitMessage: z24.string().max(2e3).optional().describe("For 'version.commit': commit message."),
13768
- query: z24.string().max(500).optional().describe("For 'suggest': search query to narrow ingredient suggestions."),
13769
- audienceEntryId: z24.string().max(200).optional().describe("For 'create-audience-set': audience entry ID (required)."),
14211
+ mapEntryId: z26.string().max(200).optional().describe("Map entry ID. Required for get and all slot.*/version.*/suggest actions."),
14212
+ title: z26.string().max(500).optional().describe("For 'create': map title (required)."),
14213
+ templateId: z26.string().max(200).optional().default("lean-canvas").describe("For 'create': template slug."),
14214
+ description: z26.string().max(2e4).optional().describe("For 'create': description."),
14215
+ slotIds: z26.array(z26.string().max(200)).max(200).optional().describe("For 'create': slot IDs to initialize."),
14216
+ status: z26.string().max(200).optional().describe("For 'list': filter by status."),
14217
+ slotId: z26.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': slot ID (required). For 'suggest': specific slot (optional)."),
14218
+ ingredientEntryId: z26.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': ingredient entry ID to add/remove (required)."),
14219
+ newIngredientEntryId: z26.string().max(200).optional().describe("For 'slot.replace': new ingredient entry ID (required)."),
14220
+ label: z26.string().max(500).optional().describe("For 'slot.add'/'slot.replace': display label override."),
14221
+ author: z26.string().max(200).optional().describe("Who is performing the action."),
14222
+ commitMessage: z26.string().max(2e3).optional().describe("For 'version.commit': commit message."),
14223
+ query: z26.string().max(500).optional().describe("For 'suggest': search query to narrow ingredient suggestions."),
14224
+ audienceEntryId: z26.string().max(200).optional().describe("For 'create-audience-set': audience entry ID (required)."),
13770
14225
  // WP-513 review round 3 (P1): without these here, zod strips them before mapActionUnion ever sees them.
13771
- ownerTeamEntryId: z24.string().max(200).optional().describe("For 'create'/'create-audience-set': owning team (rung-2 workspaces)."),
13772
- ownerRoleEntryId: z24.string().max(200).optional().describe("For 'create'/'create-audience-set': owning role (rung-2 workspaces).")
14226
+ ownerTeamEntryId: z26.string().max(200).optional().describe("For 'create'/'create-audience-set': owning team (rung-2 workspaces)."),
14227
+ ownerRoleEntryId: z26.string().max(200).optional().describe("For 'create'/'create-audience-set': owning role (rung-2 workspaces).")
13773
14228
  });
13774
- var mapCreateVariant = mapSchema.omit({ action: true }).extend({ action: z24.literal("create") });
13775
- var mapGetVariant = z24.object({ action: z24.literal("get"), mapEntryId: z24.string().max(200) });
13776
- var mapListVariant = z24.object({ action: z24.literal("list"), templateId: z24.string().max(200).optional(), status: z24.string().max(200).optional() });
14229
+ var mapCreateVariant = mapSchema.omit({ action: true }).extend({ action: z26.literal("create") });
14230
+ var mapGetVariant = z26.object({ action: z26.literal("get"), mapEntryId: z26.string().max(200) });
14231
+ var mapListVariant = z26.object({ action: z26.literal("list"), templateId: z26.string().max(200).optional(), status: z26.string().max(200).optional() });
13777
14232
  var slotBase = mapSlotSchema.omit({ action: true });
13778
- var mapSlotAddVariant = slotBase.extend({ action: z24.literal("slot.add"), slotId: z24.string().max(200), ingredientEntryId: z24.string().max(200) });
13779
- var mapSlotRemoveVariant = slotBase.extend({ action: z24.literal("slot.remove"), slotId: z24.string().max(200), ingredientEntryId: z24.string().max(200) });
13780
- var mapSlotReplaceVariant = slotBase.extend({ action: z24.literal("slot.replace"), slotId: z24.string().max(200), ingredientEntryId: z24.string().max(200), newIngredientEntryId: z24.string().max(200) });
13781
- var mapSlotListVariant = slotBase.extend({ action: z24.literal("slot.list") });
14233
+ var mapSlotAddVariant = slotBase.extend({ action: z26.literal("slot.add"), slotId: z26.string().max(200), ingredientEntryId: z26.string().max(200) });
14234
+ var mapSlotRemoveVariant = slotBase.extend({ action: z26.literal("slot.remove"), slotId: z26.string().max(200), ingredientEntryId: z26.string().max(200) });
14235
+ var mapSlotReplaceVariant = slotBase.extend({ action: z26.literal("slot.replace"), slotId: z26.string().max(200), ingredientEntryId: z26.string().max(200), newIngredientEntryId: z26.string().max(200) });
14236
+ var mapSlotListVariant = slotBase.extend({ action: z26.literal("slot.list") });
13782
14237
  var versionBase2 = mapVersionSchema.omit({ action: true });
13783
- var mapVersionCommitVariant = versionBase2.extend({ action: z24.literal("version.commit") });
13784
- var mapVersionListVariant = versionBase2.extend({ action: z24.literal("version.list") });
13785
- var mapVersionHistoryVariant = versionBase2.extend({ action: z24.literal("version.history") });
13786
- var mapSuggestVariant = mapSuggestSchema.extend({ action: z24.literal("suggest") });
13787
- var mapCreateAudienceSetVariant = createAudienceMapSetSchema.extend({ action: z24.literal("create-audience-set") });
13788
- var mapActionUnion = z24.discriminatedUnion("action", [
14238
+ var mapVersionCommitVariant = versionBase2.extend({ action: z26.literal("version.commit") });
14239
+ var mapVersionListVariant = versionBase2.extend({ action: z26.literal("version.list") });
14240
+ var mapVersionHistoryVariant = versionBase2.extend({ action: z26.literal("version.history") });
14241
+ var mapSuggestVariant = mapSuggestSchema.extend({ action: z26.literal("suggest") });
14242
+ var mapCreateAudienceSetVariant = createAudienceMapSetSchema.extend({ action: z26.literal("create-audience-set") });
14243
+ var mapActionUnion = z26.discriminatedUnion("action", [
13789
14244
  mapCreateVariant,
13790
14245
  mapGetVariant,
13791
14246
  mapListVariant,
@@ -13849,10 +14304,10 @@ function registerMapTools(server) {
13849
14304
  }
13850
14305
 
13851
14306
  // src/tools/workspace.ts
13852
- import { z as z27 } from "zod/v3";
14307
+ import { z as z29 } from "zod/v3";
13853
14308
 
13854
14309
  // src/tools/health.ts
13855
- import { z as z25 } from "zod/v3";
14310
+ import { z as z27 } from "zod/v3";
13856
14311
  var CALL_CATEGORIES = {
13857
14312
  "chain.getEntry": "read",
13858
14313
  "chain.batchGetEntries": "read",
@@ -14197,65 +14652,65 @@ ${logLines.join("\n")}` }],
14197
14652
  };
14198
14653
  }
14199
14654
  var HEALTH_ACTIONS = ["check", "whoami", "status", "audit", "self-test"];
14200
- var healthSchema = z25.object({
14201
- action: z25.enum(HEALTH_ACTIONS).describe(
14655
+ var healthSchema = z27.object({
14656
+ action: z27.enum(HEALTH_ACTIONS).describe(
14202
14657
  "'check': connectivity and workspace stats. 'whoami': session identity. 'status': workspace readiness. 'audit': session audit log. 'self-test': validate all tool schemas."
14203
14658
  ),
14204
- limit: z25.number().min(1).max(50).default(20).optional().describe("For audit: how many recent calls to show (max 50)")
14659
+ limit: z27.number().min(1).max(50).default(20).optional().describe("For audit: how many recent calls to show (max 50)")
14205
14660
  });
14206
- var healthCheckOutputSchema = z25.object({
14207
- healthy: z25.boolean(),
14208
- collections: z25.number(),
14209
- entries: z25.number(),
14210
- latencyMs: z25.number(),
14211
- workspace: z25.string()
14661
+ var healthCheckOutputSchema = z27.object({
14662
+ healthy: z27.boolean(),
14663
+ collections: z27.number(),
14664
+ entries: z27.number(),
14665
+ latencyMs: z27.number(),
14666
+ workspace: z27.string()
14212
14667
  });
14213
- var organisationHealthSchema = z25.object({
14214
- reviewed: z25.number(),
14215
- agreements: z25.number(),
14216
- disagreements: z25.number(),
14217
- abstentions: z25.number(),
14218
- agreementRate: z25.number(),
14219
- flags: z25.array(z25.object({
14220
- collection: z25.string(),
14221
- count: z25.number(),
14222
- suggestedCollection: z25.string()
14668
+ var organisationHealthSchema = z27.object({
14669
+ reviewed: z27.number(),
14670
+ agreements: z27.number(),
14671
+ disagreements: z27.number(),
14672
+ abstentions: z27.number(),
14673
+ agreementRate: z27.number(),
14674
+ flags: z27.array(z27.object({
14675
+ collection: z27.string(),
14676
+ count: z27.number(),
14677
+ suggestedCollection: z27.string()
14223
14678
  }))
14224
14679
  });
14225
- var healthStatusOutputSchema = z25.object({
14226
- stage: z25.enum(["blank", "seeded", "grounded", "connected"]).optional().default("seeded"),
14227
- scoringVersion: z25.enum(["v1", "v2"]).optional().default("v1"),
14228
- readinessScore: z25.number(),
14229
- activeEntries: z25.number(),
14230
- totalRelations: z25.number(),
14231
- orphanedEntries: z25.number(),
14232
- gaps: z25.array(z25.object({ id: z25.string(), label: z25.string(), guidance: z25.string() })),
14680
+ var healthStatusOutputSchema = z27.object({
14681
+ stage: z27.enum(["blank", "seeded", "grounded", "connected"]).optional().default("seeded"),
14682
+ scoringVersion: z27.enum(["v1", "v2"]).optional().default("v1"),
14683
+ readinessScore: z27.number(),
14684
+ activeEntries: z27.number(),
14685
+ totalRelations: z27.number(),
14686
+ orphanedEntries: z27.number(),
14687
+ gaps: z27.array(z27.object({ id: z27.string(), label: z27.string(), guidance: z27.string() })),
14233
14688
  organisationHealth: organisationHealthSchema.optional()
14234
14689
  });
14235
- var healthAuditOutputSchema = z25.object({
14236
- totalCalls: z25.number(),
14237
- calls: z25.array(z25.object({
14238
- tool: z25.string(),
14239
- action: z25.string().optional(),
14240
- timestamp: z25.string(),
14241
- durationMs: z25.number().optional()
14690
+ var healthAuditOutputSchema = z27.object({
14691
+ totalCalls: z27.number(),
14692
+ calls: z27.array(z27.object({
14693
+ tool: z27.string(),
14694
+ action: z27.string().optional(),
14695
+ timestamp: z27.string(),
14696
+ durationMs: z27.number().optional()
14242
14697
  }))
14243
14698
  });
14244
- var healthWhoamiOutputSchema = z25.object({
14245
- workspaceId: z25.string(),
14246
- workspaceName: z25.string(),
14247
- scope: z25.string(),
14248
- sessionId: z25.union([z25.string(), z25.null()]),
14249
- oriented: z25.boolean()
14699
+ var healthWhoamiOutputSchema = z27.object({
14700
+ workspaceId: z27.string(),
14701
+ workspaceName: z27.string(),
14702
+ scope: z27.string(),
14703
+ sessionId: z27.union([z27.string(), z27.null()]),
14704
+ oriented: z27.boolean()
14250
14705
  });
14251
- var selfTestOutputSchema = z25.object({
14252
- passed: z25.number(),
14253
- failed: z25.number(),
14254
- total: z25.number(),
14255
- results: z25.array(z25.object({
14256
- tool: z25.string(),
14257
- valid: z25.boolean(),
14258
- error: z25.string().optional()
14706
+ var selfTestOutputSchema = z27.object({
14707
+ passed: z27.number(),
14708
+ failed: z27.number(),
14709
+ total: z27.number(),
14710
+ results: z27.array(z27.object({
14711
+ tool: z27.string(),
14712
+ valid: z27.boolean(),
14713
+ error: z27.string().optional()
14259
14714
  }))
14260
14715
  });
14261
14716
  function handleSelfTest(server) {
@@ -14306,9 +14761,9 @@ function handleSelfTest(server) {
14306
14761
  }
14307
14762
 
14308
14763
  // src/tools/usage.ts
14309
- import { z as z26 } from "zod/v3";
14310
- var usageSummarySchema = z26.object({
14311
- periodDays: z26.number().min(1).max(90).optional().describe("Number of days to look back (default 30, max 90)")
14764
+ import { z as z28 } from "zod/v3";
14765
+ var usageSummarySchema = z28.object({
14766
+ periodDays: z28.number().min(1).max(90).optional().describe("Number of days to look back (default 30, max 90)")
14312
14767
  });
14313
14768
  async function handleUsageSummary(periodDays) {
14314
14769
  const ws = await getWorkspaceContext();
@@ -14480,35 +14935,35 @@ var WORKSPACE_ACTIONS = [
14480
14935
  "proposals-respond",
14481
14936
  "proposals-count"
14482
14937
  ];
14483
- var workspaceSchema = z27.object({
14484
- action: z27.enum(WORKSPACE_ACTIONS).describe(
14938
+ var workspaceSchema = z29.object({
14939
+ action: z29.enum(WORKSPACE_ACTIONS).describe(
14485
14940
  "'check': connectivity and workspace stats (absorbs health action=check). 'whoami': session identity (absorbs health action=whoami). 'status': workspace readiness (absorbs health action=status). 'audit': session audit log (absorbs health action=audit). 'self-test': validate all tool schemas (absorbs health action=self-test). 'usage': LLM usage and cost summary (absorbs get-usage-summary). 'proposals-list': list open consent proposals (absorbs governance-proposals action=list). 'proposals-respond': approve/reject a consent proposal (absorbs governance-proposals action=respond). 'proposals-count': count open consent proposals (absorbs governance-proposals action=count)."
14486
14941
  ),
14487
- limit: z27.number().min(1).max(50).optional().describe("For 'audit': how many recent calls to show (max 50, default 20)."),
14488
- periodDays: z27.number().min(1).max(90).optional().describe("For 'usage': number of days to look back (default 30, max 90)."),
14489
- status: z27.enum(["open", "approved", "objected", "expired"]).optional().describe("For 'proposals-list': filter by status (default: open)."),
14490
- proposalId: z27.string().max(200).optional().describe("For 'proposals-respond': proposal ID."),
14491
- verdict: z27.enum(["approve", "reject"]).optional().describe("For 'proposals-respond': approve or reject."),
14492
- reason: z27.string().max(2e3).optional().describe("For 'proposals-respond': reason for the verdict (required when rejecting).")
14942
+ limit: z29.number().min(1).max(50).optional().describe("For 'audit': how many recent calls to show (max 50, default 20)."),
14943
+ periodDays: z29.number().min(1).max(90).optional().describe("For 'usage': number of days to look back (default 30, max 90)."),
14944
+ status: z29.enum(["open", "approved", "objected", "expired"]).optional().describe("For 'proposals-list': filter by status (default: open)."),
14945
+ proposalId: z29.string().max(200).optional().describe("For 'proposals-respond': proposal ID."),
14946
+ verdict: z29.enum(["approve", "reject"]).optional().describe("For 'proposals-respond': approve or reject."),
14947
+ reason: z29.string().max(2e3).optional().describe("For 'proposals-respond': reason for the verdict (required when rejecting).")
14493
14948
  });
14494
- var workspaceCheckVariant = z27.object({ action: z27.literal("check") });
14495
- var workspaceWhoamiVariant = z27.object({ action: z27.literal("whoami") });
14496
- var workspaceStatusVariant = z27.object({ action: z27.literal("status") });
14497
- var workspaceAuditVariant = z27.object({ action: z27.literal("audit"), limit: z27.number().min(1).max(50).optional().default(20) });
14498
- var workspaceSelfTestVariant = z27.object({ action: z27.literal("self-test") });
14499
- var workspaceUsageVariant = z27.object({ action: z27.literal("usage"), periodDays: z27.number().min(1).max(90).optional() });
14500
- var workspaceProposalsListVariant = z27.object({
14501
- action: z27.literal("proposals-list"),
14502
- status: z27.enum(["open", "approved", "objected", "expired"]).optional()
14949
+ var workspaceCheckVariant = z29.object({ action: z29.literal("check") });
14950
+ var workspaceWhoamiVariant = z29.object({ action: z29.literal("whoami") });
14951
+ var workspaceStatusVariant = z29.object({ action: z29.literal("status") });
14952
+ var workspaceAuditVariant = z29.object({ action: z29.literal("audit"), limit: z29.number().min(1).max(50).optional().default(20) });
14953
+ var workspaceSelfTestVariant = z29.object({ action: z29.literal("self-test") });
14954
+ var workspaceUsageVariant = z29.object({ action: z29.literal("usage"), periodDays: z29.number().min(1).max(90).optional() });
14955
+ var workspaceProposalsListVariant = z29.object({
14956
+ action: z29.literal("proposals-list"),
14957
+ status: z29.enum(["open", "approved", "objected", "expired"]).optional()
14503
14958
  });
14504
- var workspaceProposalsRespondVariant = z27.object({
14505
- action: z27.literal("proposals-respond"),
14506
- proposalId: z27.string().max(200),
14507
- verdict: z27.enum(["approve", "reject"]),
14508
- reason: z27.string().max(2e3).optional()
14959
+ var workspaceProposalsRespondVariant = z29.object({
14960
+ action: z29.literal("proposals-respond"),
14961
+ proposalId: z29.string().max(200),
14962
+ verdict: z29.enum(["approve", "reject"]),
14963
+ reason: z29.string().max(2e3).optional()
14509
14964
  });
14510
- var workspaceProposalsCountVariant = z27.object({ action: z27.literal("proposals-count") });
14511
- var workspaceActionUnion = z27.discriminatedUnion("action", [
14965
+ var workspaceProposalsCountVariant = z29.object({ action: z29.literal("proposals-count") });
14966
+ var workspaceActionUnion = z29.discriminatedUnion("action", [
14512
14967
  workspaceCheckVariant,
14513
14968
  workspaceWhoamiVariant,
14514
14969
  workspaceStatusVariant,
@@ -14564,7 +15019,7 @@ function registerWorkspaceTools(server) {
14564
15019
  }
14565
15020
 
14566
15021
  // src/tools/feedback.ts
14567
- import { z as z28 } from "zod/v3";
15022
+ import { z as z30 } from "zod/v3";
14568
15023
 
14569
15024
  // src/lib/productFeedbackConstants.ts
14570
15025
  var PRODUCT_FEEDBACK_CATEGORIES = ["bug", "friction", "idea", "praise", "other"];
@@ -14575,9 +15030,9 @@ var VENDOR_SETTABLE_STATUSES = PRODUCT_FEEDBACK_STATUSES.filter(
14575
15030
 
14576
15031
  // src/tools/feedback.ts
14577
15032
  var actions = ["submit", "list", "queue", "note", "group", "status"];
14578
- var category = z28.enum(PRODUCT_FEEDBACK_CATEGORIES);
14579
- var status = z28.enum(PRODUCT_FEEDBACK_STATUSES);
14580
- var vendorStatus = z28.enum(VENDOR_SETTABLE_STATUSES);
15033
+ var category = z30.enum(PRODUCT_FEEDBACK_CATEGORIES);
15034
+ var status = z30.enum(PRODUCT_FEEDBACK_STATUSES);
15035
+ var vendorStatus = z30.enum(VENDOR_SETTABLE_STATUSES);
14581
15036
  var GATEWAY_MAX_STRING_BYTES = 10240;
14582
15037
  var utf8Bytes = (value) => new TextEncoder().encode(value).length;
14583
15038
  var fitsGatewayBytes = (value) => utf8Bytes(value) <= GATEWAY_MAX_STRING_BYTES;
@@ -14586,32 +15041,32 @@ var byteLimitMessage = (field) => ({
14586
15041
  });
14587
15042
  var MESSAGE_DISPLAY_LIMIT = 1e3;
14588
15043
  var FULL_MESSAGE_MAX_LIMIT = 5;
14589
- var feedbackSchema = z28.object({
14590
- action: z28.enum(actions).describe("submit requires message; list returns your own workspace's feedback (all statuses); queue is the vendor triage queue (system admins only) and accepts filters; note requires feedbackId+note; group requires feedbackIds+groupId (null clears); status requires feedbackId+status."),
14591
- message: z28.string().max(1e4).optional().describe("Required for submit: the product feedback text (max 10,000 chars and 10,240 UTF-8 bytes)."),
15044
+ var feedbackSchema = z30.object({
15045
+ action: z30.enum(actions).describe("submit requires message; list returns your own workspace's feedback (all statuses); queue is the vendor triage queue (system admins only) and accepts filters; note requires feedbackId+note; group requires feedbackIds+groupId (null clears); status requires feedbackId+status."),
15046
+ message: z30.string().max(1e4).optional().describe("Required for submit: the product feedback text (max 10,000 chars and 10,240 UTF-8 bytes)."),
14592
15047
  category: category.optional().describe("Submit/queue category; submit defaults to other."),
14593
- command: z28.string().max(1e3).optional().describe("Optional submit command context; argument values are scrubbed server-side."),
14594
- route: z28.string().max(500).optional().describe("Optional submit route context."),
14595
- client: z28.string().max(100).optional().describe("Optional submit client label."),
14596
- feedbackId: z28.string().max(200).optional().describe("Required for note/status: target feedback ID."),
14597
- feedbackIds: z28.array(z28.string().max(200)).max(100).optional().describe("Required for group: 1\u2013100 target feedback IDs."),
14598
- note: z28.string().max(4e3).optional().describe("Required for note: replacement triage note (max 10,240 UTF-8 bytes)."),
15048
+ command: z30.string().max(1e3).optional().describe("Optional submit command context; argument values are scrubbed server-side."),
15049
+ route: z30.string().max(500).optional().describe("Optional submit route context."),
15050
+ client: z30.string().max(100).optional().describe("Optional submit client label."),
15051
+ feedbackId: z30.string().max(200).optional().describe("Required for note/status: target feedback ID."),
15052
+ feedbackIds: z30.array(z30.string().max(200)).max(100).optional().describe("Required for group: 1\u2013100 target feedback IDs."),
15053
+ note: z30.string().max(4e3).optional().describe("Required for note: replacement triage note (max 10,240 UTF-8 bytes)."),
14599
15054
  status: status.optional().describe("list/queue filter (any status, including 'screening'); the status action's required target value excludes 'screening' (system-only)."),
14600
- groupId: z28.string().min(1).max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
14601
- workspaceId: z28.string().max(200).optional().describe("Queue-only filter (vendor cross-workspace triage); omitted means all workspaces. Has no effect on list \u2014 your own workspace is always injected server-side."),
14602
- since: z28.number().optional().describe("Queue-only lower createdAt window bound (inclusive) in epoch milliseconds."),
14603
- before: z28.number().optional().describe("Queue-only upper createdAt window bound (exclusive) in epoch milliseconds. A time-window FILTER, not the pager \u2014 use cursor to page."),
14604
- limit: z28.number().int().min(1).max(100).optional().describe("list/queue row limit, default 50, maximum 100."),
14605
- cursor: z28.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list/queue response (continueCursor); omit for the first page."),
14606
- full: z28.boolean().optional().describe(`list/queue only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
15055
+ groupId: z30.string().min(1).max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
15056
+ workspaceId: z30.string().max(200).optional().describe("Queue-only filter (vendor cross-workspace triage); omitted means all workspaces. Has no effect on list \u2014 your own workspace is always injected server-side."),
15057
+ since: z30.number().optional().describe("Queue-only lower createdAt window bound (inclusive) in epoch milliseconds."),
15058
+ before: z30.number().optional().describe("Queue-only upper createdAt window bound (exclusive) in epoch milliseconds. A time-window FILTER, not the pager \u2014 use cursor to page."),
15059
+ limit: z30.number().int().min(1).max(100).optional().describe("list/queue row limit, default 50, maximum 100."),
15060
+ cursor: z30.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list/queue response (continueCursor); omit for the first page."),
15061
+ full: z30.boolean().optional().describe(`list/queue only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
14607
15062
  });
14608
- var union = z28.discriminatedUnion("action", [
14609
- z28.object({ action: z28.literal("submit"), message: z28.string().min(1).max(1e4).refine(fitsGatewayBytes, byteLimitMessage("message")), category: category.optional(), command: z28.string().max(1e3).optional(), route: z28.string().max(500).optional(), client: z28.string().max(100).optional() }),
14610
- z28.object({ action: z28.literal("list"), status: status.optional(), limit: z28.number().int().min(1).max(100).optional(), cursor: z28.string().max(2e3).optional(), full: z28.boolean().optional() }),
14611
- z28.object({ action: z28.literal("queue"), status: status.optional(), category: category.optional(), groupId: z28.string().min(1).max(200).optional(), workspaceId: z28.string().max(200).optional(), since: z28.number().optional(), before: z28.number().optional(), limit: z28.number().int().min(1).max(100).optional(), cursor: z28.string().max(2e3).optional(), full: z28.boolean().optional() }),
14612
- z28.object({ action: z28.literal("note"), feedbackId: z28.string().min(1).max(200), note: z28.string().max(4e3).refine(fitsGatewayBytes, byteLimitMessage("note")) }),
14613
- z28.object({ action: z28.literal("group"), feedbackIds: z28.array(z28.string().min(1).max(200)).min(1).max(100), groupId: z28.string().min(1).max(200).nullable() }),
14614
- z28.object({ action: z28.literal("status"), feedbackId: z28.string().min(1).max(200), status: vendorStatus })
15063
+ var union = z30.discriminatedUnion("action", [
15064
+ z30.object({ action: z30.literal("submit"), message: z30.string().min(1).max(1e4).refine(fitsGatewayBytes, byteLimitMessage("message")), category: category.optional(), command: z30.string().max(1e3).optional(), route: z30.string().max(500).optional(), client: z30.string().max(100).optional() }),
15065
+ z30.object({ action: z30.literal("list"), status: status.optional(), limit: z30.number().int().min(1).max(100).optional(), cursor: z30.string().max(2e3).optional(), full: z30.boolean().optional() }),
15066
+ z30.object({ action: z30.literal("queue"), status: status.optional(), category: category.optional(), groupId: z30.string().min(1).max(200).optional(), workspaceId: z30.string().max(200).optional(), since: z30.number().optional(), before: z30.number().optional(), limit: z30.number().int().min(1).max(100).optional(), cursor: z30.string().max(2e3).optional(), full: z30.boolean().optional() }),
15067
+ z30.object({ action: z30.literal("note"), feedbackId: z30.string().min(1).max(200), note: z30.string().max(4e3).refine(fitsGatewayBytes, byteLimitMessage("note")) }),
15068
+ z30.object({ action: z30.literal("group"), feedbackIds: z30.array(z30.string().min(1).max(200)).min(1).max(100), groupId: z30.string().min(1).max(200).nullable() }),
15069
+ z30.object({ action: z30.literal("status"), feedbackId: z30.string().min(1).max(200), status: vendorStatus })
14615
15070
  ]);
14616
15071
  var specs = {
14617
15072
  submit: { params: ["message", "category", "command", "route", "client"], description: "message is required; category defaults to other." },
@@ -14738,34 +15193,34 @@ function registerFeedbackTool(server) {
14738
15193
  }
14739
15194
 
14740
15195
  // src/tools/shape.ts
14741
- import { z as z29 } from "zod/v3";
15196
+ import { z as z31 } from "zod/v3";
14742
15197
  var SHAPE_ACTIONS = ["list", "show", "agree", "dismiss"];
14743
15198
  var LIST_DISPOSITIONS = ["pending", "agreed", "dismissed", "expired"];
14744
15199
  var LIST_OUTCOMES = ["not_candidate", "atomic", "compound", "unavailable"];
14745
- var shapeSchema = z29.object({
14746
- action: z29.enum(SHAPE_ACTIONS).describe(
15200
+ var shapeSchema = z31.object({
15201
+ action: z31.enum(SHAPE_ACTIONS).describe(
14747
15202
  "'list': list shape advisories for this workspace, latest per subject. 'show': show one shape advisory by id. 'agree': agree with a compound advisory's split verdict. 'dismiss': dismiss a compound advisory's split verdict."
14748
15203
  ),
14749
- disposition: z29.enum(LIST_DISPOSITIONS).optional().describe(
15204
+ disposition: z31.enum(LIST_DISPOSITIONS).optional().describe(
14750
15205
  "For 'list': filter by disposition. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
14751
15206
  ),
14752
- outcome: z29.enum(LIST_OUTCOMES).optional().describe(
15207
+ outcome: z31.enum(LIST_OUTCOMES).optional().describe(
14753
15208
  "For 'list': filter by outcome. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
14754
15209
  ),
14755
- limit: z29.number().min(1).max(200).optional().describe("For 'list': max rows (default 50, max 200)."),
14756
- rowId: z29.string().max(200).optional().describe("For 'show'/'agree'/'dismiss': the advisory row id."),
14757
- reason: z29.string().max(1e3).optional().describe("For 'agree'/'dismiss': optional reason (capped at 1000 chars).")
15210
+ limit: z31.number().min(1).max(200).optional().describe("For 'list': max rows (default 50, max 200)."),
15211
+ rowId: z31.string().max(200).optional().describe("For 'show'/'agree'/'dismiss': the advisory row id."),
15212
+ reason: z31.string().max(1e3).optional().describe("For 'agree'/'dismiss': optional reason (capped at 1000 chars).")
14758
15213
  });
14759
- var shapeListVariant = z29.object({
14760
- action: z29.literal("list"),
14761
- disposition: z29.enum(LIST_DISPOSITIONS).optional(),
14762
- outcome: z29.enum(LIST_OUTCOMES).optional(),
14763
- limit: z29.number().min(1).max(200).optional()
15214
+ var shapeListVariant = z31.object({
15215
+ action: z31.literal("list"),
15216
+ disposition: z31.enum(LIST_DISPOSITIONS).optional(),
15217
+ outcome: z31.enum(LIST_OUTCOMES).optional(),
15218
+ limit: z31.number().min(1).max(200).optional()
14764
15219
  });
14765
- var shapeShowVariant = z29.object({ action: z29.literal("show"), rowId: z29.string().max(200) });
14766
- var shapeAgreeVariant = z29.object({ action: z29.literal("agree"), rowId: z29.string().max(200), reason: z29.string().max(1e3).optional() });
14767
- var shapeDismissVariant = z29.object({ action: z29.literal("dismiss"), rowId: z29.string().max(200), reason: z29.string().max(1e3).optional() });
14768
- var shapeActionUnion = z29.discriminatedUnion("action", [
15220
+ var shapeShowVariant = z31.object({ action: z31.literal("show"), rowId: z31.string().max(200) });
15221
+ var shapeAgreeVariant = z31.object({ action: z31.literal("agree"), rowId: z31.string().max(200), reason: z31.string().max(1e3).optional() });
15222
+ var shapeDismissVariant = z31.object({ action: z31.literal("dismiss"), rowId: z31.string().max(200), reason: z31.string().max(1e3).optional() });
15223
+ var shapeActionUnion = z31.discriminatedUnion("action", [
14769
15224
  shapeListVariant,
14770
15225
  shapeShowVariant,
14771
15226
  shapeAgreeVariant,
@@ -15432,12 +15887,12 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
15432
15887
  }
15433
15888
 
15434
15889
  // src/prompts/index.ts
15435
- import { z as z30 } from "zod/v3";
15890
+ import { z as z32 } from "zod/v3";
15436
15891
  function registerPrompts(server) {
15437
15892
  server.prompt(
15438
15893
  "review-against-rules",
15439
15894
  "Review code or a design decision against all business rules for a given domain. Fetches the rules and asks you to do a structured compliance review.",
15440
- { domain: z30.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
15895
+ { domain: z32.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
15441
15896
  async ({ domain }) => {
15442
15897
  const entries = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
15443
15898
  const rules = entries.filter((e) => e.data?.domain === domain);
@@ -15490,7 +15945,7 @@ Provide a structured review with a compliance status for each rule (COMPLIANT /
15490
15945
  server.prompt(
15491
15946
  "name-check",
15492
15947
  "Check variable names, field names, or API names against the glossary for terminology alignment. Flags drift from canonical terms.",
15493
- { names: z30.string().describe("Comma-separated list of names to check (e.g. 'vendor_id, compliance_level, formulator_type')") },
15948
+ { names: z32.string().describe("Comma-separated list of names to check (e.g. 'vendor_id, compliance_level, formulator_type')") },
15494
15949
  async ({ names }) => {
15495
15950
  const terms = await kernelQuery("chain.listEntries", { collectionSlug: "glossary" });
15496
15951
  const glossaryContext = terms.map(
@@ -15526,7 +15981,7 @@ Format as a table: Name | Status | Canonical Form | Action Needed`
15526
15981
  server.prompt(
15527
15982
  "draft-decision-record",
15528
15983
  "Draft a structured decision record from a description of what was decided. Includes context from recent decisions and relevant rules.",
15529
- { context: z30.string().describe("Description of the decision (e.g. 'We decided to use MRSL v3.1 as the conformance baseline because...')") },
15984
+ { context: z32.string().describe("Description of the decision (e.g. 'We decided to use MRSL v3.1 as the conformance baseline because...')") },
15530
15985
  async ({ context }) => {
15531
15986
  const recentDecisions = await kernelQuery("chain.listEntries", { collectionSlug: "decisions" });
15532
15987
  const sorted = [...recentDecisions].sort((a, b) => (b.data?.date ?? "") > (a.data?.date ?? "") ? 1 : -1).slice(0, 5);
@@ -15564,8 +16019,8 @@ After drafting, I can log it using the capture tool with collection "decisions".
15564
16019
  "draft-rule-from-context",
15565
16020
  "Draft a new business rule from an observation or discovery made while coding. Fetches existing rules for the domain to ensure consistency.",
15566
16021
  {
15567
- observation: z30.string().describe("What you observed or discovered (e.g. 'Suppliers can have multiple org types in Gateway')"),
15568
- domain: z30.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
16022
+ observation: z32.string().describe("What you observed or discovered (e.g. 'Suppliers can have multiple org types in Gateway')"),
16023
+ domain: z32.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
15569
16024
  },
15570
16025
  async ({ observation, domain }) => {
15571
16026
  const allRules = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
@@ -15841,4 +16296,4 @@ export {
15841
16296
  createProductBrainServer,
15842
16297
  initFeatureFlags
15843
16298
  };
15844
- //# sourceMappingURL=chunk-252CQV5P.js.map
16299
+ //# sourceMappingURL=chunk-KTRECBYJ.js.map