@fenglimg/fabric-shared 2.0.0-rc.22 → 2.0.0-rc.23
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-GDYPVGWT.js +671 -0
- package/dist/{chunk-VKCXD6CI.js → chunk-GYIALPMW.js} +21 -2
- package/dist/{chunk-BEABJYVL.js → chunk-IP6VWOVE.js} +6 -5
- package/dist/i18n/index.js +1 -1
- package/dist/index.d.ts +159 -9
- package/dist/index.js +70 -21
- package/dist/schemas/api-contracts.d.ts +270 -238
- package/dist/schemas/api-contracts.js +1 -7
- package/dist/templates/bootstrap-canonical.d.ts +1 -1
- package/dist/templates/bootstrap-canonical.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-WK4WINAZ.js +0 -633
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
// src/schemas/api-contracts.ts
|
|
2
|
+
import { z as z2 } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/onboard-slots.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var ONBOARD_SLOT_NAMES = [
|
|
7
|
+
"tech-stack-decision",
|
|
8
|
+
"architecture-pattern",
|
|
9
|
+
"code-style-tone",
|
|
10
|
+
"build-system-idiom",
|
|
11
|
+
"domain-vocabulary"
|
|
12
|
+
];
|
|
13
|
+
var onboardSlotSchema = z.enum(ONBOARD_SLOT_NAMES);
|
|
14
|
+
var ONBOARD_SLOT_TOTAL = ONBOARD_SLOT_NAMES.length;
|
|
15
|
+
|
|
16
|
+
// src/schemas/api-contracts.ts
|
|
17
|
+
var structuredWarningSchema = z2.object({
|
|
18
|
+
code: z2.string(),
|
|
19
|
+
file: z2.string(),
|
|
20
|
+
line: z2.number().optional(),
|
|
21
|
+
action_hint: z2.string()
|
|
22
|
+
});
|
|
23
|
+
var _knowledgeTypeEnum = z2.enum(["model", "decision", "guideline", "pitfall", "process"]);
|
|
24
|
+
var _maturityEnum = z2.enum(["draft", "verified", "proven"]);
|
|
25
|
+
var _layerEnum = z2.enum(["personal", "team"]);
|
|
26
|
+
var _ruleDescriptionSchema = z2.object({
|
|
27
|
+
summary: z2.string(),
|
|
28
|
+
intent_clues: z2.array(z2.string()),
|
|
29
|
+
tech_stack: z2.array(z2.string()),
|
|
30
|
+
impact: z2.array(z2.string()),
|
|
31
|
+
must_read_if: z2.string(),
|
|
32
|
+
entities: z2.array(z2.string()).optional(),
|
|
33
|
+
// v2.0: optional knowledge-entry fields. Absent for v1.x rules; present for
|
|
34
|
+
// entries that declare frontmatter `id/type/maturity/layer`.
|
|
35
|
+
id: z2.string().optional(),
|
|
36
|
+
knowledge_type: _knowledgeTypeEnum.optional(),
|
|
37
|
+
maturity: _maturityEnum.optional(),
|
|
38
|
+
knowledge_layer: _layerEnum.optional(),
|
|
39
|
+
layer_reason: z2.string().optional(),
|
|
40
|
+
created_at: z2.string().optional()
|
|
41
|
+
});
|
|
42
|
+
var _descriptionIndexItemSchema = z2.object({
|
|
43
|
+
stable_id: z2.string(),
|
|
44
|
+
level: z2.enum(["L0", "L1", "L2"]),
|
|
45
|
+
required: z2.boolean(),
|
|
46
|
+
selectable: z2.boolean(),
|
|
47
|
+
description: _ruleDescriptionSchema,
|
|
48
|
+
// v2.0: top-level knowledge surface for client-side filtering. Mirrors
|
|
49
|
+
// description.* — exposed here so MCP clients can filter without reaching
|
|
50
|
+
// into the nested payload.
|
|
51
|
+
type: _knowledgeTypeEnum.optional(),
|
|
52
|
+
maturity: _maturityEnum.optional(),
|
|
53
|
+
layer: _layerEnum.optional(),
|
|
54
|
+
layer_reason: z2.string().optional(),
|
|
55
|
+
// v2/rc.2: tag list shipped via frontmatter (commit a85121a). Exposed at
|
|
56
|
+
// the API surface so MCP clients can filter without re-parsing the
|
|
57
|
+
// description payload. Absent on legacy entries; consumers should treat
|
|
58
|
+
// missing as [].
|
|
59
|
+
tags: z2.array(z2.string()).optional(),
|
|
60
|
+
// v2.0-rc.5 (C1): relevance scope/paths drive plan-context-hint narrowing.
|
|
61
|
+
// Exposed at the API surface so MCP clients (and the `fabric
|
|
62
|
+
// plan-context-hint` CLI from D1) can filter without re-parsing the
|
|
63
|
+
// description payload. Defaults applied at the parse layer
|
|
64
|
+
// (knowledge-meta-builder + agentsMetaNodeBaseSchema):
|
|
65
|
+
// relevance_scope → 'broad' (always-surface, safe default)
|
|
66
|
+
// relevance_paths → [] (no path anchors)
|
|
67
|
+
// Consumers should treat missing fields as broad/[]. Optional on the wire
|
|
68
|
+
// so older servers without rc.5 schemas remain wire-compatible.
|
|
69
|
+
relevance_scope: z2.enum(["narrow", "broad"]).optional(),
|
|
70
|
+
relevance_paths: z2.array(z2.string()).optional()
|
|
71
|
+
});
|
|
72
|
+
var _requirementProfileSchema = z2.object({
|
|
73
|
+
target_path: z2.string(),
|
|
74
|
+
path_segments: z2.array(z2.string()),
|
|
75
|
+
extension: z2.string(),
|
|
76
|
+
known_tech: z2.array(z2.string()),
|
|
77
|
+
user_intent: z2.string(),
|
|
78
|
+
detected_entities: z2.array(z2.string())
|
|
79
|
+
});
|
|
80
|
+
var planContextInputSchema = z2.object({
|
|
81
|
+
paths: z2.array(z2.string()).min(1).describe("Candidate file paths to build neutral rule selection context for"),
|
|
82
|
+
intent: z2.string().optional().describe("User-stated requirement or implementation intent; used only to build a neutral requirement profile"),
|
|
83
|
+
known_tech: z2.array(z2.string()).optional().describe("Known technologies involved in the requirement profile"),
|
|
84
|
+
detected_entities: z2.record(z2.array(z2.string())).optional().describe("Optional path-keyed detected entities for the requirement profile"),
|
|
85
|
+
client_hash: z2.string().optional().describe("Revision hash from a prior fab_plan_context response; enables stale detection"),
|
|
86
|
+
correlation_id: z2.string().optional().describe("Optional caller-provided correlation id for Event Ledger records"),
|
|
87
|
+
session_id: z2.string().optional().describe("Optional caller-provided session id for Event Ledger records"),
|
|
88
|
+
// v2.0-rc.5 A3 (TASK-007): `include_deprecated` removed — it was a no-op
|
|
89
|
+
// placeholder (MaturitySchema has no `deprecated` value). When the maturity
|
|
90
|
+
// enum widens we re-introduce the flag as part of that protocol bump.
|
|
91
|
+
// v2/rc.2 (Q6): client-supplied layer scope. When omitted, the server
|
|
92
|
+
// falls back to fabric-config.default_layer_filter (TASK-002) so a single
|
|
93
|
+
// workspace policy controls the default. Explicit values override.
|
|
94
|
+
layer_filter: z2.enum(["team", "personal", "both"]).optional().describe(
|
|
95
|
+
"Restrict description_index to the named layer. Default: fabric-config.default_layer_filter (TASK-002)."
|
|
96
|
+
),
|
|
97
|
+
// v2.0-rc.5 C3 (TASK-012): explicit path context for `narrow` relevance
|
|
98
|
+
// filtering. When omitted, the server falls back to `paths` so existing
|
|
99
|
+
// callers see narrowing against the requested paths. When the resolved
|
|
100
|
+
// list is empty, the narrow filter fails open (every narrow entry passes).
|
|
101
|
+
target_paths: z2.array(z2.string()).optional().describe(
|
|
102
|
+
"Path context for narrow-scope relevance filtering. Defaults to `paths`; empty = no filter."
|
|
103
|
+
)
|
|
104
|
+
});
|
|
105
|
+
var planContextOutputSchema = z2.object({
|
|
106
|
+
revision_hash: z2.string(),
|
|
107
|
+
stale: z2.boolean(),
|
|
108
|
+
selection_token: z2.string(),
|
|
109
|
+
entries: z2.array(
|
|
110
|
+
z2.object({
|
|
111
|
+
path: z2.string(),
|
|
112
|
+
requirement_profile: _requirementProfileSchema,
|
|
113
|
+
description_index: z2.array(_descriptionIndexItemSchema)
|
|
114
|
+
})
|
|
115
|
+
),
|
|
116
|
+
shared: z2.object({
|
|
117
|
+
description_index: z2.array(_descriptionIndexItemSchema),
|
|
118
|
+
preflight_diagnostics: z2.array(
|
|
119
|
+
z2.object({
|
|
120
|
+
code: z2.literal("missing_description"),
|
|
121
|
+
severity: z2.literal("warn"),
|
|
122
|
+
message: z2.string(),
|
|
123
|
+
stable_ids: z2.array(z2.string()).optional(),
|
|
124
|
+
path: z2.string().optional()
|
|
125
|
+
})
|
|
126
|
+
)
|
|
127
|
+
}),
|
|
128
|
+
warnings: z2.array(structuredWarningSchema).optional(),
|
|
129
|
+
// v2.0.0-rc.22 Scope D T-D2: optional auto-heal banner fields. Surfaced
|
|
130
|
+
// ONLY when the loadActiveMetaOrStale call detected drift and rebuilt the
|
|
131
|
+
// meta in-place. Downstream CLI / hint renderers use this pair to render a
|
|
132
|
+
// "knowledge meta auto-healed (was <prev>, now <curr>)" notice without
|
|
133
|
+
// having to query the event ledger.
|
|
134
|
+
auto_healed: z2.boolean().optional(),
|
|
135
|
+
previous_revision_hash: z2.string().optional()
|
|
136
|
+
});
|
|
137
|
+
var planContextAnnotations = {
|
|
138
|
+
readOnlyHint: true,
|
|
139
|
+
idempotentHint: true,
|
|
140
|
+
destructiveHint: false,
|
|
141
|
+
openWorldHint: false,
|
|
142
|
+
title: "Plan rule context"
|
|
143
|
+
};
|
|
144
|
+
var planContextHintNarrowEntrySchema = z2.object({
|
|
145
|
+
id: z2.string(),
|
|
146
|
+
type: z2.string(),
|
|
147
|
+
maturity: z2.string(),
|
|
148
|
+
summary: z2.string()
|
|
149
|
+
});
|
|
150
|
+
var planContextHintOutputSchema = z2.object({
|
|
151
|
+
version: z2.literal(1),
|
|
152
|
+
revision_hash: z2.string(),
|
|
153
|
+
target_paths: z2.array(z2.string()),
|
|
154
|
+
narrow: z2.array(planContextHintNarrowEntrySchema),
|
|
155
|
+
broad_count: z2.number().int().nonnegative()
|
|
156
|
+
});
|
|
157
|
+
var knowledgeSectionsInputSchema = z2.object({
|
|
158
|
+
selection_token: z2.string().min(1).describe("Selection token returned by fab_plan_context"),
|
|
159
|
+
ai_selected_stable_ids: z2.array(z2.string()).describe(
|
|
160
|
+
"Stable ids picked from fab_plan_context entries[].description_index[].stable_id where selectable=true; choose 1..N to fetch bodies for"
|
|
161
|
+
),
|
|
162
|
+
ai_selection_reasons: z2.record(z2.string().min(1)).describe("Reason for each AI-selected L1 stable_id"),
|
|
163
|
+
correlation_id: z2.string().optional().describe("Optional caller-provided correlation id for Event Ledger records"),
|
|
164
|
+
session_id: z2.string().optional().describe("Optional caller-provided session id for Event Ledger records"),
|
|
165
|
+
// v2.0 rc.5 TASK-014 (C5): optional client identity hash propagated into
|
|
166
|
+
// knowledge_consumed events. Falls back to empty string when unset — full
|
|
167
|
+
// client-identity propagation deferred to rc.6.
|
|
168
|
+
client_hash: z2.string().optional().describe("Optional caller-provided client hash propagated into knowledge_consumed events")
|
|
169
|
+
});
|
|
170
|
+
var knowledgeSectionsOutputSchema = z2.object({
|
|
171
|
+
revision_hash: z2.string(),
|
|
172
|
+
/**
|
|
173
|
+
* @deprecated rc.23 TASK-002 F3 — removed in rc.24. The L0/L1/L2 selection
|
|
174
|
+
* ceremony was fully retired in rc.5 A3 (see comment above
|
|
175
|
+
* `planContextOutputSchema`); downstream consumers should use
|
|
176
|
+
* `rules[].level` directly. Kept as optional for one rc to avoid breaking
|
|
177
|
+
* pre-rc.23 clients that destructure this field.
|
|
178
|
+
*/
|
|
179
|
+
precedence: z2.tuple([z2.literal("L2"), z2.literal("L1"), z2.literal("L0")]).optional().describe(
|
|
180
|
+
"DEPRECATED (removed in rc.24): hardcoded L2/L1/L0 precedence tuple from the retired rc.5 selection ceremony. Use rules[].level instead."
|
|
181
|
+
),
|
|
182
|
+
selected_stable_ids: z2.array(z2.string()),
|
|
183
|
+
rules: z2.array(
|
|
184
|
+
z2.object({
|
|
185
|
+
stable_id: z2.string(),
|
|
186
|
+
level: z2.enum(["L0", "L1", "L2"]),
|
|
187
|
+
path: z2.string(),
|
|
188
|
+
// v2.0.0-rc.23 TASK-013 (F8b): replaced the legacy
|
|
189
|
+
// `sections: Record<string,string>` (keyed by the 4-element A-set enum)
|
|
190
|
+
// with the full markdown body (frontmatter stripped). Callers scan the
|
|
191
|
+
// body for whichever B-set heading they need (Summary / Why proposed /
|
|
192
|
+
// Session context / Evidence) — section-name discipline is now a writer
|
|
193
|
+
// convention, not an API contract.
|
|
194
|
+
body: z2.string()
|
|
195
|
+
})
|
|
196
|
+
),
|
|
197
|
+
diagnostics: z2.array(
|
|
198
|
+
// v2.0.0-rc.23 TASK-013 (F8b): `missing_section` was removed alongside the
|
|
199
|
+
// A-set enum. `missing_knowledge_metadata` stays as the warn-level signal
|
|
200
|
+
// for un-migrated v1.x entries (no knowledge_type AND no knowledge_layer
|
|
201
|
+
// in frontmatter). Does NOT block selection.
|
|
202
|
+
z2.object({
|
|
203
|
+
code: z2.literal("missing_knowledge_metadata"),
|
|
204
|
+
severity: z2.literal("warn"),
|
|
205
|
+
stable_id: z2.string(),
|
|
206
|
+
message: z2.string()
|
|
207
|
+
})
|
|
208
|
+
),
|
|
209
|
+
// v2/rc.3 (Q6): present iff a layer-flip in fab_review/modify changed the
|
|
210
|
+
// canonical stable_id since the caller's selection_token was minted.
|
|
211
|
+
// Clients should retry against `redirect_to.stable_id`.
|
|
212
|
+
redirect_to: z2.object({ stable_id: z2.string() }).optional().describe(
|
|
213
|
+
"Post-layer-flip redirect. Populated when stable_id changed after token mint (rc.3 fab_review/modify)."
|
|
214
|
+
),
|
|
215
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
216
|
+
});
|
|
217
|
+
var knowledgeSectionsAnnotations = {
|
|
218
|
+
readOnlyHint: true,
|
|
219
|
+
idempotentHint: true,
|
|
220
|
+
destructiveHint: false,
|
|
221
|
+
openWorldHint: false,
|
|
222
|
+
title: "Filter rule sections"
|
|
223
|
+
};
|
|
224
|
+
var ProposedReasonSchema = z2.enum([
|
|
225
|
+
"explicit-user-mark",
|
|
226
|
+
"diagnostic-then-fix",
|
|
227
|
+
"decision-confirmation",
|
|
228
|
+
"wrong-turn-revert",
|
|
229
|
+
"new-dependency-or-pattern",
|
|
230
|
+
"dismissal-with-reason"
|
|
231
|
+
]);
|
|
232
|
+
var PROPOSED_REASON_DESCRIPTIONS = {
|
|
233
|
+
"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",
|
|
234
|
+
"diagnostic-then-fix": "\u8BCA\u65AD\u8FC7\u7A0B\u53D1\u73B0\u65B0\u6A21\u5F0F\u6216\u8E29\u5751\uFF0C\u4FEE\u590D\u540E\u503C\u5F97\u6C89\u6DC0\u3002",
|
|
235
|
+
"decision-confirmation": "\u22652 \u5019\u9009\u65B9\u6848\u7ECF\u6743\u8861\u540E\u786E\u8BA4\u9009\u578B\uFF0C\u9700\u4FDD\u7559 rationale\u3002",
|
|
236
|
+
"wrong-turn-revert": "\u5C1D\u8BD5\u67D0\u8DEF\u5F84\u540E\u56DE\u9000\uFF0C\u9519\u8BEF\u8DEF\u5F84\u672C\u8EAB\u662F\u503C\u5F97\u8BB0\u5F55\u7684 pitfall\u3002",
|
|
237
|
+
"new-dependency-or-pattern": "\u5F15\u5165\u65B0\u4F9D\u8D56 / \u65B0\u6A21\u5F0F / \u65B0\u547D\u540D\u7EA6\u5B9A\u3002",
|
|
238
|
+
"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"
|
|
239
|
+
};
|
|
240
|
+
var _sourceSessionsField = z2.array(z2.string().min(1)).min(1);
|
|
241
|
+
var _FabExtractKnowledgeInputBaseSchema = z2.object({
|
|
242
|
+
// v2.0.0-rc.7 T5: array form. rc.23 dropped the legacy single-string alias.
|
|
243
|
+
source_sessions: _sourceSessionsField.optional().describe(
|
|
244
|
+
"Originating session ids; correlates with Event Ledger records. Array form (T5+, rc.23 made it the sole accepted shape)."
|
|
245
|
+
),
|
|
246
|
+
recent_paths: z2.array(z2.string()).describe("Workspace paths recently touched in the source session \u2014 used as scope hints"),
|
|
247
|
+
user_messages_summary: z2.string().describe("Skill-side summary of the user's intent/messages, kept compact"),
|
|
248
|
+
type: z2.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]).describe("Knowledge type bucket (plural form, mirrors directory layout)"),
|
|
249
|
+
slug: z2.string().describe("URL-safe short identifier proposed by the Skill; server may sanitize"),
|
|
250
|
+
// rc.5 B1: dual pending root. When 'personal', the server writes to
|
|
251
|
+
// ~/.fabric/knowledge/pending/<type>/; otherwise to .fabric/knowledge/pending/<type>/.
|
|
252
|
+
// Defaults to 'team' to preserve existing call sites (Skill bumps as needed).
|
|
253
|
+
layer: z2.enum(["team", "personal"]).optional().describe(
|
|
254
|
+
"Storage layer for the pending entry. 'team' writes under the workspace; 'personal' writes under the user's home. Defaults to 'team'."
|
|
255
|
+
),
|
|
256
|
+
// v2.0.0-rc.7 T6: proposed_reason — required enum that drives `## Why
|
|
257
|
+
// proposed` rendering. Skills (archive / import / review) infer the
|
|
258
|
+
// appropriate reason per their semantics (see each SKILL.md).
|
|
259
|
+
proposed_reason: ProposedReasonSchema.describe(
|
|
260
|
+
"Why this entry is being proposed. Drives `## Why proposed` rendering and enables future maturity-promotion scoring."
|
|
261
|
+
),
|
|
262
|
+
// v2.0.0-rc.7 T6: session_context — required 3-5 line markdown blob that
|
|
263
|
+
// captures the session goal + key turning point. Future-self review reads
|
|
264
|
+
// this without conversation transcript access. Min length guards against
|
|
265
|
+
// empty placeholders; cap is soft (no max), Skill caps at ~600 chars.
|
|
266
|
+
session_context: z2.string().min(20, { message: "session_context must be \u226520 chars (3-5 lines describing goal + turning point)" }).describe(
|
|
267
|
+
"3-5 line markdown blob \u2014 session goal + key turning point. Reviewed by future-self without transcript access."
|
|
268
|
+
),
|
|
269
|
+
// v2.0.0-rc.8 A1 (skill-contract-fix): relevance scope/paths on the
|
|
270
|
+
// creation surface. Mirrors `_fabReviewModifyChangesSchema.relevance_*`
|
|
271
|
+
// (L518-533) verbatim so callers can declare scope at archive time
|
|
272
|
+
// instead of waiting for a fab_review.modify follow-up. Both fields are
|
|
273
|
+
// optional — when omitted, the pending file omits the YAML lines entirely
|
|
274
|
+
// (knowledge-meta-builder defaults to broad + [] at parse time, see
|
|
275
|
+
// L1007-1021). Personal + narrow is silently degraded to broad + [] at
|
|
276
|
+
// service entry, mirroring the rc.5 review.ts:725-739 behaviour, and emits
|
|
277
|
+
// a `knowledge_scope_degraded` event keyed by `pending:<idempotency_key>`.
|
|
278
|
+
// NOTE: these fields MUST NOT be part of the idempotency hash inputs at
|
|
279
|
+
// extract-knowledge.ts:78 — preserves rc.5→rc.7 collision detection.
|
|
280
|
+
relevance_scope: z2.enum(["narrow", "broad"]).optional().describe(
|
|
281
|
+
"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 + []."
|
|
282
|
+
),
|
|
283
|
+
relevance_paths: z2.array(z2.string()).optional().describe(
|
|
284
|
+
"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)."
|
|
285
|
+
),
|
|
286
|
+
// v2.0.0-rc.23 TASK-006 (a-C1): four optional structured fields that the
|
|
287
|
+
// skill-side LLM populates from raw observations. The same information
|
|
288
|
+
// historically lived only in `## Session context` prose, forcing future-self
|
|
289
|
+
// reviewers / plan-context retrievers to re-read the entire body to decide
|
|
290
|
+
// relevance. Lifting them into structured frontmatter lets downstream
|
|
291
|
+
// surfaces (description_index, scoring, relevance triage) consume them
|
|
292
|
+
// directly. ALL FOUR ARE STRICTLY OPTIONAL — skills that cannot infer them
|
|
293
|
+
// confidently must omit, not guess.
|
|
294
|
+
//
|
|
295
|
+
// IMPORTANT: these fields MUST NOT participate in the idempotency_key hash
|
|
296
|
+
// (see rc.8 A1 convention at extract-knowledge.ts — relevance_scope /
|
|
297
|
+
// relevance_paths follow the same rule). Including them would let an LLM
|
|
298
|
+
// re-roll of the same observation create a second pending file just because
|
|
299
|
+
// its inferred metadata wording drifted.
|
|
300
|
+
intent_clues: z2.array(z2.string()).optional().describe(
|
|
301
|
+
"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."
|
|
302
|
+
),
|
|
303
|
+
tech_stack: z2.array(z2.string()).optional().describe(
|
|
304
|
+
"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."
|
|
305
|
+
),
|
|
306
|
+
impact: z2.array(z2.string()).optional().describe(
|
|
307
|
+
"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."
|
|
308
|
+
),
|
|
309
|
+
must_read_if: z2.string().optional().describe(
|
|
310
|
+
"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."
|
|
311
|
+
),
|
|
312
|
+
// v2.0.0-rc.23 TASK-014 (F8c): optional onboard-slot tag. The S5 slot
|
|
313
|
+
// mechanism reintroduces a Skill-orchestrated "project tone" capture
|
|
314
|
+
// surface after F8a deleted the auto-`fab scan` baseline pipeline.
|
|
315
|
+
// fabric-archive's first-run phase reads `fab onboard-coverage` to
|
|
316
|
+
// discover unclaimed slots, then propagates the chosen slot label here
|
|
317
|
+
// so the resulting pending entry counts toward coverage.
|
|
318
|
+
//
|
|
319
|
+
// STRICT optionality: every non-onboard fab_extract_knowledge call MUST
|
|
320
|
+
// omit this field. The skill is the only producer; downstream consumers
|
|
321
|
+
// (plan_context retrieval, doctor lints) treat missing as a steady-state
|
|
322
|
+
// signal that the entry was NOT part of an onboard pass.
|
|
323
|
+
//
|
|
324
|
+
// IDEMPOTENCY: like the four a-C1 fields and the rc.8 A1 relevance pair,
|
|
325
|
+
// `onboard_slot` MUST NOT participate in the idempotency_key hash at
|
|
326
|
+
// extract-knowledge.ts:100-106. An LLM that re-rolls the same observation
|
|
327
|
+
// with a different (or absent) slot must still collapse onto the same
|
|
328
|
+
// pending file — otherwise the slot mechanic itself could spawn
|
|
329
|
+
// duplicate entries.
|
|
330
|
+
onboard_slot: onboardSlotSchema.optional().describe(
|
|
331
|
+
"Optional slot tag from the S5 onboarding set (tech-stack-decision / architecture-pattern / code-style-tone / build-system-idiom / domain-vocabulary); lets fabric-archive's first-run phase claim a project-tone slot. Skill propose-time only; never required."
|
|
332
|
+
)
|
|
333
|
+
});
|
|
334
|
+
var FabExtractKnowledgeInputSchema = _FabExtractKnowledgeInputBaseSchema.superRefine(
|
|
335
|
+
(value, ctx) => {
|
|
336
|
+
const hasArray = Array.isArray(value.source_sessions) && value.source_sessions.length > 0;
|
|
337
|
+
if (!hasArray) {
|
|
338
|
+
ctx.addIssue({
|
|
339
|
+
code: z2.ZodIssueCode.custom,
|
|
340
|
+
message: "source_sessions (non-empty string array) is required",
|
|
341
|
+
path: ["source_sessions"]
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
var FabExtractKnowledgeInputShape = _FabExtractKnowledgeInputBaseSchema.shape;
|
|
347
|
+
var FabExtractKnowledgeOutputSchema = z2.object({
|
|
348
|
+
pending_path: z2.string().describe("Workspace-relative path to the persisted pending entry"),
|
|
349
|
+
idempotency_key: z2.string().describe("Stable key derived from inputs; identical inputs yield identical key"),
|
|
350
|
+
// v2.0.0-rc.23 TASK-009 (d): optional warnings surface for the first-reconcile
|
|
351
|
+
// gate (`meta_stale` / `reconcile_failed`). Absent on the steady-state path.
|
|
352
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
353
|
+
});
|
|
354
|
+
var fabExtractKnowledgeAnnotations = {
|
|
355
|
+
readOnlyHint: false,
|
|
356
|
+
idempotentHint: true,
|
|
357
|
+
destructiveHint: false,
|
|
358
|
+
openWorldHint: false,
|
|
359
|
+
title: "Extract pending knowledge entry"
|
|
360
|
+
};
|
|
361
|
+
var _fabReviewFiltersSchema = z2.object({
|
|
362
|
+
type: z2.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]).optional(),
|
|
363
|
+
layer: z2.enum(["team", "personal", "both"]).optional(),
|
|
364
|
+
maturity: z2.enum(["draft", "verified", "proven"]).optional(),
|
|
365
|
+
tags: z2.array(z2.string()).optional(),
|
|
366
|
+
// rc.4 TASK-006 fix (c): ISO-8601 lower bound on entry created_at; entries
|
|
367
|
+
// strictly older than this threshold are excluded from list / search
|
|
368
|
+
// results. Additive optional field — existing callers unaffected.
|
|
369
|
+
created_after: z2.string().datetime().optional()
|
|
370
|
+
}).optional();
|
|
371
|
+
var _fabReviewModifyChangesSchema = z2.object({
|
|
372
|
+
title: z2.string().optional(),
|
|
373
|
+
summary: z2.string().optional(),
|
|
374
|
+
// Q7: writing `layer` here triggers a layer-flip; downstream callers may
|
|
375
|
+
// observe a redirect_to in fab_get_knowledge_sections if stable_id changes.
|
|
376
|
+
layer: z2.enum(["team", "personal"]).optional(),
|
|
377
|
+
maturity: z2.enum(["draft", "verified", "proven"]).optional(),
|
|
378
|
+
tags: z2.array(z2.string()).optional(),
|
|
379
|
+
// v2.0-rc.5 C3 (TASK-012): relevance scope/paths patches. Applied to
|
|
380
|
+
// pending AND canonical entries. When an explicit team→personal layer flip
|
|
381
|
+
// arrives on a narrow entry, the server auto-degrades to broad + [] and
|
|
382
|
+
// emits a `knowledge_scope_degraded` event regardless of what the caller
|
|
383
|
+
// sent in these fields (personal-implies-broad).
|
|
384
|
+
relevance_scope: z2.enum(["narrow", "broad"]).optional(),
|
|
385
|
+
relevance_paths: z2.array(z2.string()).optional()
|
|
386
|
+
});
|
|
387
|
+
var FabReviewInputSchema = z2.discriminatedUnion("action", [
|
|
388
|
+
z2.object({
|
|
389
|
+
action: z2.literal("list"),
|
|
390
|
+
filters: _fabReviewFiltersSchema
|
|
391
|
+
}),
|
|
392
|
+
z2.object({
|
|
393
|
+
action: z2.literal("approve"),
|
|
394
|
+
pending_paths: z2.array(z2.string()).min(1)
|
|
395
|
+
}),
|
|
396
|
+
z2.object({
|
|
397
|
+
action: z2.literal("reject"),
|
|
398
|
+
pending_paths: z2.array(z2.string()).min(1),
|
|
399
|
+
reason: z2.string().min(1)
|
|
400
|
+
}),
|
|
401
|
+
z2.object({
|
|
402
|
+
action: z2.literal("modify"),
|
|
403
|
+
pending_path: z2.string().min(1),
|
|
404
|
+
changes: _fabReviewModifyChangesSchema
|
|
405
|
+
}),
|
|
406
|
+
z2.object({
|
|
407
|
+
action: z2.literal("search"),
|
|
408
|
+
query: z2.string().min(1),
|
|
409
|
+
filters: _fabReviewFiltersSchema
|
|
410
|
+
}),
|
|
411
|
+
z2.object({
|
|
412
|
+
action: z2.literal("defer"),
|
|
413
|
+
pending_paths: z2.array(z2.string()).min(1),
|
|
414
|
+
until: z2.string().datetime().optional(),
|
|
415
|
+
reason: z2.string().optional()
|
|
416
|
+
})
|
|
417
|
+
]);
|
|
418
|
+
var FabReviewInputShape = {
|
|
419
|
+
action: z2.enum(["list", "approve", "reject", "modify", "search", "defer"]).describe(
|
|
420
|
+
"Action selector. Discriminates the per-action fields below; required."
|
|
421
|
+
),
|
|
422
|
+
filters: _fabReviewFiltersSchema.describe(
|
|
423
|
+
"Optional filters (type/layer/maturity/tags/created_after). Used by action=list and action=search."
|
|
424
|
+
),
|
|
425
|
+
pending_paths: z2.array(z2.string()).min(1).optional().describe(
|
|
426
|
+
"Workspace-relative pending entry paths. Required when action=approve|reject|defer (non-empty array)."
|
|
427
|
+
),
|
|
428
|
+
pending_path: z2.string().min(1).optional().describe(
|
|
429
|
+
"Workspace-relative pending OR canonical entry path. Required when action=modify."
|
|
430
|
+
),
|
|
431
|
+
reason: z2.string().optional().describe(
|
|
432
|
+
"Reason string. Required (non-empty) when action=reject; optional when action=defer."
|
|
433
|
+
),
|
|
434
|
+
changes: _fabReviewModifyChangesSchema.optional().describe(
|
|
435
|
+
"Frontmatter scalar patches (title/summary/layer/maturity/tags/relevance_*). Required when action=modify."
|
|
436
|
+
),
|
|
437
|
+
query: z2.string().min(1).optional().describe(
|
|
438
|
+
"Substring query against title/summary/tags/path. Required (non-empty) when action=search."
|
|
439
|
+
),
|
|
440
|
+
until: z2.string().datetime().optional().describe(
|
|
441
|
+
"ISO-8601 datetime upper bound for the deferral. Optional; used only when action=defer."
|
|
442
|
+
)
|
|
443
|
+
};
|
|
444
|
+
var _fabReviewListItemSchema = z2.object({
|
|
445
|
+
pending_path: z2.string(),
|
|
446
|
+
type: z2.enum(["decisions", "pitfalls", "guidelines", "models", "processes"]),
|
|
447
|
+
layer: z2.enum(["team", "personal"]),
|
|
448
|
+
maturity: z2.enum(["draft", "verified", "proven"]),
|
|
449
|
+
tags: z2.array(z2.string()).optional(),
|
|
450
|
+
title: z2.string().optional(),
|
|
451
|
+
summary: z2.string().optional(),
|
|
452
|
+
// rc.5 B1: dual pending root. 'team' = workspace .fabric/knowledge/pending,
|
|
453
|
+
// 'personal' = ~/.fabric/knowledge/pending. Distinct from `layer` (frontmatter):
|
|
454
|
+
// origin reflects where the pending file actually lives on disk; layer reflects
|
|
455
|
+
// the declared classification that will drive the approve destination.
|
|
456
|
+
origin: z2.enum(["team", "personal"]).optional()
|
|
457
|
+
});
|
|
458
|
+
var FabReviewOutputSchema = z2.discriminatedUnion("action", [
|
|
459
|
+
z2.object({
|
|
460
|
+
action: z2.literal("list"),
|
|
461
|
+
items: z2.array(_fabReviewListItemSchema),
|
|
462
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
463
|
+
}),
|
|
464
|
+
z2.object({
|
|
465
|
+
action: z2.literal("approve"),
|
|
466
|
+
approved: z2.array(z2.object({ pending_path: z2.string(), stable_id: z2.string() })),
|
|
467
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
468
|
+
}),
|
|
469
|
+
z2.object({
|
|
470
|
+
action: z2.literal("reject"),
|
|
471
|
+
rejected: z2.array(z2.string()),
|
|
472
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
473
|
+
}),
|
|
474
|
+
z2.object({
|
|
475
|
+
action: z2.literal("modify"),
|
|
476
|
+
pending_path: z2.string(),
|
|
477
|
+
// When a layer-flip occurred, prior_stable_id and new_stable_id differ.
|
|
478
|
+
prior_stable_id: z2.string().optional(),
|
|
479
|
+
new_stable_id: z2.string().optional(),
|
|
480
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
481
|
+
}),
|
|
482
|
+
z2.object({
|
|
483
|
+
action: z2.literal("search"),
|
|
484
|
+
items: z2.array(_fabReviewListItemSchema),
|
|
485
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
486
|
+
}),
|
|
487
|
+
z2.object({
|
|
488
|
+
action: z2.literal("defer"),
|
|
489
|
+
deferred: z2.array(z2.string()),
|
|
490
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
491
|
+
})
|
|
492
|
+
]);
|
|
493
|
+
var FabReviewOutputShape = {
|
|
494
|
+
action: z2.enum(["list", "approve", "reject", "modify", "search", "defer"]).describe(
|
|
495
|
+
"Echoes the input action; clients can switch on it for per-variant fields below."
|
|
496
|
+
),
|
|
497
|
+
items: z2.array(_fabReviewListItemSchema).optional().describe(
|
|
498
|
+
"Pending/canonical entries surfaced. Present when action=list or action=search."
|
|
499
|
+
),
|
|
500
|
+
approved: z2.array(z2.object({ pending_path: z2.string(), stable_id: z2.string() })).optional().describe(
|
|
501
|
+
"Allocated stable ids paired with their original pending paths. Present when action=approve."
|
|
502
|
+
),
|
|
503
|
+
rejected: z2.array(z2.string()).optional().describe(
|
|
504
|
+
"Pending paths that were rejected (files retained on disk; doctor owns vacuum). Present when action=reject."
|
|
505
|
+
),
|
|
506
|
+
pending_path: z2.string().optional().describe(
|
|
507
|
+
"Echoed target path for the modification. Present when action=modify."
|
|
508
|
+
),
|
|
509
|
+
prior_stable_id: z2.string().optional().describe(
|
|
510
|
+
"Prior stable id. Present when action=modify AND a layer-flip reallocated the id."
|
|
511
|
+
),
|
|
512
|
+
new_stable_id: z2.string().optional().describe(
|
|
513
|
+
"New stable id after reallocation. Present when action=modify AND a layer-flip reallocated the id."
|
|
514
|
+
),
|
|
515
|
+
deferred: z2.array(z2.string()).optional().describe(
|
|
516
|
+
"Pending paths that were deferred (files retained on disk). Present when action=defer."
|
|
517
|
+
),
|
|
518
|
+
// v2.0.0-rc.23 TASK-009 (d): optional warnings surface for the first-reconcile
|
|
519
|
+
// gate (`meta_stale` / `reconcile_failed`). Absent on the steady-state path.
|
|
520
|
+
warnings: z2.array(structuredWarningSchema).optional()
|
|
521
|
+
};
|
|
522
|
+
var fabReviewAnnotations = {
|
|
523
|
+
readOnlyHint: false,
|
|
524
|
+
idempotentHint: false,
|
|
525
|
+
destructiveHint: false,
|
|
526
|
+
openWorldHint: false,
|
|
527
|
+
title: "Review pending knowledge entries"
|
|
528
|
+
};
|
|
529
|
+
var ledgerSourceSchema = z2.enum(["ai", "human"]);
|
|
530
|
+
var timestampFilterSchema = z2.preprocess((value) => {
|
|
531
|
+
if (value === void 0 || value === null || value === "") {
|
|
532
|
+
return void 0;
|
|
533
|
+
}
|
|
534
|
+
if (typeof value === "number") {
|
|
535
|
+
return value;
|
|
536
|
+
}
|
|
537
|
+
if (typeof value === "string") {
|
|
538
|
+
const trimmed = value.trim();
|
|
539
|
+
if (trimmed.length === 0) {
|
|
540
|
+
return void 0;
|
|
541
|
+
}
|
|
542
|
+
if (/^\d+$/.test(trimmed)) {
|
|
543
|
+
return Number.parseInt(trimmed, 10);
|
|
544
|
+
}
|
|
545
|
+
const parsed = Date.parse(trimmed);
|
|
546
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
547
|
+
}
|
|
548
|
+
return value;
|
|
549
|
+
}, z2.number().int().nonnegative());
|
|
550
|
+
var ledgerQuerySchema = z2.object({
|
|
551
|
+
source: ledgerSourceSchema.optional(),
|
|
552
|
+
since: timestampFilterSchema.optional()
|
|
553
|
+
});
|
|
554
|
+
var historyStateQuerySchema = z2.object({
|
|
555
|
+
ledger_id: z2.string().trim().min(1).optional(),
|
|
556
|
+
ts: timestampFilterSchema.optional()
|
|
557
|
+
}).superRefine((value, ctx) => {
|
|
558
|
+
const provided = [value.ledger_id, value.ts].filter((entry) => entry !== void 0);
|
|
559
|
+
if (provided.length !== 1) {
|
|
560
|
+
ctx.addIssue({
|
|
561
|
+
code: z2.ZodIssueCode.custom,
|
|
562
|
+
message: "Provide exactly one of ledger_id or ts.",
|
|
563
|
+
path: ["ledger_id"]
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
var humanLockApproveRequestSchema = z2.object({
|
|
568
|
+
file: z2.string().min(1),
|
|
569
|
+
start_line: z2.number().int().positive(),
|
|
570
|
+
end_line: z2.number().int().positive(),
|
|
571
|
+
new_hash: z2.string().min(1)
|
|
572
|
+
});
|
|
573
|
+
var humanLockFileParamsSchema = z2.object({
|
|
574
|
+
file: z2.string().min(1)
|
|
575
|
+
});
|
|
576
|
+
var annotateIntentRequestSchema = z2.object({
|
|
577
|
+
ledger_entry_id: z2.string().min(1),
|
|
578
|
+
annotation: z2.string().trim().min(1)
|
|
579
|
+
});
|
|
580
|
+
var KnowledgeTypeSchema = z2.enum([
|
|
581
|
+
"model",
|
|
582
|
+
// entities, data structures, relationships
|
|
583
|
+
"decision",
|
|
584
|
+
// architectural/technical choices with rationale
|
|
585
|
+
"guideline",
|
|
586
|
+
// recommended practices (recommend) or anti-patterns (avoid)
|
|
587
|
+
"pitfall",
|
|
588
|
+
// known risks, failure modes, troubleshooting
|
|
589
|
+
"process"
|
|
590
|
+
// workflows, state machines, operational steps
|
|
591
|
+
]);
|
|
592
|
+
var MaturitySchema = z2.enum(["draft", "verified", "proven"]);
|
|
593
|
+
var LayerSchema = z2.enum(["personal", "team"]);
|
|
594
|
+
var StableIdSchema = z2.string().regex(/^K[PT]-(MOD|DEC|GLD|PIT|PRO)-\d{4,}$/);
|
|
595
|
+
var KnowledgeEntryFrontmatterSchema = z2.object({
|
|
596
|
+
id: StableIdSchema,
|
|
597
|
+
// e.g., "KT-DEC-0042"
|
|
598
|
+
type: KnowledgeTypeSchema,
|
|
599
|
+
// one of 5 types
|
|
600
|
+
maturity: MaturitySchema,
|
|
601
|
+
// draft | verified | proven
|
|
602
|
+
layer: LayerSchema,
|
|
603
|
+
// personal | team
|
|
604
|
+
layer_reason: z2.string().optional(),
|
|
605
|
+
// why this layer (for ambiguous cases)
|
|
606
|
+
created_at: z2.string()
|
|
607
|
+
// ISO 8601 timestamp
|
|
608
|
+
// Note: 'tags' and other fields can be added later but core schema is these 6
|
|
609
|
+
});
|
|
610
|
+
var KNOWLEDGE_TYPE_CODES = {
|
|
611
|
+
model: "MOD",
|
|
612
|
+
decision: "DEC",
|
|
613
|
+
guideline: "GLD",
|
|
614
|
+
pitfall: "PIT",
|
|
615
|
+
process: "PRO"
|
|
616
|
+
};
|
|
617
|
+
function formatKnowledgeId(layer, type, counter) {
|
|
618
|
+
const layerPrefix = layer === "personal" ? "KP" : "KT";
|
|
619
|
+
const typeCode = KNOWLEDGE_TYPE_CODES[type];
|
|
620
|
+
return `${layerPrefix}-${typeCode}-${String(counter).padStart(4, "0")}`;
|
|
621
|
+
}
|
|
622
|
+
function parseKnowledgeId(id) {
|
|
623
|
+
const match = id.match(/^(KP|KT)-(MOD|DEC|GLD|PIT|PRO)-(\d+)$/);
|
|
624
|
+
if (!match) return null;
|
|
625
|
+
const layer = match[1] === "KP" ? "personal" : "team";
|
|
626
|
+
const typeCode = match[2];
|
|
627
|
+
const entry = Object.entries(KNOWLEDGE_TYPE_CODES).find(([, code]) => code === typeCode);
|
|
628
|
+
if (!entry) return null;
|
|
629
|
+
const type = entry[0];
|
|
630
|
+
return { layer, type, counter: parseInt(match[3], 10) };
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export {
|
|
634
|
+
ONBOARD_SLOT_NAMES,
|
|
635
|
+
onboardSlotSchema,
|
|
636
|
+
ONBOARD_SLOT_TOTAL,
|
|
637
|
+
structuredWarningSchema,
|
|
638
|
+
planContextInputSchema,
|
|
639
|
+
planContextOutputSchema,
|
|
640
|
+
planContextAnnotations,
|
|
641
|
+
planContextHintNarrowEntrySchema,
|
|
642
|
+
planContextHintOutputSchema,
|
|
643
|
+
knowledgeSectionsInputSchema,
|
|
644
|
+
knowledgeSectionsOutputSchema,
|
|
645
|
+
knowledgeSectionsAnnotations,
|
|
646
|
+
ProposedReasonSchema,
|
|
647
|
+
PROPOSED_REASON_DESCRIPTIONS,
|
|
648
|
+
FabExtractKnowledgeInputSchema,
|
|
649
|
+
FabExtractKnowledgeInputShape,
|
|
650
|
+
FabExtractKnowledgeOutputSchema,
|
|
651
|
+
fabExtractKnowledgeAnnotations,
|
|
652
|
+
FabReviewInputSchema,
|
|
653
|
+
FabReviewInputShape,
|
|
654
|
+
FabReviewOutputSchema,
|
|
655
|
+
FabReviewOutputShape,
|
|
656
|
+
fabReviewAnnotations,
|
|
657
|
+
ledgerSourceSchema,
|
|
658
|
+
ledgerQuerySchema,
|
|
659
|
+
historyStateQuerySchema,
|
|
660
|
+
humanLockApproveRequestSchema,
|
|
661
|
+
humanLockFileParamsSchema,
|
|
662
|
+
annotateIntentRequestSchema,
|
|
663
|
+
KnowledgeTypeSchema,
|
|
664
|
+
MaturitySchema,
|
|
665
|
+
LayerSchema,
|
|
666
|
+
StableIdSchema,
|
|
667
|
+
KnowledgeEntryFrontmatterSchema,
|
|
668
|
+
KNOWLEDGE_TYPE_CODES,
|
|
669
|
+
formatKnowledgeId,
|
|
670
|
+
parseKnowledgeId
|
|
671
|
+
};
|