@fenglimg/fabric-shared 2.2.0-rc.4 → 2.2.0-rc.9
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.
- package/dist/chunk-2GLIAZ5M.js +251 -0
- package/dist/{chunk-355LUDLW.js → chunk-5AKCRBKJ.js} +474 -418
- package/dist/{chunk-KUYCTRFI.js → chunk-AQMDXC6J.js} +400 -532
- package/dist/chunk-BDJQIOQO.js +206 -0
- package/dist/{chunk-4N6DMOOW.js → chunk-C7WZPYZE.js} +2 -1
- package/dist/{chunk-VDSM73PK.js → chunk-O6GIHZF3.js} +6 -0
- package/dist/errors/index.d.ts +6 -1
- package/dist/errors/index.js +5 -3
- package/dist/i18n/index.d.ts +29 -23
- package/dist/i18n/index.js +7 -3
- package/dist/{index-BqA89S9q.d.ts → index-D_gT1CEA.d.ts} +83 -34
- package/dist/index.d.ts +488 -579
- package/dist/index.js +1265 -1068
- package/dist/node/atomic-write.js +1 -1
- package/dist/node/mcp-payload-guard.js +1 -1
- package/dist/node.d.ts +10 -1
- package/dist/node.js +32 -1
- package/dist/schemas/api-contracts.d.ts +163 -113
- package/dist/schemas/api-contracts.js +3 -3
- package/dist/templates/bootstrap-canonical.d.ts +50 -23
- package/dist/templates/bootstrap-canonical.js +12 -9
- package/dist/types/index.d.ts +1 -1
- package/dist/types-qg4xXVuT.d.ts +8 -0
- package/package.json +3 -2
- package/dist/chunk-AFT7DB4P.js +0 -103
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/schemas/api-contracts.ts
|
|
2
|
-
import { z as
|
|
2
|
+
import { z as z3 } from "zod";
|
|
3
3
|
|
|
4
4
|
// src/onboard-slots.ts
|
|
5
5
|
import { z } from "zod";
|
|
@@ -13,63 +13,91 @@ var ONBOARD_SLOT_NAMES = [
|
|
|
13
13
|
var onboardSlotSchema = z.enum(ONBOARD_SLOT_NAMES);
|
|
14
14
|
var ONBOARD_SLOT_TOTAL = ONBOARD_SLOT_NAMES.length;
|
|
15
15
|
|
|
16
|
+
// src/schemas/scope.ts
|
|
17
|
+
import { z as z2 } from "zod";
|
|
18
|
+
var PERSONAL_SCOPE = "personal";
|
|
19
|
+
var KNOWN_SCOPE_PREFIXES = ["personal", "team", "project", "org"];
|
|
20
|
+
var SCOPE_COORDINATE_PATTERN = /^[a-z0-9_-]+(:[a-z0-9_-]+)*$/u;
|
|
21
|
+
var scopeCoordinateSchema = z2.string().min(1).regex(
|
|
22
|
+
SCOPE_COORDINATE_PATTERN,
|
|
23
|
+
"scope coordinate must be ':'-joined lowercase [a-z0-9_-] segments"
|
|
24
|
+
);
|
|
25
|
+
function scopeRoot(coordinate) {
|
|
26
|
+
const colon = coordinate.indexOf(":");
|
|
27
|
+
return colon === -1 ? coordinate : coordinate.slice(0, colon);
|
|
28
|
+
}
|
|
29
|
+
function isPersonalScope(coordinate) {
|
|
30
|
+
return scopeRoot(coordinate) === PERSONAL_SCOPE;
|
|
31
|
+
}
|
|
32
|
+
var entryScopeMetadataSchema = z2.object({
|
|
33
|
+
semantic_scope: scopeCoordinateSchema,
|
|
34
|
+
// Store alias or UUID. Validated as a non-empty string here; the resolver
|
|
35
|
+
// (P0.6) maps alias→UUID and verifies the store is in the read-set.
|
|
36
|
+
visibility_store: z2.string().min(1)
|
|
37
|
+
}).strict();
|
|
38
|
+
|
|
16
39
|
// src/schemas/api-contracts.ts
|
|
17
|
-
var structuredWarningSchema =
|
|
18
|
-
code:
|
|
19
|
-
file:
|
|
20
|
-
line:
|
|
21
|
-
|
|
40
|
+
var structuredWarningSchema = z3.object({
|
|
41
|
+
code: z3.string(),
|
|
42
|
+
file: z3.string(),
|
|
43
|
+
line: z3.number().optional(),
|
|
44
|
+
message: z3.string().optional(),
|
|
45
|
+
action_hint: z3.string()
|
|
22
46
|
});
|
|
23
|
-
var _knowledgeTypeEnum =
|
|
24
|
-
var _maturityEnum =
|
|
25
|
-
var _layerEnum =
|
|
26
|
-
var _ruleDescriptionSchema =
|
|
27
|
-
summary:
|
|
28
|
-
intent_clues:
|
|
29
|
-
tech_stack:
|
|
30
|
-
impact:
|
|
31
|
-
must_read_if:
|
|
32
|
-
entities:
|
|
47
|
+
var _knowledgeTypeEnum = z3.enum(["models", "decisions", "guidelines", "pitfalls", "processes"]);
|
|
48
|
+
var _maturityEnum = z3.enum(["draft", "verified", "proven"]);
|
|
49
|
+
var _layerEnum = z3.enum(["personal", "team"]);
|
|
50
|
+
var _ruleDescriptionSchema = z3.object({
|
|
51
|
+
summary: z3.string(),
|
|
52
|
+
intent_clues: z3.array(z3.string()),
|
|
53
|
+
tech_stack: z3.array(z3.string()),
|
|
54
|
+
impact: z3.array(z3.string()),
|
|
55
|
+
must_read_if: z3.string(),
|
|
56
|
+
entities: z3.array(z3.string()).optional(),
|
|
33
57
|
// v2.0: optional knowledge-entry fields. Absent for v1.x rules; present for
|
|
34
58
|
// entries that declare frontmatter `id/type/maturity/layer`.
|
|
35
|
-
id:
|
|
59
|
+
id: z3.string().optional(),
|
|
36
60
|
knowledge_type: _knowledgeTypeEnum.optional(),
|
|
37
61
|
maturity: _maturityEnum.optional(),
|
|
38
62
|
knowledge_layer: _layerEnum.optional(),
|
|
39
|
-
layer_reason:
|
|
40
|
-
created_at:
|
|
63
|
+
layer_reason: z3.string().optional(),
|
|
64
|
+
created_at: z3.string().optional(),
|
|
41
65
|
// v2.0.0-rc.38 UX-3 (D-MCP fold ③): these three were previously carried ONLY
|
|
42
66
|
// as top-level mirrors on the index item. With the mirrors removed,
|
|
43
67
|
// `description` becomes their canonical (and only) home, so the schema must
|
|
44
68
|
// validate them here. Optional + default-safe (tags/[]/broad) so legacy
|
|
45
69
|
// entries without frontmatter still parse.
|
|
46
|
-
tags:
|
|
47
|
-
relevance_scope:
|
|
48
|
-
relevance_paths:
|
|
70
|
+
tags: z3.array(z3.string()).optional(),
|
|
71
|
+
relevance_scope: z3.enum(["narrow", "broad"]).optional(),
|
|
72
|
+
relevance_paths: z3.array(z3.string()).optional(),
|
|
49
73
|
// v2.2 H2-related (W1-T7) — W1-REVIEW codex HIGH-2: the MCP-facing description
|
|
50
74
|
// schema must also carry `related`, else zod strips the graph edges on output
|
|
51
75
|
// validation and they never reach the client (MC1 include_related / fabric-
|
|
52
76
|
// connect would see nothing). Mirrors the agents-meta ruleDescriptionSchema.
|
|
53
|
-
related:
|
|
77
|
+
related: z3.array(z3.string()).optional()
|
|
54
78
|
});
|
|
55
|
-
var _descriptionIndexItemSchema =
|
|
56
|
-
stable_id:
|
|
57
|
-
description: _ruleDescriptionSchema
|
|
79
|
+
var _descriptionIndexItemSchema = z3.object({
|
|
80
|
+
stable_id: z3.string(),
|
|
81
|
+
description: _ruleDescriptionSchema,
|
|
82
|
+
// recall dedupe marker: true when this candidate is ALSO injected in full at
|
|
83
|
+
// SessionStart ("ALWAYS-ACTIVE RULES" = broad model/guideline). MUST be
|
|
84
|
+
// declared here or zod .strip() drops it at the MCP boundary (KT-PIT-0005),
|
|
85
|
+
// silently breaking the marker even though recall() sets it. Only ever true.
|
|
86
|
+
always_active: z3.boolean().optional()
|
|
58
87
|
});
|
|
59
|
-
var _requirementProfileSchema =
|
|
60
|
-
target_path:
|
|
61
|
-
known_tech:
|
|
62
|
-
|
|
63
|
-
detected_entities: z2.array(z2.string())
|
|
88
|
+
var _requirementProfileSchema = z3.object({
|
|
89
|
+
target_path: z3.string(),
|
|
90
|
+
known_tech: z3.array(z3.string()),
|
|
91
|
+
detected_entities: z3.array(z3.string())
|
|
64
92
|
});
|
|
65
|
-
var planContextInputSchema =
|
|
66
|
-
paths:
|
|
67
|
-
intent:
|
|
68
|
-
known_tech:
|
|
69
|
-
detected_entities:
|
|
70
|
-
client_hash:
|
|
71
|
-
correlation_id:
|
|
72
|
-
session_id:
|
|
93
|
+
var planContextInputSchema = z3.object({
|
|
94
|
+
paths: z3.array(z3.string()).min(1).describe("Candidate file paths to build neutral rule selection context for"),
|
|
95
|
+
intent: z3.string().optional().describe("User-stated requirement or implementation intent; used only to build a neutral requirement profile"),
|
|
96
|
+
known_tech: z3.array(z3.string()).optional().describe("Known technologies involved in the requirement profile"),
|
|
97
|
+
detected_entities: z3.record(z3.array(z3.string())).optional().describe("Optional path-keyed detected entities for the requirement profile"),
|
|
98
|
+
client_hash: z3.string().optional().describe("Revision hash from a prior fab_plan_context response; enables stale detection"),
|
|
99
|
+
correlation_id: z3.string().optional().describe("Optional caller-provided correlation id for Event Ledger records"),
|
|
100
|
+
session_id: z3.string().optional().describe(
|
|
73
101
|
"Recommended: pass the current client session id (Claude Code: $session_id; Codex: corresponding identifier) \u2014 enables cross-session debt tracking in fabric doctor and accurate archive-hint cross-session count. Falls back gracefully if omitted."
|
|
74
102
|
),
|
|
75
103
|
// v2.0-rc.5 A3 (TASK-007): `include_deprecated` removed — it was a no-op
|
|
@@ -78,55 +106,58 @@ var planContextInputSchema = z2.object({
|
|
|
78
106
|
// v2/rc.2 (Q6): client-supplied layer scope. When omitted, the server
|
|
79
107
|
// falls back to fabric-config.default_layer_filter (TASK-002) so a single
|
|
80
108
|
// workspace policy controls the default. Explicit values override.
|
|
81
|
-
layer_filter:
|
|
109
|
+
layer_filter: z3.enum(["team", "personal", "both"]).optional().describe(
|
|
82
110
|
"Restrict description_index to the named layer. Default: fabric-config.default_layer_filter (TASK-002)."
|
|
83
111
|
),
|
|
84
112
|
// v2.0-rc.5 C3 (TASK-012): explicit path context for `narrow` relevance
|
|
85
113
|
// filtering. When omitted, the server falls back to `paths` so existing
|
|
86
114
|
// callers see narrowing against the requested paths. When the resolved
|
|
87
115
|
// list is empty, the narrow filter fails open (every narrow entry passes).
|
|
88
|
-
target_paths:
|
|
116
|
+
target_paths: z3.array(z3.string()).optional().describe(
|
|
89
117
|
"Path context for narrow-scope relevance filtering. Defaults to `paths`; empty = no filter."
|
|
90
118
|
)
|
|
91
119
|
});
|
|
92
|
-
var _preflightDiagnosticSchema =
|
|
120
|
+
var _preflightDiagnosticSchema = z3.object({
|
|
93
121
|
// v2.0.0-rc.38 UX-2: `empty_shell_suppressed` surfaces draft entries whose
|
|
94
122
|
// description carries no selection signal (summary === stable_id + empty
|
|
95
123
|
// intent_clues/tech_stack/impact). They are filtered out of `candidates` to
|
|
96
124
|
// cut noise; this diagnostic names them so `fabric doctor` /
|
|
97
125
|
// --enrich-descriptions can prompt enrichment.
|
|
98
|
-
code:
|
|
99
|
-
severity:
|
|
100
|
-
message:
|
|
101
|
-
stable_ids:
|
|
102
|
-
path:
|
|
126
|
+
code: z3.enum(["missing_description", "empty_shell_suppressed"]),
|
|
127
|
+
severity: z3.literal("warn"),
|
|
128
|
+
message: z3.string(),
|
|
129
|
+
stable_ids: z3.array(z3.string()).optional(),
|
|
130
|
+
path: z3.string().optional()
|
|
103
131
|
});
|
|
104
|
-
var planContextOutputSchema =
|
|
105
|
-
revision_hash:
|
|
106
|
-
stale:
|
|
107
|
-
selection_token:
|
|
108
|
-
entries:
|
|
109
|
-
|
|
110
|
-
path:
|
|
132
|
+
var planContextOutputSchema = z3.object({
|
|
133
|
+
revision_hash: z3.string(),
|
|
134
|
+
stale: z3.boolean(),
|
|
135
|
+
selection_token: z3.string(),
|
|
136
|
+
entries: z3.array(
|
|
137
|
+
z3.object({
|
|
138
|
+
path: z3.string(),
|
|
111
139
|
requirement_profile: _requirementProfileSchema
|
|
112
140
|
})
|
|
113
141
|
),
|
|
114
|
-
|
|
142
|
+
// v2.2 payload de-dup: single top-level echo of the caller's `intent` (was
|
|
143
|
+
// duplicated into every entry's requirement_profile). Omitted when no intent.
|
|
144
|
+
intent: z3.string().optional(),
|
|
145
|
+
candidates: z3.array(_descriptionIndexItemSchema),
|
|
115
146
|
// v2.2 A-INFRA-3 (W1-T3-TOPK) / MC4-payload-budget (W1-T4): number of
|
|
116
147
|
// lower-ranked candidates dropped by the unified truncation chain (top_k cap
|
|
117
148
|
// + payload-budget trim). Present and > 0 ONLY when truncation fired, so the
|
|
118
149
|
// steady-state wire shape is unchanged. Lets the LLM know the returned set is
|
|
119
150
|
// not exhaustive ("N more exist; narrow your intent").
|
|
120
|
-
omitted_candidate_count:
|
|
121
|
-
preflight_diagnostics:
|
|
122
|
-
warnings:
|
|
151
|
+
omitted_candidate_count: z3.number().int().nonnegative().optional(),
|
|
152
|
+
preflight_diagnostics: z3.array(_preflightDiagnosticSchema),
|
|
153
|
+
warnings: z3.array(structuredWarningSchema).optional(),
|
|
123
154
|
// v2.0.0-rc.22 Scope D T-D2: optional auto-heal banner fields. Surfaced
|
|
124
155
|
// ONLY when the loadActiveMetaOrStale call detected drift and rebuilt the
|
|
125
156
|
// meta in-place. Downstream CLI / hint renderers use this pair to render a
|
|
126
157
|
// "knowledge meta auto-healed (was <prev>, now <curr>)" notice without
|
|
127
158
|
// having to query the event ledger.
|
|
128
|
-
auto_healed:
|
|
129
|
-
previous_revision_hash:
|
|
159
|
+
auto_healed: z3.boolean().optional(),
|
|
160
|
+
previous_revision_hash: z3.string().optional(),
|
|
130
161
|
// v2.0.0-rc.37 NEW-24: stale-id redirect map. Populated when one or more
|
|
131
162
|
// recent fab_review modify-layer flips reassigned a canonical stable_id
|
|
132
163
|
// and the NEW id is in this response's description_index. Callers that
|
|
@@ -134,13 +165,13 @@ var planContextOutputSchema = z2.object({
|
|
|
134
165
|
// the new id before issuing fab_get_knowledge_sections / fab_recall. Empty
|
|
135
166
|
// (field omitted) when no actionable redirects exist for the surfaced
|
|
136
167
|
// candidate set. See packages/server/src/services/id-redirect.ts.
|
|
137
|
-
redirects:
|
|
168
|
+
redirects: z3.record(z3.string()).optional(),
|
|
138
169
|
// lifecycle-refactor W3-T2 (§7 图谱消费): related-expansion provenance map
|
|
139
170
|
// (appended id → surfaced source id). Present only when `include_related` was
|
|
140
171
|
// requested AND at least one in-corpus one-hop neighbour was appended. Omitted
|
|
141
172
|
// on the graph-empty / steady-state path. Additive — declare it here or zod
|
|
142
173
|
// strips it on output validation.
|
|
143
|
-
related_appended:
|
|
174
|
+
related_appended: z3.record(z3.string()).optional()
|
|
144
175
|
});
|
|
145
176
|
var planContextAnnotations = {
|
|
146
177
|
readOnlyHint: true,
|
|
@@ -149,65 +180,69 @@ var planContextAnnotations = {
|
|
|
149
180
|
openWorldHint: false,
|
|
150
181
|
title: "Plan rule context"
|
|
151
182
|
};
|
|
152
|
-
var planContextHintNarrowEntrySchema =
|
|
153
|
-
id:
|
|
154
|
-
type:
|
|
155
|
-
maturity:
|
|
156
|
-
summary:
|
|
183
|
+
var planContextHintNarrowEntrySchema = z3.object({
|
|
184
|
+
id: z3.string(),
|
|
185
|
+
type: z3.string(),
|
|
186
|
+
maturity: z3.string(),
|
|
187
|
+
summary: z3.string(),
|
|
188
|
+
// W2-2 (KT-DEC-0027): the entry's must_read_if trigger hook, forwarded for the
|
|
189
|
+
// SessionStart REFERENCE rendering (decision/pitfall/process → title + hook).
|
|
190
|
+
// Optional — omitted when the frontmatter declares none.
|
|
191
|
+
must_read_if: z3.string().optional()
|
|
157
192
|
});
|
|
158
|
-
var planContextHintOutputSchema =
|
|
159
|
-
version:
|
|
160
|
-
revision_hash:
|
|
161
|
-
target_paths:
|
|
162
|
-
narrow:
|
|
163
|
-
broad_count:
|
|
193
|
+
var planContextHintOutputSchema = z3.object({
|
|
194
|
+
version: z3.literal(1),
|
|
195
|
+
revision_hash: z3.string(),
|
|
196
|
+
target_paths: z3.array(z3.string()),
|
|
197
|
+
narrow: z3.array(planContextHintNarrowEntrySchema),
|
|
198
|
+
broad_count: z3.number().int().nonnegative()
|
|
164
199
|
});
|
|
165
|
-
var knowledgeSectionsInputSchema =
|
|
166
|
-
selection_token:
|
|
167
|
-
ai_selected_stable_ids:
|
|
200
|
+
var knowledgeSectionsInputSchema = z3.object({
|
|
201
|
+
selection_token: z3.string().min(1).describe("Selection token returned by fab_plan_context"),
|
|
202
|
+
ai_selected_stable_ids: z3.array(z3.string()).describe(
|
|
168
203
|
"Stable ids picked from fab_plan_context candidates[].stable_id; choose 1..N to fetch bodies for"
|
|
169
204
|
),
|
|
170
|
-
ai_selection_reasons:
|
|
205
|
+
ai_selection_reasons: z3.record(z3.string().min(1)).optional().default({}).describe(
|
|
171
206
|
"Optional reason for each AI-selected L1 stable_id (audit telemetry). Omit to fetch bodies without annotating \u2014 server defaults to {} rather than rejecting the documented two-step call."
|
|
172
207
|
),
|
|
173
|
-
correlation_id:
|
|
174
|
-
session_id:
|
|
208
|
+
correlation_id: z3.string().optional().describe("Optional caller-provided correlation id for Event Ledger records"),
|
|
209
|
+
session_id: z3.string().optional().describe("Optional caller-provided session id for Event Ledger records"),
|
|
175
210
|
// v2.0 rc.5 TASK-014 (C5): optional client identity hash propagated into
|
|
176
211
|
// knowledge_consumed events. Falls back to empty string when unset — full
|
|
177
212
|
// client-identity propagation deferred to rc.6.
|
|
178
|
-
client_hash:
|
|
213
|
+
client_hash: z3.string().optional().describe("Optional caller-provided client hash propagated into knowledge_consumed events")
|
|
179
214
|
});
|
|
180
|
-
var knowledgeSectionsOutputSchema =
|
|
181
|
-
revision_hash:
|
|
215
|
+
var knowledgeSectionsOutputSchema = z3.object({
|
|
216
|
+
revision_hash: z3.string(),
|
|
182
217
|
// v2.0.0-rc.38 UX-13 (D-MCP step-2 audit): the deprecated `precedence`
|
|
183
218
|
// L2/L1/L0 tuple (flagged "removed in rc.24" but still emitted) is gone — it
|
|
184
219
|
// was a constant 3-string field on every response read by no production
|
|
185
|
-
// consumer.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
path:
|
|
220
|
+
// consumer. v2.0.0-rc.38 Goal B: the dead L0/L1/L2 `level` axis was retired
|
|
221
|
+
// too (dead-write — no consumer ordered by it).
|
|
222
|
+
selected_stable_ids: z3.array(z3.string()),
|
|
223
|
+
rules: z3.array(
|
|
224
|
+
z3.object({
|
|
225
|
+
stable_id: z3.string(),
|
|
226
|
+
path: z3.string(),
|
|
192
227
|
// v2.0.0-rc.23 TASK-013 (F8b): replaced the legacy
|
|
193
228
|
// `sections: Record<string,string>` (keyed by the 4-element A-set enum)
|
|
194
229
|
// with the full markdown body (frontmatter stripped). Callers scan the
|
|
195
230
|
// body for whichever B-set heading they need (Summary / Why proposed /
|
|
196
231
|
// Session context / Evidence) — section-name discipline is now a writer
|
|
197
232
|
// convention, not an API contract.
|
|
198
|
-
body:
|
|
233
|
+
body: z3.string()
|
|
199
234
|
})
|
|
200
235
|
),
|
|
201
|
-
diagnostics:
|
|
236
|
+
diagnostics: z3.array(
|
|
202
237
|
// v2.0.0-rc.23 TASK-013 (F8b): `missing_section` was removed alongside the
|
|
203
238
|
// A-set enum. `missing_knowledge_metadata` stays as the warn-level signal
|
|
204
239
|
// for un-migrated v1.x entries (no knowledge_type AND no knowledge_layer
|
|
205
240
|
// in frontmatter). Does NOT block selection.
|
|
206
|
-
|
|
207
|
-
code:
|
|
208
|
-
severity:
|
|
209
|
-
stable_id:
|
|
210
|
-
message:
|
|
241
|
+
z3.object({
|
|
242
|
+
code: z3.enum(["missing_knowledge_metadata", "unresolved_selected_id"]),
|
|
243
|
+
severity: z3.literal("warn"),
|
|
244
|
+
stable_id: z3.string(),
|
|
245
|
+
message: z3.string()
|
|
211
246
|
})
|
|
212
247
|
),
|
|
213
248
|
// v2/rc.3 (Q6) + v2.0.0-rc.37 NEW-24: present iff at least one stable_id in
|
|
@@ -217,113 +252,96 @@ var knowledgeSectionsOutputSchema = z2.object({
|
|
|
217
252
|
// (old_id → new_id) when multiple rewrites fire in one fetch. Both shapes
|
|
218
253
|
// are accepted for forward-compat; readers should branch on shape and
|
|
219
254
|
// refresh their cached ids accordingly.
|
|
220
|
-
redirect_to:
|
|
221
|
-
|
|
222
|
-
|
|
255
|
+
redirect_to: z3.union([
|
|
256
|
+
z3.object({ stable_id: z3.string() }),
|
|
257
|
+
z3.record(z3.string())
|
|
223
258
|
]).optional().describe(
|
|
224
259
|
"Post-layer-flip redirect. Pre-rc.37: { stable_id } shape from rc.3 fab_review/modify. rc.37+: also accepts a (old_id \u2192 new_id) map for fab_get_knowledge_sections / fab_recall transparent rewrite."
|
|
225
260
|
),
|
|
226
|
-
warnings:
|
|
261
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
227
262
|
});
|
|
228
263
|
var knowledgeSectionsAnnotations = {
|
|
229
264
|
readOnlyHint: true,
|
|
230
265
|
idempotentHint: true,
|
|
231
266
|
destructiveHint: false,
|
|
232
267
|
openWorldHint: false,
|
|
233
|
-
title: "
|
|
268
|
+
title: "Fetch knowledge entry bodies"
|
|
234
269
|
};
|
|
235
|
-
var recallInputSchema =
|
|
236
|
-
paths:
|
|
237
|
-
"Candidate file paths to recall Fabric
|
|
270
|
+
var recallInputSchema = z3.object({
|
|
271
|
+
paths: z3.array(z3.string()).min(1).describe(
|
|
272
|
+
"Candidate file paths to recall Fabric knowledge entries for. Same semantics as fab_plan_context.paths."
|
|
238
273
|
),
|
|
239
|
-
intent:
|
|
240
|
-
known_tech:
|
|
241
|
-
detected_entities:
|
|
242
|
-
client_hash:
|
|
243
|
-
correlation_id:
|
|
244
|
-
session_id:
|
|
274
|
+
intent: z3.string().optional().describe("User-stated requirement or implementation intent; used to build a neutral requirement profile."),
|
|
275
|
+
known_tech: z3.array(z3.string()).optional().describe("Known technologies involved."),
|
|
276
|
+
detected_entities: z3.record(z3.array(z3.string())).optional().describe("Optional path-keyed detected entities."),
|
|
277
|
+
client_hash: z3.string().optional().describe("Revision hash from a prior call; enables stale detection."),
|
|
278
|
+
correlation_id: z3.string().optional().describe("Optional caller-provided correlation id for Event Ledger records."),
|
|
279
|
+
session_id: z3.string().optional().describe(
|
|
245
280
|
"Current client session id (Claude Code: $session_id; Codex: corresponding identifier). Enables cross-session debt tracking. Falls back gracefully if omitted."
|
|
246
281
|
),
|
|
247
|
-
layer_filter:
|
|
282
|
+
layer_filter: z3.enum(["team", "personal", "both"]).optional().describe(
|
|
248
283
|
"Restrict recall to the named layer. Default: fabric-config.default_layer_filter."
|
|
249
284
|
),
|
|
250
|
-
target_paths:
|
|
285
|
+
target_paths: z3.array(z3.string()).optional().describe(
|
|
251
286
|
"Path context for narrow-scope relevance filtering. Defaults to `paths`; empty = no filter."
|
|
252
287
|
),
|
|
253
|
-
ids:
|
|
254
|
-
"Optional explicit stable_ids to
|
|
288
|
+
ids: z3.array(z3.string()).optional().describe(
|
|
289
|
+
"Optional explicit stable_ids to SCOPE the returned read paths. When omitted, `paths` carries one read path per surfaced candidate. The candidate DESCRIPTION index is always returned in full for discovery \u2014 `ids` only narrows which read paths are surfaced (e.g. when you already know which entries to Read). Stale ids are redirect-rewritten before matching."
|
|
255
290
|
),
|
|
256
|
-
//
|
|
257
|
-
include_related:
|
|
258
|
-
"When true, also
|
|
291
|
+
// W1-3 / KT-DEC-0031: graph expansion (surface related read paths, no body).
|
|
292
|
+
include_related: z3.boolean().optional().describe(
|
|
293
|
+
"When true, also surface the one-hop `related` graph neighbours (of the surfaced entries) that are present in the candidate set \u2014 their descriptions and read paths, NOT their bodies."
|
|
259
294
|
)
|
|
260
295
|
});
|
|
261
|
-
var recallOutputSchema =
|
|
262
|
-
revision_hash:
|
|
263
|
-
stale:
|
|
264
|
-
// Selection token surfaced for callers who want to continue the conversation
|
|
265
|
-
// with fab_get_knowledge_sections (e.g. fetch additional ids later) — every
|
|
266
|
-
// recall response is still token-backed internally.
|
|
267
|
-
selection_token: z2.string(),
|
|
296
|
+
var recallOutputSchema = z3.object({
|
|
297
|
+
revision_hash: z3.string(),
|
|
298
|
+
stale: z3.boolean(),
|
|
268
299
|
// v2.0.0-rc.38 UX-1/UX-4: mirrors planContextOutputSchema fold ① — per-path
|
|
269
300
|
// description_index collapsed into a single top-level `candidates`, and
|
|
270
301
|
// `preflight_diagnostics` lifted out of the removed `shared` wrapper.
|
|
271
|
-
entries:
|
|
272
|
-
|
|
273
|
-
path:
|
|
302
|
+
entries: z3.array(
|
|
303
|
+
z3.object({
|
|
304
|
+
path: z3.string(),
|
|
274
305
|
requirement_profile: _requirementProfileSchema
|
|
275
306
|
})
|
|
276
307
|
),
|
|
277
|
-
|
|
278
|
-
//
|
|
279
|
-
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
// 边界对 AI 可见): per-rule store provenance so the caller can trace which
|
|
293
|
-
// store each recalled entry came from. cross-store-recall already prefixes
|
|
294
|
-
// store entries `<alias>:<stable_id>`; this surfaces that as a structured
|
|
295
|
-
// field (`{ alias }`) instead of forcing the caller to parse the id. Omitted
|
|
296
|
-
// for project-local entries (no alias prefix). Additive — declare it or zod
|
|
297
|
-
// strips it on output validation.
|
|
298
|
-
store: z2.object({ alias: z2.string() }).optional()
|
|
308
|
+
// v2.2 payload de-dup: single top-level echo of the caller's `intent` (was
|
|
309
|
+
// duplicated into every entry's requirement_profile). Omitted when no intent.
|
|
310
|
+
intent: z3.string().optional(),
|
|
311
|
+
// W1 (KT-DEC-0026): the discovery index — every surfaced candidate's
|
|
312
|
+
// DESCRIPTION (summary / intent_clues / must_read_if / related ...). No body.
|
|
313
|
+
candidates: z3.array(_descriptionIndexItemSchema),
|
|
314
|
+
// W1 (KT-DEC-0026): the read-path index — one entry per surfaced candidate
|
|
315
|
+
// (scoped by `ids` when provided), in ranked order. `path` is the on-disk
|
|
316
|
+
// knowledge file the agent Reads to load the body on demand; `store` is the
|
|
317
|
+
// originating store alias (omitted for unqualified entries).
|
|
318
|
+
paths: z3.array(
|
|
319
|
+
z3.object({
|
|
320
|
+
stable_id: z3.string(),
|
|
321
|
+
path: z3.string(),
|
|
322
|
+
store: z3.object({ alias: z3.string() }).optional()
|
|
299
323
|
})
|
|
300
324
|
),
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
directive: z2.string(),
|
|
322
|
-
next_steps: z2.array(z2.string()).optional(),
|
|
323
|
-
truncation: z2.object({
|
|
324
|
-
omitted_candidate_count: z2.number().int().nonnegative(),
|
|
325
|
-
returned_candidate_count: z2.number().int().nonnegative()
|
|
326
|
-
}).optional()
|
|
325
|
+
// Number of lower-ranked candidates dropped by the retrieval budget. Present
|
|
326
|
+
// (and > 0) ONLY when truncation fired — keeps the steady-state wire shape
|
|
327
|
+
// unchanged while signalling "more exist; narrow your intent".
|
|
328
|
+
omitted_candidate_count: z3.number().int().nonnegative().optional(),
|
|
329
|
+
preflight_diagnostics: z3.array(_preflightDiagnosticSchema),
|
|
330
|
+
warnings: z3.array(structuredWarningSchema).optional(),
|
|
331
|
+
auto_healed: z3.boolean().optional(),
|
|
332
|
+
previous_revision_hash: z3.string().optional(),
|
|
333
|
+
// v2.0.0-rc.37 NEW-24: parallel to planContextOutputSchema.redirects — stale
|
|
334
|
+
// (pre layer-flip) ids in `ids` are redirect-rewritten before matching; the
|
|
335
|
+
// surfaced map exposes the substitution so callers refresh cached state.
|
|
336
|
+
redirects: z3.record(z3.string()).optional(),
|
|
337
|
+
// lifecycle-refactor W3-T2 (§7 图谱消费): related-expansion provenance map
|
|
338
|
+
// (appended id → surfaced source id). Present only when include_related
|
|
339
|
+
// appended an in-corpus neighbour. Omitted on the steady-state path.
|
|
340
|
+
related_appended: z3.record(z3.string()).optional(),
|
|
341
|
+
// v2.2 MC1-recall-pack: standing behavioral directive (cite-before-edit) +
|
|
342
|
+
// dynamic discovery hints, so the one-call recall is self-describing.
|
|
343
|
+
directive: z3.string(),
|
|
344
|
+
next_steps: z3.array(z3.string()).optional()
|
|
327
345
|
});
|
|
328
346
|
var recallAnnotations = {
|
|
329
347
|
readOnlyHint: true,
|
|
@@ -332,34 +350,34 @@ var recallAnnotations = {
|
|
|
332
350
|
openWorldHint: false,
|
|
333
351
|
title: "Recall Fabric knowledge (one-call)"
|
|
334
352
|
};
|
|
335
|
-
var archiveScanInputSchema =
|
|
336
|
-
range:
|
|
353
|
+
var archiveScanInputSchema = z3.object({
|
|
354
|
+
range: z3.union([z3.array(z3.string()).min(1), z3.literal("all")]).optional().describe(
|
|
337
355
|
"Phase 0 scope: explicit session_id[] to constrain the scan, or the 'all' sentinel. Omitted = scan everything since the last knowledge_proposed anchor."
|
|
338
356
|
),
|
|
339
|
-
now_ms:
|
|
340
|
-
correlation_id:
|
|
341
|
-
session_id:
|
|
357
|
+
now_ms: z3.number().int().nonnegative().optional().describe("Override for the anti-loop cooldown clock (testing). Defaults to Date.now()."),
|
|
358
|
+
correlation_id: z3.string().optional().describe("Optional caller-provided correlation id for Event Ledger records."),
|
|
359
|
+
session_id: z3.string().optional().describe("Current client session id; recorded for cross-session debt tracking.")
|
|
342
360
|
});
|
|
343
|
-
var archiveScanOutputSchema =
|
|
361
|
+
var archiveScanOutputSchema = z3.object({
|
|
344
362
|
// ts of the most recent knowledge_proposed event (the lower bound), or null
|
|
345
363
|
// when the workspace has never archived (scan everything).
|
|
346
|
-
anchor_ts:
|
|
364
|
+
anchor_ts: z3.number().nullable(),
|
|
347
365
|
// Distinct session_ids since the anchor that survived the outcome filter,
|
|
348
366
|
// in first-seen order — ready for the Skill to load digests + stitch.
|
|
349
|
-
session_ids:
|
|
367
|
+
session_ids: z3.array(z3.string()),
|
|
350
368
|
// Sessions dropped by the filter, with the rule that fired (audit/debug).
|
|
351
|
-
dropped:
|
|
352
|
-
|
|
353
|
-
session_id:
|
|
354
|
-
reason:
|
|
369
|
+
dropped: z3.array(
|
|
370
|
+
z3.object({
|
|
371
|
+
session_id: z3.string(),
|
|
372
|
+
reason: z3.enum(["user_dismissed", "cooldown", "no_new_signal"])
|
|
355
373
|
})
|
|
356
374
|
),
|
|
357
375
|
// max ts examined across the scan — becomes the next covered_through_ts.
|
|
358
|
-
covered_through_ts:
|
|
376
|
+
covered_through_ts: z3.number().nullable(),
|
|
359
377
|
// Idempotency keys already proposed by prior archive runs but not yet
|
|
360
378
|
// reviewed (Phase 4.5 cross-session pending dedupe). Drop matching candidates.
|
|
361
|
-
already_proposed_keys:
|
|
362
|
-
warnings:
|
|
379
|
+
already_proposed_keys: z3.array(z3.string()),
|
|
380
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
363
381
|
});
|
|
364
382
|
var archiveScanAnnotations = {
|
|
365
383
|
readOnlyHint: true,
|
|
@@ -368,7 +386,7 @@ var archiveScanAnnotations = {
|
|
|
368
386
|
openWorldHint: false,
|
|
369
387
|
title: "Scan event ledger for archive candidates (deterministic)"
|
|
370
388
|
};
|
|
371
|
-
var ProposedReasonSchema =
|
|
389
|
+
var ProposedReasonSchema = z3.enum([
|
|
372
390
|
"explicit-user-mark",
|
|
373
391
|
"diagnostic-then-fix",
|
|
374
392
|
"decision-confirmation",
|
|
@@ -376,7 +394,7 @@ var ProposedReasonSchema = z2.enum([
|
|
|
376
394
|
"new-dependency-or-pattern",
|
|
377
395
|
"dismissal-with-reason"
|
|
378
396
|
]);
|
|
379
|
-
var
|
|
397
|
+
var PROPOSED_REASON_DESCRIPTIONS_ZH = {
|
|
380
398
|
"explicit-user-mark": "\u7528\u6237\u663E\u5F0F\u6807\u8BB0\u9700\u5F52\u6863\uFF08always / never / \u4E0B\u6B21\u6CE8\u610F \u7B49\u89C4\u8303\u6027\u8BED\u8A00\uFF09\u3002",
|
|
381
399
|
"diagnostic-then-fix": "\u8BCA\u65AD\u8FC7\u7A0B\u53D1\u73B0\u65B0\u6A21\u5F0F\u6216\u8E29\u5751\uFF0C\u4FEE\u590D\u540E\u503C\u5F97\u6C89\u6DC0\u3002",
|
|
382
400
|
"decision-confirmation": "\u22652 \u5019\u9009\u65B9\u6848\u7ECF\u6743\u8861\u540E\u786E\u8BA4\u9009\u578B\uFF0C\u9700\u4FDD\u7559 rationale\u3002",
|
|
@@ -384,8 +402,20 @@ var PROPOSED_REASON_DESCRIPTIONS = {
|
|
|
384
402
|
"new-dependency-or-pattern": "\u5F15\u5165\u65B0\u4F9D\u8D56 / \u65B0\u6A21\u5F0F / \u65B0\u547D\u540D\u7EA6\u5B9A\u3002",
|
|
385
403
|
"dismissal-with-reason": "\u7528\u6237\u660E\u786E\u62D2\u7EDD\u67D0\u65B9\u6848\u5E76\u7ED9\u51FA\u539F\u56E0\uFF0C\u539F\u56E0\u5373\u53EF\u5F52\u6863\u77E5\u8BC6\u3002"
|
|
386
404
|
};
|
|
387
|
-
var
|
|
388
|
-
|
|
405
|
+
var PROPOSED_REASON_DESCRIPTIONS_EN = {
|
|
406
|
+
"explicit-user-mark": "User explicitly marked this for archival (normative language: always / never / next time, etc.).",
|
|
407
|
+
"diagnostic-then-fix": "A new pattern or pitfall surfaced during diagnosis and is worth retaining after the fix.",
|
|
408
|
+
"decision-confirmation": "A choice was confirmed after weighing \u22652 candidate approaches; the rationale must be preserved.",
|
|
409
|
+
"wrong-turn-revert": "A path was tried then reverted; the wrong turn itself is a pitfall worth recording.",
|
|
410
|
+
"new-dependency-or-pattern": "Introduces a new dependency / pattern / naming convention.",
|
|
411
|
+
"dismissal-with-reason": "The user explicitly rejected an approach and gave a reason; the reason is archivable knowledge."
|
|
412
|
+
};
|
|
413
|
+
var PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE = {
|
|
414
|
+
"zh-CN": PROPOSED_REASON_DESCRIPTIONS_ZH,
|
|
415
|
+
en: PROPOSED_REASON_DESCRIPTIONS_EN
|
|
416
|
+
};
|
|
417
|
+
var _sourceSessionsField = z3.array(z3.string().min(1)).min(1);
|
|
418
|
+
var _FabExtractKnowledgeInputBaseSchema = z3.object({
|
|
389
419
|
// v2.0.0-rc.7 T5: array form. rc.23 dropped the legacy single-string alias.
|
|
390
420
|
// v2.2 全砍 F13: REQUIRED in the base schema (was `.optional()`) so the MCP
|
|
391
421
|
// tool's advertised inputSchema (registerTool reads `.shape`) matches the
|
|
@@ -394,15 +424,19 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
394
424
|
source_sessions: _sourceSessionsField.describe(
|
|
395
425
|
"Originating session ids (REQUIRED, non-empty array); correlates with Event Ledger records. Array form (T5+, rc.23 made it the sole accepted shape)."
|
|
396
426
|
),
|
|
397
|
-
recent_paths:
|
|
398
|
-
user_messages_summary:
|
|
399
|
-
type:
|
|
400
|
-
slug:
|
|
401
|
-
//
|
|
402
|
-
//
|
|
427
|
+
recent_paths: z3.array(z3.string()).describe("Workspace paths recently touched in the source session \u2014 used as scope hints"),
|
|
428
|
+
user_messages_summary: z3.string().describe("Skill-side summary of the user's intent/messages, kept compact"),
|
|
429
|
+
type: z3.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]).describe("Knowledge type bucket (plural form, mirrors directory layout)"),
|
|
430
|
+
slug: z3.string().describe("URL-safe short identifier proposed by the Skill; server may sanitize"),
|
|
431
|
+
// Store-only cutover: layer is a compatibility audience hint. The server
|
|
432
|
+
// resolves the actual write target through semantic_scope/write_routes and
|
|
433
|
+
// writes to the selected mounted store's knowledge/pending/<type>/ tree.
|
|
403
434
|
// Defaults to 'team' to preserve existing call sites (Skill bumps as needed).
|
|
404
|
-
layer:
|
|
405
|
-
"
|
|
435
|
+
layer: z3.enum(["team", "personal"]).optional().describe(
|
|
436
|
+
"Compatibility storage audience. 'personal' writes to the personal store; non-personal writes resolve by semantic_scope/write_routes. Defaults to 'team'."
|
|
437
|
+
),
|
|
438
|
+
semantic_scope: z3.string().regex(SCOPE_COORDINATE_PATTERN).optional().describe(
|
|
439
|
+
"Logical audience/write route coordinate for this pending entry, e.g. personal, team, project:fabric-v2, org:acme:team:platform. Server validates and resolves it through write_routes."
|
|
406
440
|
),
|
|
407
441
|
// v2.0.0-rc.7 T6: proposed_reason — required enum that drives `## Why
|
|
408
442
|
// proposed` rendering. Skills (archive / import / review) infer the
|
|
@@ -414,7 +448,7 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
414
448
|
// captures the session goal + key turning point. Future-self review reads
|
|
415
449
|
// this without conversation transcript access. Min length guards against
|
|
416
450
|
// empty placeholders; cap is soft (no max), Skill caps at ~600 chars.
|
|
417
|
-
session_context:
|
|
451
|
+
session_context: z3.string().min(20, { message: "session_context must be \u226520 chars (3-5 lines describing goal + turning point)" }).describe(
|
|
418
452
|
"3-5 line markdown blob \u2014 session goal + key turning point. Reviewed by future-self without transcript access."
|
|
419
453
|
),
|
|
420
454
|
// v2.0.0-rc.8 A1 (skill-contract-fix): relevance scope/paths on the
|
|
@@ -428,10 +462,10 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
428
462
|
// a `knowledge_scope_degraded` event keyed by `pending:<idempotency_key>`.
|
|
429
463
|
// NOTE: these fields MUST NOT be part of the idempotency hash inputs at
|
|
430
464
|
// extract-knowledge.ts:78 — preserves rc.5→rc.7 collision detection.
|
|
431
|
-
relevance_scope:
|
|
465
|
+
relevance_scope: z3.enum(["narrow", "broad"]).optional().describe(
|
|
432
466
|
"Optional relevance scope. 'narrow' restricts plan-context-hint surfacing to relevance_paths; 'broad' always surfaces. Omit to let the meta-builder default to 'broad'. Personal + narrow is silently degraded to broad + []."
|
|
433
467
|
),
|
|
434
|
-
relevance_paths:
|
|
468
|
+
relevance_paths: z3.array(z3.string()).optional().describe(
|
|
435
469
|
"Optional path anchors for narrow scope. Workspace-relative globs or paths. Omit to let the meta-builder default to []. Ignored when scope is broad (server preserves the array for audit)."
|
|
436
470
|
),
|
|
437
471
|
// v2.0.0-rc.23 TASK-006 (a-C1): four optional structured fields that the
|
|
@@ -448,16 +482,16 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
448
482
|
// relevance_paths follow the same rule). Including them would let an LLM
|
|
449
483
|
// re-roll of the same observation create a second pending file just because
|
|
450
484
|
// its inferred metadata wording drifted.
|
|
451
|
-
intent_clues:
|
|
485
|
+
intent_clues: z3.array(z3.string()).optional().describe(
|
|
452
486
|
"Short LLM-readable triggers describing when this rule should fire and when it should not. Each item \u226480 chars, imperative phrasing (e.g. 'when editing Cocos UI batch code', 'NOT for non-batch contexts'). Optional \u2014 omit when the skill cannot infer cleanly."
|
|
453
487
|
),
|
|
454
|
-
tech_stack:
|
|
488
|
+
tech_stack: z3.array(z3.string()).optional().describe(
|
|
455
489
|
"Tech stack / languages / frameworks the rule applies to (e.g. ['typescript', 'cocos-creator', 'nodejs']). Inferred from recent_paths file extensions and manifest files. Optional \u2014 omit when the rule is stack-agnostic."
|
|
456
490
|
),
|
|
457
|
-
impact:
|
|
491
|
+
impact: z3.array(z3.string()).optional().describe(
|
|
458
492
|
"Consequences of ignoring this rule, used by the LLM to weight relevance vs cost. Each item \u2264120 chars (e.g. 'O(n\xB2) re-render on every frame', 'silent data loss on collision'). Optional \u2014 omit when impact is not observable."
|
|
459
493
|
),
|
|
460
|
-
must_read_if:
|
|
494
|
+
must_read_if: z3.string().optional().describe(
|
|
461
495
|
"One-line strong trigger; when this condition holds the entry is considered required reading. Single line \u2264160 chars (e.g. 'touching anything under packages/cli/src/commands/hooks.ts'). Optional \u2014 omit when no single strong trigger fits."
|
|
462
496
|
),
|
|
463
497
|
// v2.0.0-rc.37 NEW-37 (werewolf dogfood remediation): optional tags array.
|
|
@@ -468,7 +502,7 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
468
502
|
// IDEMPOTENCY: tags MUST NOT 参与 idempotency_key hash(同 relevance_*
|
|
469
503
|
// / intent_clues 等可变字段一致),re-extract 时 tags 调整不应产生重复
|
|
470
504
|
// pending file。
|
|
471
|
-
tags:
|
|
505
|
+
tags: z3.array(z3.string()).optional().describe(
|
|
472
506
|
"Optional topic tags (2-4 kebab-case strings recommended). Drives cross-entry retrieval + topic clustering. Skill-inferred from session content; omit when not confidently inferable. Empty array allowed but discouraged (degrades narrow hint topic signal)."
|
|
473
507
|
),
|
|
474
508
|
// v2.0.0-rc.23 TASK-014 (F8c): optional onboard-slot tag. The S5 slot
|
|
@@ -503,7 +537,7 @@ var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
|
503
537
|
// signal was captured. Like relevance_paths it MUST NOT participate in
|
|
504
538
|
// the idempotency_key hash (an idempotent re-extract may surface a
|
|
505
539
|
// slightly different read set without spawning a duplicate pending).
|
|
506
|
-
evidence_paths:
|
|
540
|
+
evidence_paths: z3.array(z3.string()).optional().describe(
|
|
507
541
|
"Workspace-relative paths the agent CONSULTED (read but never modified) while building this knowledge. Documents context without affecting activation. Lifted from the legacy body ## Evidence markdown block into structured frontmatter so plan-context retrieval can read it as data."
|
|
508
542
|
)
|
|
509
543
|
});
|
|
@@ -512,7 +546,7 @@ var FabExtractKnowledgeInputSchema = _FabExtractKnowledgeInputBaseSchema.superRe
|
|
|
512
546
|
const hasArray = Array.isArray(value.source_sessions) && value.source_sessions.length > 0;
|
|
513
547
|
if (!hasArray) {
|
|
514
548
|
ctx.addIssue({
|
|
515
|
-
code:
|
|
549
|
+
code: z3.ZodIssueCode.custom,
|
|
516
550
|
message: "source_sessions (non-empty string array) is required",
|
|
517
551
|
path: ["source_sessions"]
|
|
518
552
|
});
|
|
@@ -520,12 +554,12 @@ var FabExtractKnowledgeInputSchema = _FabExtractKnowledgeInputBaseSchema.superRe
|
|
|
520
554
|
}
|
|
521
555
|
);
|
|
522
556
|
var FabExtractKnowledgeInputShape = _FabExtractKnowledgeInputBaseSchema.shape;
|
|
523
|
-
var FabExtractKnowledgeOutputSchema =
|
|
524
|
-
pending_path:
|
|
525
|
-
idempotency_key:
|
|
557
|
+
var FabExtractKnowledgeOutputSchema = z3.object({
|
|
558
|
+
pending_path: z3.string().describe("Workspace-relative path to the persisted pending entry"),
|
|
559
|
+
idempotency_key: z3.string().describe("Stable key derived from inputs; identical inputs yield identical key"),
|
|
526
560
|
// v2.0.0-rc.23 TASK-009 (d): optional warnings surface for the first-reconcile
|
|
527
561
|
// gate (`meta_stale` / `reconcile_failed`). Absent on the steady-state path.
|
|
528
|
-
warnings:
|
|
562
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
529
563
|
});
|
|
530
564
|
var fabExtractKnowledgeAnnotations = {
|
|
531
565
|
readOnlyHint: false,
|
|
@@ -534,21 +568,21 @@ var fabExtractKnowledgeAnnotations = {
|
|
|
534
568
|
openWorldHint: false,
|
|
535
569
|
title: "Extract pending knowledge entry"
|
|
536
570
|
};
|
|
537
|
-
var _fabReviewFiltersSchema =
|
|
538
|
-
type:
|
|
539
|
-
layer:
|
|
540
|
-
maturity:
|
|
541
|
-
tags:
|
|
571
|
+
var _fabReviewFiltersSchema = z3.object({
|
|
572
|
+
type: z3.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]).optional(),
|
|
573
|
+
layer: z3.enum(["team", "personal", "both"]).optional(),
|
|
574
|
+
maturity: z3.enum(["draft", "verified", "proven"]).optional(),
|
|
575
|
+
tags: z3.array(z3.string()).optional(),
|
|
542
576
|
// rc.4 TASK-006 fix (c): ISO-8601 lower bound on entry created_at; entries
|
|
543
577
|
// strictly older than this threshold are excluded from list / search
|
|
544
578
|
// results. Additive optional field — existing callers unaffected.
|
|
545
|
-
created_after:
|
|
579
|
+
created_after: z3.string().datetime().optional(),
|
|
546
580
|
// v2.0.0-rc.27 TASK-001 (§2.2/§2.3): opt-in surfacing of lifecycle-filtered
|
|
547
581
|
// entries. Default (omit both) hides rejected entries and deferred entries
|
|
548
582
|
// whose deferred_until is in the future. Pass true to include them — e.g.
|
|
549
583
|
// for vacuum tooling, audit dashboards, or "show me what I parked" UX.
|
|
550
|
-
include_rejected:
|
|
551
|
-
include_deferred:
|
|
584
|
+
include_rejected: z3.boolean().optional(),
|
|
585
|
+
include_deferred: z3.boolean().optional(),
|
|
552
586
|
// v2.0.0-rc.27 TASK-006 (audit §2.23): opt-in body inspection. Default
|
|
553
587
|
// list/search return only frontmatter-derived fields — a malicious
|
|
554
588
|
// pending entry could hide a prompt-injection payload under `## Evidence`
|
|
@@ -558,41 +592,57 @@ var _fabReviewFiltersSchema = z2.object({
|
|
|
558
592
|
// default-off design keeps the wire payload small for routine list
|
|
559
593
|
// calls; reviewer workflows pass `true` before approving so the body
|
|
560
594
|
// is rendered into the reviewer's UI for visual scan.
|
|
561
|
-
include_body:
|
|
595
|
+
include_body: z3.boolean().optional()
|
|
562
596
|
}).optional();
|
|
563
|
-
var _fabReviewModifyChangesSchema =
|
|
564
|
-
title:
|
|
565
|
-
summary:
|
|
597
|
+
var _fabReviewModifyChangesSchema = z3.object({
|
|
598
|
+
title: z3.string().optional(),
|
|
599
|
+
summary: z3.string().optional(),
|
|
566
600
|
// Q7: writing `layer` here triggers a layer-flip; downstream callers may
|
|
567
601
|
// observe a redirect_to in fab_get_knowledge_sections if stable_id changes.
|
|
568
|
-
layer:
|
|
569
|
-
maturity:
|
|
570
|
-
tags:
|
|
602
|
+
layer: z3.enum(["team", "personal"]).optional(),
|
|
603
|
+
maturity: z3.enum(["draft", "verified", "proven"]).optional(),
|
|
604
|
+
tags: z3.array(z3.string()).optional(),
|
|
571
605
|
// v2.0-rc.5 C3 (TASK-012): relevance scope/paths patches. Applied to
|
|
572
606
|
// pending AND canonical entries. When an explicit team→personal layer flip
|
|
573
607
|
// arrives on a narrow entry, the server auto-degrades to broad + [] and
|
|
574
608
|
// emits a `knowledge_scope_degraded` event regardless of what the caller
|
|
575
609
|
// sent in these fields (personal-implies-broad).
|
|
576
|
-
relevance_scope:
|
|
577
|
-
relevance_paths:
|
|
610
|
+
relevance_scope: z3.enum(["narrow", "broad"]).optional(),
|
|
611
|
+
relevance_paths: z3.array(z3.string()).optional(),
|
|
612
|
+
// v2.2 project-scope migration: re-scope an existing entry's resolution
|
|
613
|
+
// coordinate (e.g. team → project:fabric-v2) WITHOUT moving stores
|
|
614
|
+
// (scope ⊥ store, S42/A2). The in-place modify path keeps visibility_store
|
|
615
|
+
// intact, so a team→project flip just relabels who recall surfaces it to
|
|
616
|
+
// (G-FILTER, cross-store-recall.ts) — the entry stays physically in the
|
|
617
|
+
// same shared store. A personal-root coordinate is rejected here: landing
|
|
618
|
+
// an entry in the personal store is a store move, which is the dedicated
|
|
619
|
+
// modify-layer path (R5#3 privacy boundary), never an in-place scalar edit.
|
|
620
|
+
semantic_scope: z3.string().regex(SCOPE_COORDINATE_PATTERN).optional(),
|
|
621
|
+
// v2.2 graph edges (KT-DEC-0031 wiki seam): write the `related` H2 adjacency
|
|
622
|
+
// (bare or store-qualified stable_ids this entry points at). REPLACE semantics
|
|
623
|
+
// mirror tags/relevance_paths — the caller (fabric-connect) reads existing
|
|
624
|
+
// edges via fab_recall and sends the merged set. Absent this field the modify
|
|
625
|
+
// path silently dropped `related` via zod .strip() (KT-PIT-0005 recurrence),
|
|
626
|
+
// leaving the only programmatic related-write path non-functional.
|
|
627
|
+
related: z3.array(z3.string()).optional()
|
|
578
628
|
});
|
|
579
|
-
var FabReviewInputSchema =
|
|
580
|
-
|
|
581
|
-
action:
|
|
629
|
+
var FabReviewInputSchema = z3.discriminatedUnion("action", [
|
|
630
|
+
z3.object({
|
|
631
|
+
action: z3.literal("list"),
|
|
582
632
|
filters: _fabReviewFiltersSchema
|
|
583
633
|
}),
|
|
584
|
-
|
|
585
|
-
action:
|
|
586
|
-
pending_paths:
|
|
634
|
+
z3.object({
|
|
635
|
+
action: z3.literal("approve"),
|
|
636
|
+
pending_paths: z3.array(z3.string()).min(1)
|
|
587
637
|
}),
|
|
588
|
-
|
|
589
|
-
action:
|
|
590
|
-
pending_paths:
|
|
591
|
-
reason:
|
|
638
|
+
z3.object({
|
|
639
|
+
action: z3.literal("reject"),
|
|
640
|
+
pending_paths: z3.array(z3.string()).min(1),
|
|
641
|
+
reason: z3.string().min(1)
|
|
592
642
|
}),
|
|
593
|
-
|
|
594
|
-
action:
|
|
595
|
-
pending_path:
|
|
643
|
+
z3.object({
|
|
644
|
+
action: z3.literal("modify"),
|
|
645
|
+
pending_path: z3.string().min(1),
|
|
596
646
|
changes: _fabReviewModifyChangesSchema
|
|
597
647
|
}),
|
|
598
648
|
// v2.0.0-rc.37 NEW-12: explicit modify split. `modify-content` edits scalar
|
|
@@ -601,177 +651,176 @@ var FabReviewInputSchema = z2.discriminatedUnion("action", [
|
|
|
601
651
|
// (changes.layer REQUIRED) which may reallocate the stable_id + emit an
|
|
602
652
|
// id-redirect (rc.37 NEW-24). Legacy `modify` stays for back-compat and
|
|
603
653
|
// routes by whether changes.layer is present.
|
|
604
|
-
|
|
605
|
-
action:
|
|
606
|
-
pending_path:
|
|
654
|
+
z3.object({
|
|
655
|
+
action: z3.literal("modify-content"),
|
|
656
|
+
pending_path: z3.string().min(1),
|
|
607
657
|
changes: _fabReviewModifyChangesSchema
|
|
608
658
|
}),
|
|
609
|
-
|
|
610
|
-
action:
|
|
611
|
-
pending_path:
|
|
659
|
+
z3.object({
|
|
660
|
+
action: z3.literal("modify-layer"),
|
|
661
|
+
pending_path: z3.string().min(1),
|
|
612
662
|
changes: _fabReviewModifyChangesSchema.extend({
|
|
613
|
-
layer:
|
|
663
|
+
layer: z3.enum(["team", "personal"])
|
|
614
664
|
})
|
|
615
665
|
}),
|
|
616
|
-
|
|
617
|
-
action:
|
|
618
|
-
query:
|
|
666
|
+
z3.object({
|
|
667
|
+
action: z3.literal("search"),
|
|
668
|
+
query: z3.string().min(1),
|
|
619
669
|
filters: _fabReviewFiltersSchema
|
|
620
670
|
}),
|
|
621
|
-
|
|
622
|
-
action:
|
|
623
|
-
pending_paths:
|
|
624
|
-
until:
|
|
625
|
-
reason:
|
|
671
|
+
z3.object({
|
|
672
|
+
action: z3.literal("defer"),
|
|
673
|
+
pending_paths: z3.array(z3.string()).min(1),
|
|
674
|
+
until: z3.string().datetime().optional(),
|
|
675
|
+
reason: z3.string().optional()
|
|
626
676
|
})
|
|
627
677
|
]);
|
|
628
678
|
var FabReviewInputShape = {
|
|
629
|
-
action:
|
|
679
|
+
action: z3.enum(["list", "approve", "reject", "modify", "modify-content", "modify-layer", "search", "defer"]).describe(
|
|
630
680
|
"Action selector. Discriminates the per-action fields below; required. modify-content edits scalars (no layer); modify-layer is the layer-flip path (changes.layer required); modify is the legacy combined alias."
|
|
631
681
|
),
|
|
632
682
|
filters: _fabReviewFiltersSchema.describe(
|
|
633
683
|
"Optional filters (type/layer/maturity/tags/created_after). Used by action=list and action=search."
|
|
634
684
|
),
|
|
635
|
-
pending_paths:
|
|
685
|
+
pending_paths: z3.array(z3.string()).min(1).optional().describe(
|
|
636
686
|
"Workspace-relative pending entry paths. Required when action=approve|reject|defer (non-empty array)."
|
|
637
687
|
),
|
|
638
|
-
pending_path:
|
|
688
|
+
pending_path: z3.string().min(1).optional().describe(
|
|
639
689
|
"Workspace-relative pending OR canonical entry path. Required when action=modify."
|
|
640
690
|
),
|
|
641
|
-
reason:
|
|
691
|
+
reason: z3.string().optional().describe(
|
|
642
692
|
"Reason string. Required (non-empty) when action=reject; optional when action=defer."
|
|
643
693
|
),
|
|
644
694
|
changes: _fabReviewModifyChangesSchema.optional().describe(
|
|
645
|
-
"Frontmatter scalar patches (title/summary/layer/maturity/tags/relevance_
|
|
695
|
+
"Frontmatter scalar patches (title/summary/layer/maturity/tags/relevance_*/semantic_scope/related). Required when action=modify. semantic_scope re-scopes the entry's resolution coordinate in place (e.g. team \u2192 project:<id>) without moving stores; personal-root coordinates are rejected (use modify-layer)."
|
|
646
696
|
),
|
|
647
|
-
query:
|
|
697
|
+
query: z3.string().min(1).optional().describe(
|
|
648
698
|
"Substring query against title/summary/tags/path. Required (non-empty) when action=search."
|
|
649
699
|
),
|
|
650
|
-
until:
|
|
700
|
+
until: z3.string().datetime().optional().describe(
|
|
651
701
|
"ISO-8601 datetime upper bound for the deferral. Optional; used only when action=defer."
|
|
652
702
|
)
|
|
653
703
|
};
|
|
654
|
-
var _fabReviewListItemSchema =
|
|
655
|
-
pending_path:
|
|
704
|
+
var _fabReviewListItemSchema = z3.object({
|
|
705
|
+
pending_path: z3.string(),
|
|
656
706
|
// v2.0.0-rc.27 TASK-001 (§2.12): for personal-layer entries `pending_path`
|
|
657
707
|
// carries the human-friendly `~/...` form (legacy contract) while
|
|
658
708
|
// `pending_path_absolute` carries the os-expanded absolute path. Programmatic
|
|
659
709
|
// consumers (Read tool, fs.readFile, downstream MCP servers) should prefer
|
|
660
710
|
// the absolute variant — the `~` is a shell-only sigil that breaks every
|
|
661
711
|
// non-shell consumer. Team entries omit this field because their
|
|
662
|
-
// `pending_path` is already
|
|
663
|
-
pending_path_absolute:
|
|
664
|
-
type:
|
|
665
|
-
layer:
|
|
666
|
-
maturity:
|
|
667
|
-
tags:
|
|
668
|
-
title:
|
|
669
|
-
summary:
|
|
670
|
-
//
|
|
671
|
-
//
|
|
672
|
-
//
|
|
673
|
-
|
|
674
|
-
origin: z2.enum(["team", "personal"]).optional(),
|
|
712
|
+
// `pending_path` is already store-resolved and unambiguous.
|
|
713
|
+
pending_path_absolute: z3.string().optional(),
|
|
714
|
+
type: z3.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]),
|
|
715
|
+
layer: z3.enum(["team", "personal"]),
|
|
716
|
+
maturity: z3.enum(["draft", "verified", "proven"]),
|
|
717
|
+
tags: z3.array(z3.string()).optional(),
|
|
718
|
+
title: z3.string().optional(),
|
|
719
|
+
summary: z3.string().optional(),
|
|
720
|
+
// Store-only cutover: origin reflects the resolved store audience where the
|
|
721
|
+
// pending file lives; layer reflects the declared classification that will
|
|
722
|
+
// drive approval semantics.
|
|
723
|
+
origin: z3.enum(["team", "personal"]).optional(),
|
|
675
724
|
// v2.0.0-rc.27 TASK-001 (§2.2/§2.3): frontmatter status markers. Default
|
|
676
725
|
// "active" (or absent). `rejected` entries are excluded from list/search
|
|
677
726
|
// unless filters.include_rejected=true; `deferred` entries are excluded
|
|
678
727
|
// when deferred_until is in the future. Authored by reject/defer write
|
|
679
728
|
// paths — never by extract or approve.
|
|
680
|
-
status:
|
|
681
|
-
deferred_until:
|
|
729
|
+
status: z3.enum(["active", "rejected", "deferred"]).optional(),
|
|
730
|
+
deferred_until: z3.string().datetime().optional(),
|
|
682
731
|
// v2.0.0-rc.27 TASK-006 (audit §2.23): full body content (everything
|
|
683
732
|
// after the closing `---` of frontmatter). Surfaced only when caller
|
|
684
733
|
// passes `filters.include_body: true`. Default-omitted to keep payload
|
|
685
734
|
// small for routine list calls.
|
|
686
|
-
body:
|
|
735
|
+
body: z3.string().optional()
|
|
687
736
|
});
|
|
688
|
-
var _fabReviewSearchItemSchema =
|
|
689
|
-
// Search hits live in one of two trees:
|
|
690
|
-
// - "pending" →
|
|
691
|
-
// - "canonical" →
|
|
692
|
-
area:
|
|
693
|
-
path:
|
|
694
|
-
path_absolute:
|
|
695
|
-
type:
|
|
696
|
-
layer:
|
|
697
|
-
maturity:
|
|
698
|
-
tags:
|
|
699
|
-
title:
|
|
700
|
-
summary:
|
|
701
|
-
origin:
|
|
702
|
-
status:
|
|
703
|
-
deferred_until:
|
|
704
|
-
body:
|
|
737
|
+
var _fabReviewSearchItemSchema = z3.object({
|
|
738
|
+
// Search hits live in one of two store trees:
|
|
739
|
+
// - "pending" → mounted store `knowledge/pending/`
|
|
740
|
+
// - "canonical" → mounted store `knowledge/{decisions,pitfalls,...}`
|
|
741
|
+
area: z3.enum(["pending", "canonical"]),
|
|
742
|
+
path: z3.string(),
|
|
743
|
+
path_absolute: z3.string().optional(),
|
|
744
|
+
type: z3.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]),
|
|
745
|
+
layer: z3.enum(["team", "personal"]),
|
|
746
|
+
maturity: z3.enum(["draft", "verified", "proven"]),
|
|
747
|
+
tags: z3.array(z3.string()).optional(),
|
|
748
|
+
title: z3.string().optional(),
|
|
749
|
+
summary: z3.string().optional(),
|
|
750
|
+
origin: z3.enum(["team", "personal"]).optional(),
|
|
751
|
+
status: z3.enum(["active", "rejected", "deferred"]).optional(),
|
|
752
|
+
deferred_until: z3.string().datetime().optional(),
|
|
753
|
+
body: z3.string().optional(),
|
|
705
754
|
// For pending hits the upstream stable_id may still be unassigned — keep it
|
|
706
755
|
// optional so canonical hits (which always have one) parse alongside pending
|
|
707
756
|
// hits in the same array.
|
|
708
|
-
stable_id:
|
|
757
|
+
stable_id: z3.string().optional()
|
|
709
758
|
});
|
|
710
|
-
var FabReviewOutputSchema =
|
|
711
|
-
|
|
712
|
-
action:
|
|
713
|
-
items:
|
|
714
|
-
warnings:
|
|
759
|
+
var FabReviewOutputSchema = z3.discriminatedUnion("action", [
|
|
760
|
+
z3.object({
|
|
761
|
+
action: z3.literal("list"),
|
|
762
|
+
items: z3.array(_fabReviewListItemSchema),
|
|
763
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
715
764
|
}),
|
|
716
|
-
|
|
717
|
-
action:
|
|
718
|
-
approved:
|
|
719
|
-
warnings:
|
|
765
|
+
z3.object({
|
|
766
|
+
action: z3.literal("approve"),
|
|
767
|
+
approved: z3.array(z3.object({ pending_path: z3.string(), stable_id: z3.string() })),
|
|
768
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
720
769
|
}),
|
|
721
|
-
|
|
722
|
-
action:
|
|
723
|
-
rejected:
|
|
724
|
-
warnings:
|
|
770
|
+
z3.object({
|
|
771
|
+
action: z3.literal("reject"),
|
|
772
|
+
rejected: z3.array(z3.string()),
|
|
773
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
725
774
|
}),
|
|
726
|
-
|
|
727
|
-
action:
|
|
728
|
-
pending_path:
|
|
775
|
+
z3.object({
|
|
776
|
+
action: z3.literal("modify"),
|
|
777
|
+
pending_path: z3.string(),
|
|
729
778
|
// When a layer-flip occurred, prior_stable_id and new_stable_id differ.
|
|
730
|
-
prior_stable_id:
|
|
731
|
-
new_stable_id:
|
|
732
|
-
warnings:
|
|
779
|
+
prior_stable_id: z3.string().optional(),
|
|
780
|
+
new_stable_id: z3.string().optional(),
|
|
781
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
733
782
|
}),
|
|
734
|
-
|
|
735
|
-
action:
|
|
783
|
+
z3.object({
|
|
784
|
+
action: z3.literal("search"),
|
|
736
785
|
// v2.0.0-rc.29 TASK-007 (BUG-M4): search returns the new search-item
|
|
737
786
|
// shape with `area` discriminator + neutrally-named `path` field.
|
|
738
|
-
items:
|
|
739
|
-
warnings:
|
|
787
|
+
items: z3.array(_fabReviewSearchItemSchema),
|
|
788
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
740
789
|
}),
|
|
741
|
-
|
|
742
|
-
action:
|
|
743
|
-
deferred:
|
|
744
|
-
warnings:
|
|
790
|
+
z3.object({
|
|
791
|
+
action: z3.literal("defer"),
|
|
792
|
+
deferred: z3.array(z3.string()),
|
|
793
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
745
794
|
})
|
|
746
795
|
]);
|
|
747
796
|
var FabReviewOutputShape = {
|
|
748
|
-
action:
|
|
797
|
+
action: z3.enum(["list", "approve", "reject", "modify", "search", "defer"]).describe(
|
|
749
798
|
"Echoes the input action; clients can switch on it for per-variant fields below."
|
|
750
799
|
),
|
|
751
|
-
items:
|
|
800
|
+
items: z3.array(z3.union([_fabReviewListItemSchema, _fabReviewSearchItemSchema])).optional().describe(
|
|
752
801
|
"Pending entries (action=list, `pending_path` shape) or pending+canonical entries (action=search, `area`+`path` shape)."
|
|
753
802
|
),
|
|
754
|
-
approved:
|
|
803
|
+
approved: z3.array(z3.object({ pending_path: z3.string(), stable_id: z3.string() })).optional().describe(
|
|
755
804
|
"Allocated stable ids paired with their original pending paths. Present when action=approve."
|
|
756
805
|
),
|
|
757
|
-
rejected:
|
|
806
|
+
rejected: z3.array(z3.string()).optional().describe(
|
|
758
807
|
"Pending paths that were rejected (files retained on disk; doctor owns vacuum). Present when action=reject."
|
|
759
808
|
),
|
|
760
|
-
pending_path:
|
|
809
|
+
pending_path: z3.string().optional().describe(
|
|
761
810
|
"Echoed target path for the modification. Present when action=modify."
|
|
762
811
|
),
|
|
763
|
-
prior_stable_id:
|
|
812
|
+
prior_stable_id: z3.string().optional().describe(
|
|
764
813
|
"Prior stable id. Present when action=modify AND a layer-flip reallocated the id."
|
|
765
814
|
),
|
|
766
|
-
new_stable_id:
|
|
815
|
+
new_stable_id: z3.string().optional().describe(
|
|
767
816
|
"New stable id after reallocation. Present when action=modify AND a layer-flip reallocated the id."
|
|
768
817
|
),
|
|
769
|
-
deferred:
|
|
818
|
+
deferred: z3.array(z3.string()).optional().describe(
|
|
770
819
|
"Pending paths that were deferred (files retained on disk). Present when action=defer."
|
|
771
820
|
),
|
|
772
821
|
// v2.0.0-rc.23 TASK-009 (d): optional warnings surface for the first-reconcile
|
|
773
822
|
// gate (`meta_stale` / `reconcile_failed`). Absent on the steady-state path.
|
|
774
|
-
warnings:
|
|
823
|
+
warnings: z3.array(structuredWarningSchema).optional()
|
|
775
824
|
};
|
|
776
825
|
var fabReviewAnnotations = {
|
|
777
826
|
readOnlyHint: false,
|
|
@@ -780,35 +829,35 @@ var fabReviewAnnotations = {
|
|
|
780
829
|
openWorldHint: false,
|
|
781
830
|
title: "Review pending knowledge entries"
|
|
782
831
|
};
|
|
783
|
-
var citeContractMetricsSchema =
|
|
784
|
-
decisions_cited:
|
|
785
|
-
pitfalls_cited:
|
|
786
|
-
contract_with:
|
|
787
|
-
contract_missing:
|
|
788
|
-
hard_violated:
|
|
789
|
-
cite_id_unresolved:
|
|
790
|
-
skip_count:
|
|
832
|
+
var citeContractMetricsSchema = z3.object({
|
|
833
|
+
decisions_cited: z3.number().int().nonnegative(),
|
|
834
|
+
pitfalls_cited: z3.number().int().nonnegative(),
|
|
835
|
+
contract_with: z3.number().int().nonnegative(),
|
|
836
|
+
contract_missing: z3.number().int().nonnegative(),
|
|
837
|
+
hard_violated: z3.number().int().nonnegative(),
|
|
838
|
+
cite_id_unresolved: z3.number().int().nonnegative(),
|
|
839
|
+
skip_count: z3.record(z3.string(), z3.number().int().nonnegative())
|
|
791
840
|
});
|
|
792
|
-
var citeLayerTypeBreakdownSchema =
|
|
793
|
-
team:
|
|
794
|
-
personal:
|
|
841
|
+
var citeLayerTypeBreakdownSchema = z3.object({
|
|
842
|
+
team: z3.record(z3.string(), z3.number().int().nonnegative()),
|
|
843
|
+
personal: z3.record(z3.string(), z3.number().int().nonnegative())
|
|
795
844
|
});
|
|
796
|
-
var citeCoverageReportSchema =
|
|
797
|
-
status:
|
|
798
|
-
marker_ts:
|
|
799
|
-
marker_emitted_now:
|
|
800
|
-
since_ts:
|
|
801
|
-
client_filter:
|
|
845
|
+
var citeCoverageReportSchema = z3.object({
|
|
846
|
+
status: z3.enum(["ok", "skipped"]),
|
|
847
|
+
marker_ts: z3.number().int().nonnegative(),
|
|
848
|
+
marker_emitted_now: z3.boolean(),
|
|
849
|
+
since_ts: z3.number().int().nonnegative(),
|
|
850
|
+
client_filter: z3.enum(["cc", "codex", "all"]),
|
|
802
851
|
// v2.0.0-rc.24 TASK-08: layer filter discriminator. Optional so pre-TASK-10
|
|
803
852
|
// CLI callers (which never set the flag) still parse. Defaults to "all" at
|
|
804
853
|
// the service layer.
|
|
805
|
-
layer_filter:
|
|
806
|
-
metrics:
|
|
807
|
-
edits_touched:
|
|
808
|
-
qualifying_cites:
|
|
809
|
-
recalled_unverified:
|
|
810
|
-
expected_but_missed:
|
|
811
|
-
total_turns:
|
|
854
|
+
layer_filter: z3.enum(["team", "personal", "all"]).optional(),
|
|
855
|
+
metrics: z3.object({
|
|
856
|
+
edits_touched: z3.number().int().nonnegative(),
|
|
857
|
+
qualifying_cites: z3.number().int().nonnegative(),
|
|
858
|
+
recalled_unverified: z3.number().int().nonnegative(),
|
|
859
|
+
expected_but_missed: z3.number().int().nonnegative(),
|
|
860
|
+
total_turns: z3.number().int().nonnegative(),
|
|
812
861
|
// v2.0.0-rc.38 UX-8 (C, user-authorized): cite-policy COMPLIANCE rate —
|
|
813
862
|
// the corrected G-CITE semantic. The legacy qualifying_cites/edits ratio
|
|
814
863
|
// measured "how often an applicable KB id existed" (a function of corpus
|
|
@@ -817,14 +866,14 @@ var citeCoverageReportSchema = z2.object({
|
|
|
817
866
|
// `KB: none [reason]` (the policy explicitly allows the none sentinel) —
|
|
818
867
|
// over the turns where a cite was expected. null when no cite-expected
|
|
819
868
|
// turns observed (avoids a misleading 0/0 → 0). Range [0,1].
|
|
820
|
-
cite_compliance_rate:
|
|
821
|
-
compliant_cites:
|
|
822
|
-
noncompliant_cites:
|
|
869
|
+
cite_compliance_rate: z3.number().min(0).max(1).nullable().optional(),
|
|
870
|
+
compliant_cites: z3.number().int().nonnegative().optional(),
|
|
871
|
+
noncompliant_cites: z3.number().int().nonnegative().optional(),
|
|
823
872
|
// Edit signals lacking session_id → uncorrelatable, silently excluded from
|
|
824
873
|
// expected_but_missed. >0 typically means a stale pre-session_id hook is
|
|
825
874
|
// installed (run `fabric install`). Surfaced so the denominator gap is
|
|
826
875
|
// visible rather than a silent 100% confound.
|
|
827
|
-
uncorrelatable_edits:
|
|
876
|
+
uncorrelatable_edits: z3.number().int().nonnegative().optional(),
|
|
828
877
|
// v2.1 ⑤ cite-redesign (P5): recall-based coverage口径. The redesign infers
|
|
829
878
|
// a citation from real behavior — an in-session fab_recall
|
|
830
879
|
// (knowledge_context_planned) whose target_paths overlap a subsequently
|
|
@@ -833,8 +882,8 @@ var citeCoverageReportSchema = z2.object({
|
|
|
833
882
|
// window) by such an overlapping recall. recall_coverage_rate =
|
|
834
883
|
// recall_backed_edits / edits_touched (null when no edits). Additive — the
|
|
835
884
|
// legacy first-line-`KB:` metrics above are unchanged (back-compat).
|
|
836
|
-
recall_backed_edits:
|
|
837
|
-
recall_coverage_rate:
|
|
885
|
+
recall_backed_edits: z3.number().int().nonnegative().optional(),
|
|
886
|
+
recall_coverage_rate: z3.number().min(0).max(1).nullable().optional(),
|
|
838
887
|
// v2.2.0-rc.1 W1-T3 (cite 诚实拆分 / lifecycle §3): exposed_and_mutated is a
|
|
839
888
|
// WEAK auxiliary signal — strictly SEPARATE from cite_compliance_rate (which
|
|
840
889
|
// is the true explicit-adherence rate, currently ~2.5%). It MUST NOT be
|
|
@@ -851,9 +900,9 @@ var citeCoverageReportSchema = z2.object({
|
|
|
851
900
|
// distinct (session_id, stable_id) pairs satisfying all three; `ids` =
|
|
852
901
|
// sorted distinct stable_ids (capped, diagnostics only). Always >= 0; null/
|
|
853
902
|
// absent on degraded/skipped reports.
|
|
854
|
-
exposed_and_mutated:
|
|
855
|
-
count:
|
|
856
|
-
ids:
|
|
903
|
+
exposed_and_mutated: z3.object({
|
|
904
|
+
count: z3.number().int().nonnegative(),
|
|
905
|
+
ids: z3.array(z3.string()).optional()
|
|
857
906
|
}).optional(),
|
|
858
907
|
// lifecycle-refactor W2-T4 (§5 row7 PostToolUse / §0 下沉 doctor): mutation
|
|
859
908
|
// funnel rebuilt offline from the new `file_mutated` PostToolUse marker —
|
|
@@ -864,8 +913,8 @@ var citeCoverageReportSchema = z2.object({
|
|
|
864
913
|
// PostToolUse parallel-fire race). Strictly ADDITIVE — never folded into
|
|
865
914
|
// cite_compliance_rate (honesty 铁律, mirrors exposed_and_mutated). Absent on
|
|
866
915
|
// degraded/skipped reports.
|
|
867
|
-
mutations_observed:
|
|
868
|
-
count:
|
|
916
|
+
mutations_observed: z3.object({
|
|
917
|
+
count: z3.number().int().nonnegative()
|
|
869
918
|
}).optional(),
|
|
870
919
|
// lifecycle-refactor W2-T4 (§5 row7 mutation_pool + downgrade): low-confidence
|
|
871
920
|
// mutation attribution pool. A `file_mutated` event is `attributed` ONLY when
|
|
@@ -878,41 +927,41 @@ var citeCoverageReportSchema = z2.object({
|
|
|
878
927
|
// (升 fallback via session shell event + baseline) is a SPECULATIVE
|
|
879
928
|
// implementation note — deliberately NOT run here (doctor stays read-only,
|
|
880
929
|
// no git diff / no disk write). Additive; absent on degraded/skipped reports.
|
|
881
|
-
mutation_pool:
|
|
882
|
-
attributed:
|
|
883
|
-
unattributed_workspace_dirty:
|
|
930
|
+
mutation_pool: z3.object({
|
|
931
|
+
attributed: z3.number().int().nonnegative(),
|
|
932
|
+
unattributed_workspace_dirty: z3.number().int().nonnegative()
|
|
884
933
|
}).optional(),
|
|
885
934
|
// lifecycle-refactor W2-T4 (§5 row2 SessionEnd funnel 对账下沉 doctor): the
|
|
886
935
|
// SessionEnd hook only O(1)-appends a `session_ended` marker; this counts the
|
|
887
936
|
// distinct sessions that emitted one (funnel "closed" boundary). Purely an
|
|
888
937
|
// observability marker — not joined into any rate. Additive.
|
|
889
|
-
sessions_closed:
|
|
890
|
-
count:
|
|
938
|
+
sessions_closed: z3.object({
|
|
939
|
+
count: z3.number().int().nonnegative()
|
|
891
940
|
}).optional()
|
|
892
941
|
}),
|
|
893
|
-
per_client:
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
edits_touched:
|
|
897
|
-
qualifying_cites:
|
|
898
|
-
recalled_unverified:
|
|
899
|
-
expected_but_missed:
|
|
900
|
-
total_turns:
|
|
942
|
+
per_client: z3.record(
|
|
943
|
+
z3.string(),
|
|
944
|
+
z3.object({
|
|
945
|
+
edits_touched: z3.number().int().nonnegative().optional(),
|
|
946
|
+
qualifying_cites: z3.number().int().nonnegative().optional(),
|
|
947
|
+
recalled_unverified: z3.number().int().nonnegative().optional(),
|
|
948
|
+
expected_but_missed: z3.number().int().nonnegative().optional(),
|
|
949
|
+
total_turns: z3.number().int().nonnegative().optional()
|
|
901
950
|
})
|
|
902
951
|
).optional(),
|
|
903
|
-
dismissed_reason_histogram:
|
|
904
|
-
none_reason_histogram:
|
|
952
|
+
dismissed_reason_histogram: z3.record(z3.string(), z3.number().int().nonnegative()).optional(),
|
|
953
|
+
none_reason_histogram: z3.record(z3.string(), z3.number().int().nonnegative()).optional(),
|
|
905
954
|
// v2.0.0-rc.24 TASK-08: contract-policy audit metrics. Status discriminates
|
|
906
955
|
// populated vs degraded modes. contract_metrics + per_layer_type are emitted
|
|
907
956
|
// (zeroed) in degraded modes so the renderer iterates one stable shape.
|
|
908
|
-
contract_metrics_status:
|
|
957
|
+
contract_metrics_status: z3.enum(["ok", "skipped:bootstrap_drift", "awaiting_marker"]).optional(),
|
|
909
958
|
contract_metrics: citeContractMetricsSchema.optional(),
|
|
910
959
|
per_layer_type: citeLayerTypeBreakdownSchema.optional(),
|
|
911
|
-
contract_marker_ts:
|
|
912
|
-
generated_at:
|
|
960
|
+
contract_marker_ts: z3.number().int().nonnegative().optional(),
|
|
961
|
+
generated_at: z3.string()
|
|
913
962
|
});
|
|
914
|
-
var ledgerSourceSchema =
|
|
915
|
-
var timestampFilterSchema =
|
|
963
|
+
var ledgerSourceSchema = z3.enum(["ai", "human"]);
|
|
964
|
+
var timestampFilterSchema = z3.preprocess((value) => {
|
|
916
965
|
if (value === void 0 || value === null || value === "") {
|
|
917
966
|
return void 0;
|
|
918
967
|
}
|
|
@@ -931,38 +980,38 @@ var timestampFilterSchema = z2.preprocess((value) => {
|
|
|
931
980
|
return Number.isNaN(parsed) ? value : parsed;
|
|
932
981
|
}
|
|
933
982
|
return value;
|
|
934
|
-
},
|
|
935
|
-
var ledgerQuerySchema =
|
|
983
|
+
}, z3.number().int().nonnegative());
|
|
984
|
+
var ledgerQuerySchema = z3.object({
|
|
936
985
|
source: ledgerSourceSchema.optional(),
|
|
937
986
|
since: timestampFilterSchema.optional()
|
|
938
987
|
});
|
|
939
|
-
var historyStateQuerySchema =
|
|
940
|
-
ledger_id:
|
|
988
|
+
var historyStateQuerySchema = z3.object({
|
|
989
|
+
ledger_id: z3.string().trim().min(1).optional(),
|
|
941
990
|
ts: timestampFilterSchema.optional()
|
|
942
991
|
}).superRefine((value, ctx) => {
|
|
943
992
|
const provided = [value.ledger_id, value.ts].filter((entry) => entry !== void 0);
|
|
944
993
|
if (provided.length !== 1) {
|
|
945
994
|
ctx.addIssue({
|
|
946
|
-
code:
|
|
995
|
+
code: z3.ZodIssueCode.custom,
|
|
947
996
|
message: "Provide exactly one of ledger_id or ts.",
|
|
948
997
|
path: ["ledger_id"]
|
|
949
998
|
});
|
|
950
999
|
}
|
|
951
1000
|
});
|
|
952
|
-
var humanLockApproveRequestSchema =
|
|
953
|
-
file:
|
|
954
|
-
start_line:
|
|
955
|
-
end_line:
|
|
956
|
-
new_hash:
|
|
1001
|
+
var humanLockApproveRequestSchema = z3.object({
|
|
1002
|
+
file: z3.string().min(1),
|
|
1003
|
+
start_line: z3.number().int().positive(),
|
|
1004
|
+
end_line: z3.number().int().positive(),
|
|
1005
|
+
new_hash: z3.string().min(1)
|
|
957
1006
|
});
|
|
958
|
-
var humanLockFileParamsSchema =
|
|
959
|
-
file:
|
|
1007
|
+
var humanLockFileParamsSchema = z3.object({
|
|
1008
|
+
file: z3.string().min(1)
|
|
960
1009
|
});
|
|
961
|
-
var annotateIntentRequestSchema =
|
|
962
|
-
ledger_entry_id:
|
|
963
|
-
annotation:
|
|
1010
|
+
var annotateIntentRequestSchema = z3.object({
|
|
1011
|
+
ledger_entry_id: z3.string().min(1),
|
|
1012
|
+
annotation: z3.string().trim().min(1)
|
|
964
1013
|
});
|
|
965
|
-
var KnowledgeTypeSchema =
|
|
1014
|
+
var KnowledgeTypeSchema = z3.enum([
|
|
966
1015
|
"models",
|
|
967
1016
|
// entities, data structures, relationships
|
|
968
1017
|
"decisions",
|
|
@@ -974,10 +1023,10 @@ var KnowledgeTypeSchema = z2.enum([
|
|
|
974
1023
|
"processes"
|
|
975
1024
|
// workflows, state machines, operational steps
|
|
976
1025
|
]);
|
|
977
|
-
var MaturitySchema =
|
|
978
|
-
var LayerSchema =
|
|
979
|
-
var StableIdSchema =
|
|
980
|
-
var KnowledgeEntryFrontmatterSchema =
|
|
1026
|
+
var MaturitySchema = z3.enum(["draft", "verified", "proven"]);
|
|
1027
|
+
var LayerSchema = z3.enum(["personal", "team"]);
|
|
1028
|
+
var StableIdSchema = z3.string().regex(/^K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/);
|
|
1029
|
+
var KnowledgeEntryFrontmatterSchema = z3.object({
|
|
981
1030
|
id: StableIdSchema,
|
|
982
1031
|
// e.g., "KT-DEC-0042"
|
|
983
1032
|
type: KnowledgeTypeSchema,
|
|
@@ -986,9 +1035,9 @@ var KnowledgeEntryFrontmatterSchema = z2.object({
|
|
|
986
1035
|
// draft | verified | proven
|
|
987
1036
|
layer: LayerSchema,
|
|
988
1037
|
// personal | team
|
|
989
|
-
layer_reason:
|
|
1038
|
+
layer_reason: z3.string().optional(),
|
|
990
1039
|
// why this layer (for ambiguous cases)
|
|
991
|
-
created_at:
|
|
1040
|
+
created_at: z3.string()
|
|
992
1041
|
// ISO 8601 timestamp
|
|
993
1042
|
// Note: 'tags' and other fields can be added later but core schema is these 6
|
|
994
1043
|
});
|
|
@@ -1019,6 +1068,13 @@ export {
|
|
|
1019
1068
|
ONBOARD_SLOT_NAMES,
|
|
1020
1069
|
onboardSlotSchema,
|
|
1021
1070
|
ONBOARD_SLOT_TOTAL,
|
|
1071
|
+
PERSONAL_SCOPE,
|
|
1072
|
+
KNOWN_SCOPE_PREFIXES,
|
|
1073
|
+
SCOPE_COORDINATE_PATTERN,
|
|
1074
|
+
scopeCoordinateSchema,
|
|
1075
|
+
scopeRoot,
|
|
1076
|
+
isPersonalScope,
|
|
1077
|
+
entryScopeMetadataSchema,
|
|
1022
1078
|
structuredWarningSchema,
|
|
1023
1079
|
planContextInputSchema,
|
|
1024
1080
|
planContextOutputSchema,
|
|
@@ -1035,7 +1091,7 @@ export {
|
|
|
1035
1091
|
archiveScanOutputSchema,
|
|
1036
1092
|
archiveScanAnnotations,
|
|
1037
1093
|
ProposedReasonSchema,
|
|
1038
|
-
|
|
1094
|
+
PROPOSED_REASON_DESCRIPTIONS_BY_LOCALE,
|
|
1039
1095
|
FabExtractKnowledgeInputSchema,
|
|
1040
1096
|
FabExtractKnowledgeInputShape,
|
|
1041
1097
|
FabExtractKnowledgeOutputSchema,
|