@rasensio/aidlc 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/add-action.d.ts.map +1 -1
- package/dist/commands/add-action.js +2 -3
- package/dist/commands/add-action.js.map +1 -1
- package/dist/commands/add-skill.d.ts +28 -0
- package/dist/commands/add-skill.d.ts.map +1 -0
- package/dist/commands/add-skill.js +315 -0
- package/dist/commands/add-skill.js.map +1 -0
- package/dist/commands/add.d.ts +25 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +29 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +1 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/compile/adapters/claude-code.d.ts.map +1 -1
- package/dist/compile/adapters/claude-code.js +3 -24
- package/dist/compile/adapters/claude-code.js.map +1 -1
- package/dist/compile/adapters/codex.d.ts.map +1 -1
- package/dist/compile/adapters/codex.js +3 -2
- package/dist/compile/adapters/codex.js.map +1 -1
- package/dist/compile/adapters/cursor.d.ts.map +1 -1
- package/dist/compile/adapters/cursor.js +4 -2
- package/dist/compile/adapters/cursor.js.map +1 -1
- package/dist/compile/adapters/kiro.d.ts.map +1 -1
- package/dist/compile/adapters/kiro.js +6 -10
- package/dist/compile/adapters/kiro.js.map +1 -1
- package/dist/compile/adapters/windsurf.d.ts.map +1 -1
- package/dist/compile/adapters/windsurf.js +9 -11
- package/dist/compile/adapters/windsurf.js.map +1 -1
- package/dist/compile/content-root.d.ts +22 -0
- package/dist/compile/content-root.d.ts.map +1 -0
- package/dist/compile/content-root.js +28 -0
- package/dist/compile/content-root.js.map +1 -0
- package/dist/compile/limits.d.ts +20 -0
- package/dist/compile/limits.d.ts.map +1 -0
- package/dist/compile/limits.js +20 -0
- package/dist/compile/limits.js.map +1 -0
- package/dist/compile/naming.d.ts +92 -0
- package/dist/compile/naming.d.ts.map +1 -0
- package/dist/compile/naming.js +105 -0
- package/dist/compile/naming.js.map +1 -0
- package/dist/operational/discover.d.ts +89 -0
- package/dist/operational/discover.d.ts.map +1 -0
- package/dist/operational/discover.js +132 -0
- package/dist/operational/discover.js.map +1 -0
- package/dist/operational/emit.d.ts +93 -0
- package/dist/operational/emit.d.ts.map +1 -0
- package/dist/operational/emit.js +227 -0
- package/dist/operational/emit.js.map +1 -0
- package/dist/operational/knowledge.d.ts +64 -0
- package/dist/operational/knowledge.d.ts.map +1 -0
- package/dist/operational/knowledge.js +144 -0
- package/dist/operational/knowledge.js.map +1 -0
- package/dist/operational/packagers.d.ts +67 -0
- package/dist/operational/packagers.d.ts.map +1 -0
- package/dist/operational/packagers.js +252 -0
- package/dist/operational/packagers.js.map +1 -0
- package/dist/operational/redact.d.ts +49 -0
- package/dist/operational/redact.d.ts.map +1 -0
- package/dist/operational/redact.js +135 -0
- package/dist/operational/redact.js.map +1 -0
- package/dist/operational/schema.d.ts +80 -0
- package/dist/operational/schema.d.ts.map +1 -0
- package/dist/operational/schema.js +205 -0
- package/dist/operational/schema.js.map +1 -0
- package/dist/operational/verify.d.ts +100 -0
- package/dist/operational/verify.d.ts.map +1 -0
- package/dist/operational/verify.js +175 -0
- package/dist/operational/verify.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-imposed size budgets for emitted rule files.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from the windsurf adapter so operational packaging can enforce the
|
|
5
|
+
* same per-file ceiling instead of hardcoding a second copy of the number.
|
|
6
|
+
*
|
|
7
|
+
* Known limitation (AC-48): `MAX_TOTAL_CHARS` is enforced *within* a single
|
|
8
|
+
* InstallPlan. Framework and operational emission produce separate plans, so
|
|
9
|
+
* neither sees the other's contribution to the total. The per-file cap is
|
|
10
|
+
* enforced for both; the cross-plan total is not.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
/** Windsurf per-rule-file character ceiling. */
|
|
15
|
+
export declare const MAX_FILE_CHARS = 6000;
|
|
16
|
+
/** Windsurf total-rules character ceiling across all rule files. */
|
|
17
|
+
export declare const MAX_TOTAL_CHARS = 12000;
|
|
18
|
+
/** Fraction of a ceiling at which a warning is emitted. */
|
|
19
|
+
export declare const TOTAL_WARN_THRESHOLD = 0.85;
|
|
20
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/compile/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gDAAgD;AAChD,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,oEAAoE;AACpE,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB,OAAO,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-imposed size budgets for emitted rule files.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from the windsurf adapter so operational packaging can enforce the
|
|
5
|
+
* same per-file ceiling instead of hardcoding a second copy of the number.
|
|
6
|
+
*
|
|
7
|
+
* Known limitation (AC-48): `MAX_TOTAL_CHARS` is enforced *within* a single
|
|
8
|
+
* InstallPlan. Framework and operational emission produce separate plans, so
|
|
9
|
+
* neither sees the other's contribution to the total. The per-file cap is
|
|
10
|
+
* enforced for both; the cross-plan total is not.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
/** Windsurf per-rule-file character ceiling. */
|
|
15
|
+
export const MAX_FILE_CHARS = 6000;
|
|
16
|
+
/** Windsurf total-rules character ceiling across all rule files. */
|
|
17
|
+
export const MAX_TOTAL_CHARS = 12000;
|
|
18
|
+
/** Fraction of a ceiling at which a warning is emitted. */
|
|
19
|
+
export const TOTAL_WARN_THRESHOLD = 0.85;
|
|
20
|
+
//# sourceMappingURL=limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/compile/limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC,oEAAoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AAErC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared skill-naming conventions for platform packaging.
|
|
3
|
+
*
|
|
4
|
+
* Before this module the five adapters each restated their own naming rules in
|
|
5
|
+
* a private helper, so framework and operational packaging could drift apart
|
|
6
|
+
* (AC-34). The helpers were *not* equivalent — they implemented three distinct
|
|
7
|
+
* behaviours — so this module exposes the behaviour space explicitly rather than
|
|
8
|
+
* collapsing them into one function and silently changing adapter output:
|
|
9
|
+
*
|
|
10
|
+
* | Caller | Function | Behaviour |
|
|
11
|
+
* |---------------------|---------------------------|---------------------------------------------|
|
|
12
|
+
* | claude-code, kiro | `normalizeSkillName` | substitute, collapse, trim, prefix, truncate |
|
|
13
|
+
* | windsurf | `skillSlug` | lowercase + substitute only |
|
|
14
|
+
* | cursor, codex | `canonicalSkillFilename` | pass-through |
|
|
15
|
+
*
|
|
16
|
+
* Prefixing is a caller choice, never unconditional (AC-41): framework emission
|
|
17
|
+
* passes `prefix: true`, operational emission passes `prefix: false`. That is
|
|
18
|
+
* what lets operational skills stay out of the reserved `aidlc-` namespace
|
|
19
|
+
* (AC-19) while still reusing these conventions.
|
|
20
|
+
*
|
|
21
|
+
* Requirements: AC-19, AC-33, AC-34, AC-41
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
/** Maximum length for a platform skill directory or file name. */
|
|
26
|
+
export declare const MAX_SKILL_NAME_LENGTH = 64;
|
|
27
|
+
/** The namespace prefix reserved for framework-owned skills. */
|
|
28
|
+
export declare const FRAMEWORK_PREFIX = "aidlc-";
|
|
29
|
+
/** Options controlling how a skill name becomes a path segment. */
|
|
30
|
+
export interface SkillNameOpts {
|
|
31
|
+
/**
|
|
32
|
+
* Apply the reserved `aidlc-` framework prefix. Always explicit — an
|
|
33
|
+
* unconditional prefix is what made AC-19 and AC-34 contradictory (AC-41).
|
|
34
|
+
*/
|
|
35
|
+
prefix: boolean;
|
|
36
|
+
/** Collapse runs of hyphens and trim leading/trailing ones. Default true. */
|
|
37
|
+
collapse?: boolean;
|
|
38
|
+
/** Truncate to this length. Default `MAX_SKILL_NAME_LENGTH`; 0 disables. */
|
|
39
|
+
truncate?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a skill name into a filesystem-safe path segment.
|
|
43
|
+
*
|
|
44
|
+
* This is the claude-code / kiro directory convention: lowercase, non-charset
|
|
45
|
+
* characters substituted with hyphens, hyphen runs collapsed, ends trimmed,
|
|
46
|
+
* optionally prefixed, then truncated.
|
|
47
|
+
*
|
|
48
|
+
* @param name - Raw skill name.
|
|
49
|
+
* @param opts - Prefix choice plus optional collapse/truncate overrides.
|
|
50
|
+
* @returns A lowercase hyphenated segment safe to use as a directory name.
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeSkillName(name: string, opts: SkillNameOpts): string;
|
|
53
|
+
/**
|
|
54
|
+
* Windsurf's weaker slug: lowercase and substitute, but neither collapse nor
|
|
55
|
+
* truncate nor prefix.
|
|
56
|
+
*
|
|
57
|
+
* Deliberately not unified with `normalizeSkillName`. The two agree on every
|
|
58
|
+
* name shipped today (all are already lowercase-hyphenated), but they diverge on
|
|
59
|
+
* non-conforming input, and changing windsurf's output would violate AC-33.
|
|
60
|
+
* `test/golden-adapters-refactor.test.ts` pins the difference.
|
|
61
|
+
*
|
|
62
|
+
* @param name - Raw skill name.
|
|
63
|
+
* @returns A lowercase slug with non-charset characters substituted.
|
|
64
|
+
*/
|
|
65
|
+
export declare function skillSlug(name: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* The canonical `.aidlc/skills/` filename convention: the skill name verbatim
|
|
68
|
+
* plus `.md`.
|
|
69
|
+
*
|
|
70
|
+
* Used by claude-code, kiro, cursor, and codex. Windsurf routes its canonical
|
|
71
|
+
* filename through `skillSlug` instead — a pre-existing inconsistency preserved
|
|
72
|
+
* here rather than fixed, per AC-33.
|
|
73
|
+
*
|
|
74
|
+
* @param name - Raw skill name.
|
|
75
|
+
* @returns `<name>.md`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function canonicalSkillFilename(name: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Build a platform rule/file name carrying the framework prefix.
|
|
80
|
+
*
|
|
81
|
+
* Several adapters built this prefix inline in a template literal
|
|
82
|
+
* (`.cursor/rules/aidlc-${name}.mdc`), which meant re-pointing the helpers alone
|
|
83
|
+
* would have left the convention restated per platform — the drift AC-34 exists
|
|
84
|
+
* to prevent. Note this reproduces the existing double-prefix for framework
|
|
85
|
+
* skills (`aidlc-aidlc-overview`), which AC-33 requires us to preserve.
|
|
86
|
+
*
|
|
87
|
+
* @param name - Raw skill name (or slug).
|
|
88
|
+
* @param ext - File extension including the dot, e.g. `.mdc`.
|
|
89
|
+
* @returns `aidlc-<name><ext>`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function prefixedRuleFilename(name: string, ext: string): string;
|
|
92
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/compile/naming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAQxC,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAmB5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared skill-naming conventions for platform packaging.
|
|
3
|
+
*
|
|
4
|
+
* Before this module the five adapters each restated their own naming rules in
|
|
5
|
+
* a private helper, so framework and operational packaging could drift apart
|
|
6
|
+
* (AC-34). The helpers were *not* equivalent — they implemented three distinct
|
|
7
|
+
* behaviours — so this module exposes the behaviour space explicitly rather than
|
|
8
|
+
* collapsing them into one function and silently changing adapter output:
|
|
9
|
+
*
|
|
10
|
+
* | Caller | Function | Behaviour |
|
|
11
|
+
* |---------------------|---------------------------|---------------------------------------------|
|
|
12
|
+
* | claude-code, kiro | `normalizeSkillName` | substitute, collapse, trim, prefix, truncate |
|
|
13
|
+
* | windsurf | `skillSlug` | lowercase + substitute only |
|
|
14
|
+
* | cursor, codex | `canonicalSkillFilename` | pass-through |
|
|
15
|
+
*
|
|
16
|
+
* Prefixing is a caller choice, never unconditional (AC-41): framework emission
|
|
17
|
+
* passes `prefix: true`, operational emission passes `prefix: false`. That is
|
|
18
|
+
* what lets operational skills stay out of the reserved `aidlc-` namespace
|
|
19
|
+
* (AC-19) while still reusing these conventions.
|
|
20
|
+
*
|
|
21
|
+
* Requirements: AC-19, AC-33, AC-34, AC-41
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
/** Maximum length for a platform skill directory or file name. */
|
|
26
|
+
export const MAX_SKILL_NAME_LENGTH = 64;
|
|
27
|
+
/**
|
|
28
|
+
* The one skill that never takes the `aidlc-` prefix: the bare entry point.
|
|
29
|
+
* Both prefixing adapters exempt it, so the shared helper must too.
|
|
30
|
+
*/
|
|
31
|
+
const BARE_ENTRY_POINT = 'aidlc';
|
|
32
|
+
/** The namespace prefix reserved for framework-owned skills. */
|
|
33
|
+
export const FRAMEWORK_PREFIX = 'aidlc-';
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a skill name into a filesystem-safe path segment.
|
|
36
|
+
*
|
|
37
|
+
* This is the claude-code / kiro directory convention: lowercase, non-charset
|
|
38
|
+
* characters substituted with hyphens, hyphen runs collapsed, ends trimmed,
|
|
39
|
+
* optionally prefixed, then truncated.
|
|
40
|
+
*
|
|
41
|
+
* @param name - Raw skill name.
|
|
42
|
+
* @param opts - Prefix choice plus optional collapse/truncate overrides.
|
|
43
|
+
* @returns A lowercase hyphenated segment safe to use as a directory name.
|
|
44
|
+
*/
|
|
45
|
+
export function normalizeSkillName(name, opts) {
|
|
46
|
+
const collapse = opts.collapse ?? true;
|
|
47
|
+
const truncate = opts.truncate ?? MAX_SKILL_NAME_LENGTH;
|
|
48
|
+
let normalized = name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
49
|
+
if (collapse) {
|
|
50
|
+
normalized = normalized.replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
51
|
+
}
|
|
52
|
+
if (opts.prefix && normalized !== BARE_ENTRY_POINT && !normalized.startsWith(FRAMEWORK_PREFIX)) {
|
|
53
|
+
normalized = `${FRAMEWORK_PREFIX}${normalized}`;
|
|
54
|
+
}
|
|
55
|
+
if (truncate > 0 && normalized.length > truncate) {
|
|
56
|
+
normalized = normalized.slice(0, truncate);
|
|
57
|
+
}
|
|
58
|
+
return normalized;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Windsurf's weaker slug: lowercase and substitute, but neither collapse nor
|
|
62
|
+
* truncate nor prefix.
|
|
63
|
+
*
|
|
64
|
+
* Deliberately not unified with `normalizeSkillName`. The two agree on every
|
|
65
|
+
* name shipped today (all are already lowercase-hyphenated), but they diverge on
|
|
66
|
+
* non-conforming input, and changing windsurf's output would violate AC-33.
|
|
67
|
+
* `test/golden-adapters-refactor.test.ts` pins the difference.
|
|
68
|
+
*
|
|
69
|
+
* @param name - Raw skill name.
|
|
70
|
+
* @returns A lowercase slug with non-charset characters substituted.
|
|
71
|
+
*/
|
|
72
|
+
export function skillSlug(name) {
|
|
73
|
+
return name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The canonical `.aidlc/skills/` filename convention: the skill name verbatim
|
|
77
|
+
* plus `.md`.
|
|
78
|
+
*
|
|
79
|
+
* Used by claude-code, kiro, cursor, and codex. Windsurf routes its canonical
|
|
80
|
+
* filename through `skillSlug` instead — a pre-existing inconsistency preserved
|
|
81
|
+
* here rather than fixed, per AC-33.
|
|
82
|
+
*
|
|
83
|
+
* @param name - Raw skill name.
|
|
84
|
+
* @returns `<name>.md`.
|
|
85
|
+
*/
|
|
86
|
+
export function canonicalSkillFilename(name) {
|
|
87
|
+
return `${name}.md`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build a platform rule/file name carrying the framework prefix.
|
|
91
|
+
*
|
|
92
|
+
* Several adapters built this prefix inline in a template literal
|
|
93
|
+
* (`.cursor/rules/aidlc-${name}.mdc`), which meant re-pointing the helpers alone
|
|
94
|
+
* would have left the convention restated per platform — the drift AC-34 exists
|
|
95
|
+
* to prevent. Note this reproduces the existing double-prefix for framework
|
|
96
|
+
* skills (`aidlc-aidlc-overview`), which AC-33 requires us to preserve.
|
|
97
|
+
*
|
|
98
|
+
* @param name - Raw skill name (or slug).
|
|
99
|
+
* @param ext - File extension including the dot, e.g. `.mdc`.
|
|
100
|
+
* @returns `aidlc-<name><ext>`.
|
|
101
|
+
*/
|
|
102
|
+
export function prefixedRuleFilename(name, ext) {
|
|
103
|
+
return `${FRAMEWORK_PREFIX}${name}${ext}`;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/compile/naming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAExC;;;GAGG;AACH,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAezC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,IAAmB;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,qBAAqB,CAAC;IAExD,IAAI,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IAEhE,IAAI,QAAQ,EAAE,CAAC;QACb,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,IAAI,UAAU,KAAK,gBAAgB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/F,UAAU,GAAG,GAAG,gBAAgB,GAAG,UAAU,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QACjD,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,GAAG,IAAI,KAAK,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,GAAW;IAC5D,OAAO,GAAG,gBAAgB,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery and re-emit for operational skills.
|
|
3
|
+
*
|
|
4
|
+
* Re-emit (AC-18) exists so a skill can be packaged for a newly added platform
|
|
5
|
+
* without rewriting it, and so a content-package update can reach skills generated
|
|
6
|
+
* earlier. It refreshes the machine-managed verification section and
|
|
7
|
+
* `content_version`, and leaves every user-authored byte alone — which is how
|
|
8
|
+
* AC-50 is scoped in the design rather than violated.
|
|
9
|
+
*
|
|
10
|
+
* Requirements: AC-17, AC-18, AC-36, AC-50
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { PlatformId } from '../core/types.js';
|
|
15
|
+
import { type OperationalSkill } from './schema.js';
|
|
16
|
+
import { type EmitReport } from './emit.js';
|
|
17
|
+
/** One discovered skill plus where it came from. */
|
|
18
|
+
export interface DiscoveredSkill {
|
|
19
|
+
skill: OperationalSkill;
|
|
20
|
+
/** Repo-relative path of the canonical body. */
|
|
21
|
+
path: string;
|
|
22
|
+
}
|
|
23
|
+
/** A canonical body that exists but could not be parsed. */
|
|
24
|
+
export interface DiscoveryProblem {
|
|
25
|
+
path: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
}
|
|
28
|
+
/** Result of scanning the operational-skills directory. */
|
|
29
|
+
export interface DiscoveryResult {
|
|
30
|
+
skills: DiscoveredSkill[];
|
|
31
|
+
/** Unparseable files, surfaced as warnings rather than aborting the scan. */
|
|
32
|
+
problems: DiscoveryProblem[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Enumerate canonical operational-skill bodies.
|
|
36
|
+
*
|
|
37
|
+
* Matches `*.md` exactly and excludes anything containing `.tmp`, so a staged or
|
|
38
|
+
* abandoned temp file is never mistaken for a skill.
|
|
39
|
+
*
|
|
40
|
+
* @param projectRoot - Absolute project root.
|
|
41
|
+
* @returns Parsed skills plus any files that failed to parse.
|
|
42
|
+
*/
|
|
43
|
+
export declare function discoverOperationalSkills(projectRoot: string): DiscoveryResult;
|
|
44
|
+
/** Load a single operational skill by name. */
|
|
45
|
+
export declare function loadOperationalSkill(projectRoot: string, name: string): OperationalSkill | null;
|
|
46
|
+
/**
|
|
47
|
+
* Refresh the machine-managed parts of a skill from the content package.
|
|
48
|
+
*
|
|
49
|
+
* Replaces only the bytes between the verify-steps delimiters and updates
|
|
50
|
+
* `content_version`. When the body has no managed region — a hand-authored file, or
|
|
51
|
+
* one whose markers were removed — the section is appended rather than silently
|
|
52
|
+
* skipped, so verification is never absent (AC-35).
|
|
53
|
+
*
|
|
54
|
+
* @param skill - The skill to refresh.
|
|
55
|
+
* @param contentRoot - Content package root.
|
|
56
|
+
* @param contentVersion - Version to stamp.
|
|
57
|
+
* @returns A new skill; the input is not mutated.
|
|
58
|
+
*/
|
|
59
|
+
export declare function refreshManagedSections(skill: OperationalSkill, contentRoot: string, contentVersion: string): OperationalSkill;
|
|
60
|
+
/** Options for a re-emit run. */
|
|
61
|
+
export interface ReEmitOptions {
|
|
62
|
+
projectRoot: string;
|
|
63
|
+
contentRoot: string;
|
|
64
|
+
contentVersion: string;
|
|
65
|
+
platforms: PlatformId[];
|
|
66
|
+
/** Re-emit only this skill; omit for every discovered skill (AC-18 scope). */
|
|
67
|
+
name?: string;
|
|
68
|
+
dryRun?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** Outcome of a re-emit run. */
|
|
71
|
+
export interface ReEmitResult {
|
|
72
|
+
/** Names of skills re-emitted. */
|
|
73
|
+
names: string[];
|
|
74
|
+
report: EmitReport;
|
|
75
|
+
problems: DiscoveryProblem[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Re-emit one or all operational skills.
|
|
79
|
+
*
|
|
80
|
+
* Deliberately overwrites platform-derived files — they are, by definition, this
|
|
81
|
+
* command's own prior output, which is AC-50's stated exception to AC-10's
|
|
82
|
+
* no-silent-overwrite rule.
|
|
83
|
+
*
|
|
84
|
+
* @param opts - Re-emit options.
|
|
85
|
+
* @returns Which skills were re-emitted and what changed on disk.
|
|
86
|
+
* @throws When a named skill does not exist, or a configured platform lacks packaging.
|
|
87
|
+
*/
|
|
88
|
+
export declare function reEmit(opts: ReEmitOptions): ReEmitResult;
|
|
89
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/operational/discover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM3E,OAAO,EAAiD,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE3F,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,gBAAgB,CAAC;IACxB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAuB9E;AAED,+CAA+C;AAC/C,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,IAAI,CAIzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,gBAAgB,CAWlB;AAED,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CAkDxD"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery and re-emit for operational skills.
|
|
3
|
+
*
|
|
4
|
+
* Re-emit (AC-18) exists so a skill can be packaged for a newly added platform
|
|
5
|
+
* without rewriting it, and so a content-package update can reach skills generated
|
|
6
|
+
* earlier. It refreshes the machine-managed verification section and
|
|
7
|
+
* `content_version`, and leaves every user-authored byte alone — which is how
|
|
8
|
+
* AC-50 is scoped in the design rather than violated.
|
|
9
|
+
*
|
|
10
|
+
* Requirements: AC-17, AC-18, AC-36, AC-50
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { OPERATIONAL_DIR, canonicalBodyPath } from './packagers.js';
|
|
17
|
+
import { parseOperationalSkill } from './schema.js';
|
|
18
|
+
import { extractVerifySteps, replaceVerifySection, wrapVerifySection, } from './verify.js';
|
|
19
|
+
import { executePlanStaged, dryRunPlanStaged, planEmit } from './emit.js';
|
|
20
|
+
/**
|
|
21
|
+
* Enumerate canonical operational-skill bodies.
|
|
22
|
+
*
|
|
23
|
+
* Matches `*.md` exactly and excludes anything containing `.tmp`, so a staged or
|
|
24
|
+
* abandoned temp file is never mistaken for a skill.
|
|
25
|
+
*
|
|
26
|
+
* @param projectRoot - Absolute project root.
|
|
27
|
+
* @returns Parsed skills plus any files that failed to parse.
|
|
28
|
+
*/
|
|
29
|
+
export function discoverOperationalSkills(projectRoot) {
|
|
30
|
+
const dir = join(projectRoot, OPERATIONAL_DIR);
|
|
31
|
+
const skills = [];
|
|
32
|
+
const problems = [];
|
|
33
|
+
if (!existsSync(dir)) {
|
|
34
|
+
return { skills, problems };
|
|
35
|
+
}
|
|
36
|
+
// Sorted so discovery order — and therefore index content — is deterministic.
|
|
37
|
+
for (const entry of readdirSync(dir).sort()) {
|
|
38
|
+
if (!entry.endsWith('.md') || entry.includes('.tmp'))
|
|
39
|
+
continue;
|
|
40
|
+
const rel = `${OPERATIONAL_DIR}/${entry}`;
|
|
41
|
+
try {
|
|
42
|
+
const skill = parseOperationalSkill(readFileSync(join(dir, entry), 'utf8'));
|
|
43
|
+
skills.push({ skill, path: rel });
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
problems.push({ path: rel, reason: err.message });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { skills, problems };
|
|
50
|
+
}
|
|
51
|
+
/** Load a single operational skill by name. */
|
|
52
|
+
export function loadOperationalSkill(projectRoot, name) {
|
|
53
|
+
const abs = join(projectRoot, canonicalBodyPath(name));
|
|
54
|
+
if (!existsSync(abs))
|
|
55
|
+
return null;
|
|
56
|
+
return parseOperationalSkill(readFileSync(abs, 'utf8'));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Refresh the machine-managed parts of a skill from the content package.
|
|
60
|
+
*
|
|
61
|
+
* Replaces only the bytes between the verify-steps delimiters and updates
|
|
62
|
+
* `content_version`. When the body has no managed region — a hand-authored file, or
|
|
63
|
+
* one whose markers were removed — the section is appended rather than silently
|
|
64
|
+
* skipped, so verification is never absent (AC-35).
|
|
65
|
+
*
|
|
66
|
+
* @param skill - The skill to refresh.
|
|
67
|
+
* @param contentRoot - Content package root.
|
|
68
|
+
* @param contentVersion - Version to stamp.
|
|
69
|
+
* @returns A new skill; the input is not mutated.
|
|
70
|
+
*/
|
|
71
|
+
export function refreshManagedSections(skill, contentRoot, contentVersion) {
|
|
72
|
+
const steps = extractVerifySteps(contentRoot);
|
|
73
|
+
const replaced = replaceVerifySection(skill.body, steps);
|
|
74
|
+
const body = replaced ?? `${skill.body.replace(/\n+$/, '')}\n\n${wrapVerifySection(steps)}\n`;
|
|
75
|
+
return {
|
|
76
|
+
meta: { ...skill.meta, content_version: contentVersion },
|
|
77
|
+
body,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Re-emit one or all operational skills.
|
|
82
|
+
*
|
|
83
|
+
* Deliberately overwrites platform-derived files — they are, by definition, this
|
|
84
|
+
* command's own prior output, which is AC-50's stated exception to AC-10's
|
|
85
|
+
* no-silent-overwrite rule.
|
|
86
|
+
*
|
|
87
|
+
* @param opts - Re-emit options.
|
|
88
|
+
* @returns Which skills were re-emitted and what changed on disk.
|
|
89
|
+
* @throws When a named skill does not exist, or a configured platform lacks packaging.
|
|
90
|
+
*/
|
|
91
|
+
export function reEmit(opts) {
|
|
92
|
+
const { skills: discovered, problems } = discoverOperationalSkills(opts.projectRoot);
|
|
93
|
+
const targets = opts.name
|
|
94
|
+
? discovered.filter((d) => d.skill.meta.name === opts.name)
|
|
95
|
+
: discovered;
|
|
96
|
+
if (opts.name && targets.length === 0) {
|
|
97
|
+
throw new Error(`no operational skill named '${opts.name}' in ${OPERATIONAL_DIR}/` +
|
|
98
|
+
(problems.length > 0
|
|
99
|
+
? ` (${problems.length} file(s) failed to parse — see warnings)`
|
|
100
|
+
: ''));
|
|
101
|
+
}
|
|
102
|
+
// Refresh every target first, so index artifacts describe post-refresh state.
|
|
103
|
+
const refreshed = targets.map((d) => refreshManagedSections(d.skill, opts.contentRoot, opts.contentVersion));
|
|
104
|
+
// The full set as it will exist after this run, for index platforms.
|
|
105
|
+
const byName = new Map(discovered.map((d) => [d.skill.meta.name, d.skill]));
|
|
106
|
+
for (const s of refreshed)
|
|
107
|
+
byName.set(s.meta.name, s);
|
|
108
|
+
const allSkills = [...byName.values()];
|
|
109
|
+
const filesWritten = [];
|
|
110
|
+
const filesSkipped = [];
|
|
111
|
+
const warnings = [];
|
|
112
|
+
for (const skill of refreshed) {
|
|
113
|
+
const plan = planEmit({
|
|
114
|
+
skill,
|
|
115
|
+
platforms: opts.platforms,
|
|
116
|
+
projectRoot: opts.projectRoot,
|
|
117
|
+
allSkills,
|
|
118
|
+
});
|
|
119
|
+
const report = opts.dryRun
|
|
120
|
+
? dryRunPlanStaged(plan, opts.projectRoot)
|
|
121
|
+
: executePlanStaged(plan, opts.projectRoot);
|
|
122
|
+
filesWritten.push(...report.filesWritten);
|
|
123
|
+
filesSkipped.push(...report.filesSkipped);
|
|
124
|
+
warnings.push(...report.warnings);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
names: refreshed.map((s) => s.meta.name),
|
|
128
|
+
report: { filesWritten, filesSkipped, warnings },
|
|
129
|
+
problems,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/operational/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operational-skill emission: plan building and staged, all-or-nothing execution.
|
|
3
|
+
*
|
|
4
|
+
* Reuses `InstallPlan`/`FileOp` — the same types the framework adapters produce —
|
|
5
|
+
* which buys skip-if-identical idempotence (NFR-7), dry-run equivalence, and
|
|
6
|
+
* `mergeBlock` support for codex without touching `SkillMeta` (AC-33).
|
|
7
|
+
*
|
|
8
|
+
* `executePlan` writes op-by-op, so a mid-plan failure leaves a partial tree. That
|
|
9
|
+
* is unacceptable under AC-45 and unrepairable under AC-10's collision refusal, so
|
|
10
|
+
* emission uses `executePlanStaged` instead: resolve and validate everything,
|
|
11
|
+
* stage every byte into one scratch directory, then commit by rename.
|
|
12
|
+
*
|
|
13
|
+
* Requirements: AC-15, AC-17, AC-45, AC-47, NFR-7
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import type { InstallPlan, PlatformId } from '../core/types.js';
|
|
18
|
+
import { type OperationalSkill } from './schema.js';
|
|
19
|
+
/** Inputs for one emission. */
|
|
20
|
+
export interface EmitRequest {
|
|
21
|
+
/** The skill being emitted (its canonical body is (re)written). */
|
|
22
|
+
skill: OperationalSkill;
|
|
23
|
+
/** Platforms from `.aidlc/config.yaml`. */
|
|
24
|
+
platforms: PlatformId[];
|
|
25
|
+
/** Absolute project root. */
|
|
26
|
+
projectRoot: string;
|
|
27
|
+
/**
|
|
28
|
+
* Every operational skill in the project, including `skill`. Index platforms
|
|
29
|
+
* need the full set; per-skill platforms ignore it.
|
|
30
|
+
*/
|
|
31
|
+
allSkills: OperationalSkill[];
|
|
32
|
+
}
|
|
33
|
+
/** Result of applying (or simulating) an operational plan. */
|
|
34
|
+
export interface EmitReport {
|
|
35
|
+
filesWritten: string[];
|
|
36
|
+
filesSkipped: string[];
|
|
37
|
+
warnings: string[];
|
|
38
|
+
}
|
|
39
|
+
/** Thrown when staging or committing fails. */
|
|
40
|
+
export declare class EmitError extends Error {
|
|
41
|
+
/** Ops whose rename already completed, when a commit fails part-way. */
|
|
42
|
+
readonly committed: string[];
|
|
43
|
+
constructor(reason: string,
|
|
44
|
+
/** Ops whose rename already completed, when a commit fails part-way. */
|
|
45
|
+
committed?: string[]);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the InstallPlan for one operational skill.
|
|
49
|
+
*
|
|
50
|
+
* Every packager is resolved **before** any op is produced, so a mixed
|
|
51
|
+
* supported/unsupported `platforms:` list throws during planning with nothing
|
|
52
|
+
* staged — AC-47's all-or-nothing guarantee.
|
|
53
|
+
*
|
|
54
|
+
* @param req - The emission request.
|
|
55
|
+
* @returns A plan whose ops cover the canonical body plus every platform artifact.
|
|
56
|
+
* @throws {UnsupportedPlatformError} When any configured platform lacks packaging.
|
|
57
|
+
*/
|
|
58
|
+
export declare function planEmit(req: EmitRequest): InstallPlan;
|
|
59
|
+
/**
|
|
60
|
+
* Apply a plan atomically-as-possible.
|
|
61
|
+
*
|
|
62
|
+
* Three phases:
|
|
63
|
+
* 1. **Resolve and validate** — compute final content for every op. Pure. Every
|
|
64
|
+
* predictable failure lands here, before a single byte is written.
|
|
65
|
+
* 2. **Stage** — write each op into one scratch directory outside every path the
|
|
66
|
+
* project enumerates. On failure, remove the scratch dir and abort; the tree is
|
|
67
|
+
* exactly as it was.
|
|
68
|
+
* 3. **Commit** — create parent directories, then rename each staged file onto its
|
|
69
|
+
* target.
|
|
70
|
+
*
|
|
71
|
+
* Honest bound: phase 3 is a rename sequence, not one transaction. A failure there
|
|
72
|
+
* reports which renames completed, and the residual state is repaired by
|
|
73
|
+
* `--re-emit`, which is idempotent. Directories this run created are removed on a
|
|
74
|
+
* phase-3 failure only when still empty.
|
|
75
|
+
*
|
|
76
|
+
* Skip-if-identical is preserved, so re-emitting unchanged input writes nothing
|
|
77
|
+
* (NFR-7, AC-17).
|
|
78
|
+
*
|
|
79
|
+
* @param plan - The plan to apply.
|
|
80
|
+
* @param rootDir - Absolute project root.
|
|
81
|
+
* @returns What was written and skipped.
|
|
82
|
+
*/
|
|
83
|
+
export declare function executePlanStaged(plan: InstallPlan, rootDir: string): EmitReport;
|
|
84
|
+
/**
|
|
85
|
+
* Simulate `executePlanStaged` without touching the filesystem.
|
|
86
|
+
*
|
|
87
|
+
* Uses the same resolution, so `--dry-run` is provably equivalent to a real run.
|
|
88
|
+
*
|
|
89
|
+
* @param plan - The plan to simulate.
|
|
90
|
+
* @param rootDir - Absolute project root.
|
|
91
|
+
*/
|
|
92
|
+
export declare function dryRunPlanStaged(plan: InstallPlan, rootDir: string): EmitReport;
|
|
93
|
+
//# sourceMappingURL=emit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/operational/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAYH,OAAO,KAAK,EAAU,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIxE,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM/E,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,KAAK,EAAE,gBAAgB,CAAC;IACxB,2CAA2C;IAC3C,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,8DAA8D;AAC9D,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,+CAA+C;AAC/C,qBAAa,SAAU,SAAQ,KAAK;IAGhC,wEAAwE;aACxD,SAAS,EAAE,MAAM,EAAE;gBAFnC,MAAM,EAAE,MAAM;IACd,wEAAwE;IACxD,SAAS,GAAE,MAAM,EAAO;CAK3C;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CA4CtD;AA6BD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CA6EhF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAgB/E"}
|