@rasensio/aidlc 1.8.1 → 1.9.1

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.
Files changed (104) hide show
  1. package/dist/cli.js +2 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/add-action.d.ts.map +1 -1
  4. package/dist/commands/add-action.js +2 -3
  5. package/dist/commands/add-action.js.map +1 -1
  6. package/dist/commands/add-skill.d.ts +28 -0
  7. package/dist/commands/add-skill.d.ts.map +1 -0
  8. package/dist/commands/add-skill.js +315 -0
  9. package/dist/commands/add-skill.js.map +1 -0
  10. package/dist/commands/add.d.ts +25 -0
  11. package/dist/commands/add.d.ts.map +1 -0
  12. package/dist/commands/add.js +29 -0
  13. package/dist/commands/add.js.map +1 -0
  14. package/dist/commands/claim.d.ts +9 -0
  15. package/dist/commands/claim.d.ts.map +1 -1
  16. package/dist/commands/claim.js +26 -4
  17. package/dist/commands/claim.js.map +1 -1
  18. package/dist/commands/cost.d.ts.map +1 -1
  19. package/dist/commands/cost.js +3 -5
  20. package/dist/commands/cost.js.map +1 -1
  21. package/dist/commands/init.d.ts.map +1 -1
  22. package/dist/commands/init.js +1 -10
  23. package/dist/commands/init.js.map +1 -1
  24. package/dist/commands/update.d.ts.map +1 -1
  25. package/dist/commands/update.js +1 -9
  26. package/dist/commands/update.js.map +1 -1
  27. package/dist/compile/adapters/claude-code.d.ts.map +1 -1
  28. package/dist/compile/adapters/claude-code.js +3 -24
  29. package/dist/compile/adapters/claude-code.js.map +1 -1
  30. package/dist/compile/adapters/codex.d.ts.map +1 -1
  31. package/dist/compile/adapters/codex.js +3 -2
  32. package/dist/compile/adapters/codex.js.map +1 -1
  33. package/dist/compile/adapters/cursor.d.ts.map +1 -1
  34. package/dist/compile/adapters/cursor.js +4 -2
  35. package/dist/compile/adapters/cursor.js.map +1 -1
  36. package/dist/compile/adapters/kiro.d.ts.map +1 -1
  37. package/dist/compile/adapters/kiro.js +6 -10
  38. package/dist/compile/adapters/kiro.js.map +1 -1
  39. package/dist/compile/adapters/windsurf.d.ts.map +1 -1
  40. package/dist/compile/adapters/windsurf.js +9 -11
  41. package/dist/compile/adapters/windsurf.js.map +1 -1
  42. package/dist/compile/content-root.d.ts +22 -0
  43. package/dist/compile/content-root.d.ts.map +1 -0
  44. package/dist/compile/content-root.js +28 -0
  45. package/dist/compile/content-root.js.map +1 -0
  46. package/dist/compile/limits.d.ts +20 -0
  47. package/dist/compile/limits.d.ts.map +1 -0
  48. package/dist/compile/limits.js +20 -0
  49. package/dist/compile/limits.js.map +1 -0
  50. package/dist/compile/naming.d.ts +92 -0
  51. package/dist/compile/naming.d.ts.map +1 -0
  52. package/dist/compile/naming.js +105 -0
  53. package/dist/compile/naming.js.map +1 -0
  54. package/dist/concurrency/session-id.d.ts +12 -0
  55. package/dist/concurrency/session-id.d.ts.map +1 -1
  56. package/dist/concurrency/session-id.js +24 -4
  57. package/dist/concurrency/session-id.js.map +1 -1
  58. package/dist/cost/agent.d.ts +48 -0
  59. package/dist/cost/agent.d.ts.map +1 -0
  60. package/dist/cost/agent.js +167 -0
  61. package/dist/cost/agent.js.map +1 -0
  62. package/dist/cost/providers/index.d.ts +13 -0
  63. package/dist/cost/providers/index.d.ts.map +1 -0
  64. package/dist/cost/providers/index.js +23 -0
  65. package/dist/cost/providers/index.js.map +1 -0
  66. package/dist/cost/sync.d.ts.map +1 -1
  67. package/dist/cost/sync.js +114 -37
  68. package/dist/cost/sync.js.map +1 -1
  69. package/dist/doctor/migrations/index.d.ts.map +1 -1
  70. package/dist/doctor/migrations/index.js +2 -0
  71. package/dist/doctor/migrations/index.js.map +1 -1
  72. package/dist/doctor/migrations/unknown-agent-claims.d.ts +25 -0
  73. package/dist/doctor/migrations/unknown-agent-claims.d.ts.map +1 -0
  74. package/dist/doctor/migrations/unknown-agent-claims.js +82 -0
  75. package/dist/doctor/migrations/unknown-agent-claims.js.map +1 -0
  76. package/dist/operational/discover.d.ts +89 -0
  77. package/dist/operational/discover.d.ts.map +1 -0
  78. package/dist/operational/discover.js +132 -0
  79. package/dist/operational/discover.js.map +1 -0
  80. package/dist/operational/emit.d.ts +93 -0
  81. package/dist/operational/emit.d.ts.map +1 -0
  82. package/dist/operational/emit.js +227 -0
  83. package/dist/operational/emit.js.map +1 -0
  84. package/dist/operational/knowledge.d.ts +64 -0
  85. package/dist/operational/knowledge.d.ts.map +1 -0
  86. package/dist/operational/knowledge.js +144 -0
  87. package/dist/operational/knowledge.js.map +1 -0
  88. package/dist/operational/packagers.d.ts +67 -0
  89. package/dist/operational/packagers.d.ts.map +1 -0
  90. package/dist/operational/packagers.js +252 -0
  91. package/dist/operational/packagers.js.map +1 -0
  92. package/dist/operational/redact.d.ts +49 -0
  93. package/dist/operational/redact.d.ts.map +1 -0
  94. package/dist/operational/redact.js +135 -0
  95. package/dist/operational/redact.js.map +1 -0
  96. package/dist/operational/schema.d.ts +80 -0
  97. package/dist/operational/schema.d.ts.map +1 -0
  98. package/dist/operational/schema.js +205 -0
  99. package/dist/operational/schema.js.map +1 -0
  100. package/dist/operational/verify.d.ts +100 -0
  101. package/dist/operational/verify.d.ts.map +1 -0
  102. package/dist/operational/verify.js +175 -0
  103. package/dist/operational/verify.js.map +1 -0
  104. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/operational/redact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Operational-skill schema: frontmatter shape, parsing, serialization, and name
3
+ * validation.
4
+ *
5
+ * Deliberately NOT `SkillMeta`. `SkillMeta` requires `phase: PhaseName`
6
+ * (`core/types.ts`) and `parseSkillFile` throws without it
7
+ * (`compile/loaders.ts:84`) — an operational skill has no lifecycle phase, which
8
+ * is the constraint behind decision D-1's separate emit path (AC-33, AC-39).
9
+ *
10
+ * Requirements: AC-19, AC-20, AC-33, AC-39, AC-42
11
+ *
12
+ * @module
13
+ */
14
+ /** Maximum length of an operational skill name (matches the platform cap). */
15
+ export declare const MAX_OPERATIONAL_NAME_LENGTH = 64;
16
+ /** The literal `kind` value that marks a skill as app-owned (AC-20). */
17
+ export declare const OPERATIONAL_KIND = "operational";
18
+ /** Frontmatter of an operational skill (AC-39). */
19
+ export interface OperationalSkillMeta {
20
+ /** Skill name; validated by `validateOperationalSkillName`. */
21
+ name: string;
22
+ /** One-line summary of the operation the skill performs. */
23
+ description: string;
24
+ /** Always `'operational'` — the positive ownership marker (AC-20). */
25
+ kind: typeof OPERATIONAL_KIND;
26
+ /** Tool that generated the skill, e.g. `aidlc-add-skill`. */
27
+ generated_by: string;
28
+ /** `@rasensio/aidlc-content` version whose verify steps are inlined. */
29
+ content_version: string;
30
+ /** Optional natural-language trigger description. */
31
+ trigger?: string;
32
+ /**
33
+ * Repo-relative paths the skill operates on. The ONLY source of paths for the
34
+ * AC-38 existence check — prose and fenced code blocks are never scanned, which
35
+ * is how the false-failure exclusion is satisfied structurally.
36
+ */
37
+ paths?: string[];
38
+ }
39
+ /** A parsed operational skill: frontmatter plus markdown body. */
40
+ export interface OperationalSkill {
41
+ meta: OperationalSkillMeta;
42
+ body: string;
43
+ }
44
+ /** Thrown when a name or frontmatter violates the schema. */
45
+ export declare class OperationalSchemaError extends Error {
46
+ constructor(reason: string);
47
+ }
48
+ /**
49
+ * Validate an operational skill name before it is used in any filesystem path.
50
+ *
51
+ * This runs before path construction, not after, because the name reaches
52
+ * `.aidlc/operational-skills/<name>.md` and four platform directories. The
53
+ * charset alone excludes every traversal character; the explicit separator and
54
+ * dot-segment checks are defence in depth so that relaxing the charset later
55
+ * cannot silently reopen traversal.
56
+ *
57
+ * @param name - Candidate skill name.
58
+ * @throws {OperationalSchemaError} When the name is unusable or reserved.
59
+ */
60
+ export declare function validateOperationalSkillName(name: string): void;
61
+ /**
62
+ * Serialize an operational skill to frontmatter + body.
63
+ *
64
+ * Keys are emitted in `KEY_ORDER` and optional keys are omitted when absent, so
65
+ * the same input always produces the same bytes — the ordering half of AC-17.
66
+ *
67
+ * @param skill - The skill to serialize.
68
+ * @returns Full file content, frontmatter first.
69
+ */
70
+ export declare function serializeOperationalSkill(skill: OperationalSkill): string;
71
+ /**
72
+ * Parse an operational skill file into frontmatter and body.
73
+ *
74
+ * @param raw - Full file content.
75
+ * @returns The parsed skill.
76
+ * @throws {OperationalSchemaError} On missing/unclosed frontmatter, a missing or
77
+ * wrongly-typed required field, or an invalid name.
78
+ */
79
+ export declare function parseOperationalSkill(raw: string): OperationalSkill;
80
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/operational/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,8EAA8E;AAC9E,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAyB9C,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAM9C,mDAAmD;AACnD,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,IAAI,EAAE,OAAO,gBAAgB,CAAC;IAC9B,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,eAAe,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6DAA6D;AAC7D,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,MAAM,EAAE,MAAM;CAI3B;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA+C/D;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CA0BzE;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAmEnE"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Operational-skill schema: frontmatter shape, parsing, serialization, and name
3
+ * validation.
4
+ *
5
+ * Deliberately NOT `SkillMeta`. `SkillMeta` requires `phase: PhaseName`
6
+ * (`core/types.ts`) and `parseSkillFile` throws without it
7
+ * (`compile/loaders.ts:84`) — an operational skill has no lifecycle phase, which
8
+ * is the constraint behind decision D-1's separate emit path (AC-33, AC-39).
9
+ *
10
+ * Requirements: AC-19, AC-20, AC-33, AC-39, AC-42
11
+ *
12
+ * @module
13
+ */
14
+ import { parse as parseYaml } from 'yaml';
15
+ // ---------------------------------------------------------------------------
16
+ // Constants
17
+ // ---------------------------------------------------------------------------
18
+ /** Maximum length of an operational skill name (matches the platform cap). */
19
+ export const MAX_OPERATIONAL_NAME_LENGTH = 64;
20
+ /** Allowed name charset: lowercase alphanumeric plus interior hyphens. */
21
+ const NAME_RE = /^[a-z][a-z0-9-]*$/;
22
+ /** The namespace reserved for framework-owned skills (AC-19). */
23
+ const RESERVED_PREFIX = 'aidlc-';
24
+ /** The bare framework entry-point name, also reserved. */
25
+ const RESERVED_BARE = 'aidlc';
26
+ /**
27
+ * Frontmatter key order for serialization. Fixed, because a stable key order is
28
+ * half of AC-17's byte-identical determinism guarantee.
29
+ */
30
+ const KEY_ORDER = [
31
+ 'name',
32
+ 'description',
33
+ 'kind',
34
+ 'generated_by',
35
+ 'content_version',
36
+ 'trigger',
37
+ 'paths',
38
+ ];
39
+ /** The literal `kind` value that marks a skill as app-owned (AC-20). */
40
+ export const OPERATIONAL_KIND = 'operational';
41
+ /** Thrown when a name or frontmatter violates the schema. */
42
+ export class OperationalSchemaError extends Error {
43
+ constructor(reason) {
44
+ super(reason);
45
+ this.name = 'OperationalSchemaError';
46
+ }
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Name validation (AC-19, AC-42) — a security boundary
50
+ // ---------------------------------------------------------------------------
51
+ /**
52
+ * Validate an operational skill name before it is used in any filesystem path.
53
+ *
54
+ * This runs before path construction, not after, because the name reaches
55
+ * `.aidlc/operational-skills/<name>.md` and four platform directories. The
56
+ * charset alone excludes every traversal character; the explicit separator and
57
+ * dot-segment checks are defence in depth so that relaxing the charset later
58
+ * cannot silently reopen traversal.
59
+ *
60
+ * @param name - Candidate skill name.
61
+ * @throws {OperationalSchemaError} When the name is unusable or reserved.
62
+ */
63
+ export function validateOperationalSkillName(name) {
64
+ if (typeof name !== 'string' || name.length === 0) {
65
+ throw new OperationalSchemaError('skill name is required');
66
+ }
67
+ // Traversal and separator rejection — checked before the charset test so the
68
+ // error message names the real problem rather than a generic charset failure.
69
+ if (name.includes('/') || name.includes('\\')) {
70
+ throw new OperationalSchemaError(`skill name '${name}' must not contain path separators`);
71
+ }
72
+ if (name.includes('..')) {
73
+ throw new OperationalSchemaError(`skill name '${name}' must not contain '..'`);
74
+ }
75
+ if (name.startsWith('.')) {
76
+ throw new OperationalSchemaError(`skill name '${name}' must not start with '.'`);
77
+ }
78
+ if (name.length > MAX_OPERATIONAL_NAME_LENGTH) {
79
+ throw new OperationalSchemaError(`skill name '${name}' exceeds ${MAX_OPERATIONAL_NAME_LENGTH} characters`);
80
+ }
81
+ if (!NAME_RE.test(name)) {
82
+ throw new OperationalSchemaError(`skill name '${name}' must be lowercase letters, digits, and hyphens, starting with a letter`);
83
+ }
84
+ if (name.endsWith('-') || name.includes('--')) {
85
+ throw new OperationalSchemaError(`skill name '${name}' must not contain consecutive or trailing hyphens`);
86
+ }
87
+ // AC-19 enforced, not merely observed: the aidlc- namespace is framework-owned.
88
+ if (name === RESERVED_BARE || name.startsWith(RESERVED_PREFIX)) {
89
+ throw new OperationalSchemaError(`skill name '${name}' is reserved: the '${RESERVED_PREFIX}' namespace belongs to framework skills`);
90
+ }
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Serialization
94
+ // ---------------------------------------------------------------------------
95
+ /** Quote a scalar for YAML only when necessary, so output stays readable. */
96
+ function scalar(value) {
97
+ const needsQuoting = value === '' ||
98
+ /^[\s]|[\s]$/.test(value) ||
99
+ /^[-?:,[\]{}#&*!|>'"%@`]/.test(value) ||
100
+ /:\s/.test(value) ||
101
+ / #/.test(value) ||
102
+ /[\n"]/.test(value);
103
+ if (!needsQuoting)
104
+ return value;
105
+ return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
106
+ }
107
+ /**
108
+ * Serialize an operational skill to frontmatter + body.
109
+ *
110
+ * Keys are emitted in `KEY_ORDER` and optional keys are omitted when absent, so
111
+ * the same input always produces the same bytes — the ordering half of AC-17.
112
+ *
113
+ * @param skill - The skill to serialize.
114
+ * @returns Full file content, frontmatter first.
115
+ */
116
+ export function serializeOperationalSkill(skill) {
117
+ const meta = skill.meta;
118
+ const lines = ['---'];
119
+ for (const key of KEY_ORDER) {
120
+ const value = meta[key];
121
+ if (value === undefined || value === null)
122
+ continue;
123
+ if (Array.isArray(value)) {
124
+ if (value.length === 0)
125
+ continue;
126
+ lines.push(`${key}:`);
127
+ for (const item of value) {
128
+ lines.push(` - ${scalar(String(item))}`);
129
+ }
130
+ continue;
131
+ }
132
+ lines.push(`${key}: ${scalar(String(value))}`);
133
+ }
134
+ lines.push('---');
135
+ // Exactly one blank line between frontmatter and body, and the body's own
136
+ // leading whitespace is not preserved — both matter for determinism.
137
+ const body = skill.body.replace(/^\n+/, '');
138
+ return `${lines.join('\n')}\n\n${body}`;
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Parsing
142
+ // ---------------------------------------------------------------------------
143
+ /**
144
+ * Parse an operational skill file into frontmatter and body.
145
+ *
146
+ * @param raw - Full file content.
147
+ * @returns The parsed skill.
148
+ * @throws {OperationalSchemaError} On missing/unclosed frontmatter, a missing or
149
+ * wrongly-typed required field, or an invalid name.
150
+ */
151
+ export function parseOperationalSkill(raw) {
152
+ const lines = raw.split('\n');
153
+ if (lines[0]?.trim() !== '---') {
154
+ throw new OperationalSchemaError('missing YAML frontmatter delimiter');
155
+ }
156
+ let endIndex = -1;
157
+ for (let i = 1; i < lines.length; i++) {
158
+ if (lines[i]?.trim() === '---') {
159
+ endIndex = i;
160
+ break;
161
+ }
162
+ }
163
+ if (endIndex === -1) {
164
+ throw new OperationalSchemaError('unclosed YAML frontmatter');
165
+ }
166
+ let parsed;
167
+ try {
168
+ parsed = parseYaml(lines.slice(1, endIndex).join('\n'));
169
+ }
170
+ catch (err) {
171
+ throw new OperationalSchemaError(`invalid YAML frontmatter: ${err.message}`);
172
+ }
173
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
174
+ throw new OperationalSchemaError('frontmatter must be a YAML mapping');
175
+ }
176
+ const m = parsed;
177
+ for (const field of ['name', 'description', 'generated_by', 'content_version']) {
178
+ if (typeof m[field] !== 'string' || m[field].length === 0) {
179
+ throw new OperationalSchemaError(`frontmatter missing required field '${field}'`);
180
+ }
181
+ }
182
+ if (m.kind !== OPERATIONAL_KIND) {
183
+ throw new OperationalSchemaError(`frontmatter field 'kind' must be '${OPERATIONAL_KIND}' (found ${JSON.stringify(m.kind)})`);
184
+ }
185
+ if (m.trigger !== undefined && typeof m.trigger !== 'string') {
186
+ throw new OperationalSchemaError("frontmatter field 'trigger' must be a string");
187
+ }
188
+ if (m.paths !== undefined) {
189
+ if (!Array.isArray(m.paths) || m.paths.some((p) => typeof p !== 'string')) {
190
+ throw new OperationalSchemaError("frontmatter field 'paths' must be a list of strings");
191
+ }
192
+ }
193
+ validateOperationalSkillName(m.name);
194
+ const meta = {
195
+ name: m.name,
196
+ description: m.description,
197
+ kind: OPERATIONAL_KIND,
198
+ generated_by: m.generated_by,
199
+ content_version: m.content_version,
200
+ ...(m.trigger !== undefined ? { trigger: m.trigger } : {}),
201
+ ...(m.paths !== undefined ? { paths: m.paths } : {}),
202
+ };
203
+ return { meta, body: lines.slice(endIndex + 1).join('\n').replace(/^\n+/, '') };
204
+ }
205
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/operational/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Verification-step inlining and the generated-skill smoke check.
3
+ *
4
+ * Two responsibilities, both consequences of decision D-5:
5
+ *
6
+ * - `extractVerifySteps` reads the delimited region of
7
+ * `packages/content/guidance/content-operations.md` **from the installed content
8
+ * package**, so generation never depends on a project-level `.aidlc/guidance/`
9
+ * directory (AC-36). That matters because the guidance-layer machinery does not
10
+ * work: `{{guidance:}}` placeholders have no production resolver and bundled
11
+ * layers are never installed into a project.
12
+ * - `checkOperationalSkill` is the AC-38 smoke check. It is a plain function, not
13
+ * a test-framework test, because a generated skill lives in the user's repo,
14
+ * which may have no JS toolchain at all.
15
+ *
16
+ * Requirements: AC-35, AC-36, AC-37, AC-38
17
+ *
18
+ * @module
19
+ */
20
+ /** Filename of the verification-steps source inside the content package. */
21
+ export declare const VERIFY_SOURCE_FILE = "content-operations.md";
22
+ /** Opening delimiter of the machine-managed region. */
23
+ export declare const VERIFY_BEGIN = "<!-- aidlc:verify-steps:begin -->";
24
+ /** Closing delimiter of the machine-managed region. */
25
+ export declare const VERIFY_END = "<!-- aidlc:verify-steps:end -->";
26
+ /** Thrown when the verification source is missing or malformed. */
27
+ export declare class VerifySourceError extends Error {
28
+ constructor(reason: string);
29
+ }
30
+ /**
31
+ * Absolute path to the verification-steps source.
32
+ *
33
+ * @param contentRoot - Content package root (see `compile/content-root.ts`).
34
+ */
35
+ export declare function verifySourcePath(contentRoot: string): string;
36
+ /**
37
+ * Read the verification steps from the content package.
38
+ *
39
+ * Returns the bytes strictly between the delimiters, trimmed of surrounding blank
40
+ * lines. Byte-exactness matters: AC-37 asserts that the text in a generated skill
41
+ * is identical to this region.
42
+ *
43
+ * @param contentRoot - Content package root.
44
+ * @returns The verification-steps text.
45
+ * @throws {VerifySourceError} When the file is absent, the delimiters are missing
46
+ * or inverted, the region is empty, or it contains a `{{` sequence.
47
+ */
48
+ export declare function extractVerifySteps(contentRoot: string): string;
49
+ /**
50
+ * Wrap verification steps in the delimiters that mark them machine-managed.
51
+ *
52
+ * Re-emit replaces only the bytes between these markers, which is what lets a
53
+ * content-package update reach existing skills while leaving user-authored
54
+ * content untouched (AC-50 as scoped by the design).
55
+ *
56
+ * @param steps - Verification-steps text.
57
+ * @returns The delimited block.
58
+ */
59
+ export declare function wrapVerifySection(steps: string): string;
60
+ /**
61
+ * Extract the managed region from a generated skill body.
62
+ *
63
+ * @param body - Generated skill body.
64
+ * @returns The verification text, or null when no managed region is present.
65
+ */
66
+ export declare function readVerifySection(body: string): string | null;
67
+ /**
68
+ * Replace the managed region of a body, leaving every other byte alone.
69
+ *
70
+ * @param body - Existing skill body.
71
+ * @param steps - Replacement verification steps.
72
+ * @returns The updated body, or null when the body has no managed region.
73
+ */
74
+ export declare function replaceVerifySection(body: string, steps: string): string | null;
75
+ /** Result of the generated-skill smoke check. */
76
+ export interface SkillCheckResult {
77
+ ok: boolean;
78
+ /** Human-readable failures; empty when `ok`. */
79
+ failures: string[];
80
+ }
81
+ /**
82
+ * Smoke-check a generated operational skill.
83
+ *
84
+ * Assertions, in order:
85
+ * 1. The file parses against the operational-skill schema.
86
+ * 2. A verification section is present, and the managed region contains no `{{`.
87
+ * 3. Every path declared in `meta.paths` exists.
88
+ *
89
+ * Path checking reads **only** `meta.paths` — never prose, never fenced code
90
+ * blocks. That is how AC-38's false-failure exclusion is satisfied structurally
91
+ * rather than by heuristic. Likewise the `{{` check is scoped to the managed
92
+ * region, so a skill that legitimately documents Handlebars or `${{ }}` syntax in
93
+ * its own instructions does not fail its own smoke check.
94
+ *
95
+ * @param raw - Full content of the generated skill file.
96
+ * @param projectRoot - Root the declared paths are relative to.
97
+ * @returns Pass/fail plus every failure found (not just the first).
98
+ */
99
+ export declare function checkOperationalSkill(raw: string, projectRoot: string): SkillCheckResult;
100
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/operational/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,uDAAuD;AACvD,eAAO,MAAM,YAAY,sCAAsC,CAAC;AAEhE,uDAAuD;AACvD,eAAO,MAAM,UAAU,oCAAoC,CAAC;AAM5D,mEAAmE;AACnE,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,MAAM,EAAE,MAAM;CAI3B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAqC9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK7D;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/E;AAMD,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,gDAAgD;IAChD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAoCxF"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Verification-step inlining and the generated-skill smoke check.
3
+ *
4
+ * Two responsibilities, both consequences of decision D-5:
5
+ *
6
+ * - `extractVerifySteps` reads the delimited region of
7
+ * `packages/content/guidance/content-operations.md` **from the installed content
8
+ * package**, so generation never depends on a project-level `.aidlc/guidance/`
9
+ * directory (AC-36). That matters because the guidance-layer machinery does not
10
+ * work: `{{guidance:}}` placeholders have no production resolver and bundled
11
+ * layers are never installed into a project.
12
+ * - `checkOperationalSkill` is the AC-38 smoke check. It is a plain function, not
13
+ * a test-framework test, because a generated skill lives in the user's repo,
14
+ * which may have no JS toolchain at all.
15
+ *
16
+ * Requirements: AC-35, AC-36, AC-37, AC-38
17
+ *
18
+ * @module
19
+ */
20
+ import { existsSync, readFileSync } from 'node:fs';
21
+ import { join } from 'node:path';
22
+ import { OperationalSchemaError, parseOperationalSkill } from './schema.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Constants
25
+ // ---------------------------------------------------------------------------
26
+ /** Filename of the verification-steps source inside the content package. */
27
+ export const VERIFY_SOURCE_FILE = 'content-operations.md';
28
+ /** Opening delimiter of the machine-managed region. */
29
+ export const VERIFY_BEGIN = '<!-- aidlc:verify-steps:begin -->';
30
+ /** Closing delimiter of the machine-managed region. */
31
+ export const VERIFY_END = '<!-- aidlc:verify-steps:end -->';
32
+ // ---------------------------------------------------------------------------
33
+ // Extraction
34
+ // ---------------------------------------------------------------------------
35
+ /** Thrown when the verification source is missing or malformed. */
36
+ export class VerifySourceError extends Error {
37
+ constructor(reason) {
38
+ super(reason);
39
+ this.name = 'VerifySourceError';
40
+ }
41
+ }
42
+ /**
43
+ * Absolute path to the verification-steps source.
44
+ *
45
+ * @param contentRoot - Content package root (see `compile/content-root.ts`).
46
+ */
47
+ export function verifySourcePath(contentRoot) {
48
+ return join(contentRoot, 'guidance', VERIFY_SOURCE_FILE);
49
+ }
50
+ /**
51
+ * Read the verification steps from the content package.
52
+ *
53
+ * Returns the bytes strictly between the delimiters, trimmed of surrounding blank
54
+ * lines. Byte-exactness matters: AC-37 asserts that the text in a generated skill
55
+ * is identical to this region.
56
+ *
57
+ * @param contentRoot - Content package root.
58
+ * @returns The verification-steps text.
59
+ * @throws {VerifySourceError} When the file is absent, the delimiters are missing
60
+ * or inverted, the region is empty, or it contains a `{{` sequence.
61
+ */
62
+ export function extractVerifySteps(contentRoot) {
63
+ const path = verifySourcePath(contentRoot);
64
+ if (!existsSync(path)) {
65
+ throw new VerifySourceError(`verification source not found at ${path}; the installed @rasensio/aidlc-content package may be too old`);
66
+ }
67
+ const raw = readFileSync(path, 'utf8');
68
+ const beginIdx = raw.indexOf(VERIFY_BEGIN);
69
+ const endIdx = raw.indexOf(VERIFY_END);
70
+ if (beginIdx === -1 || endIdx === -1) {
71
+ throw new VerifySourceError(`${VERIFY_SOURCE_FILE} is missing the ${VERIFY_BEGIN} / ${VERIFY_END} delimiters`);
72
+ }
73
+ if (endIdx < beginIdx) {
74
+ throw new VerifySourceError(`${VERIFY_SOURCE_FILE} has inverted verify-steps delimiters`);
75
+ }
76
+ const region = raw.slice(beginIdx + VERIFY_BEGIN.length, endIdx).replace(/^\n+|\n+$/g, '');
77
+ if (region.length === 0) {
78
+ throw new VerifySourceError(`${VERIFY_SOURCE_FILE} has an empty verify-steps region`);
79
+ }
80
+ // AC-35: no generated file may contain an unresolved placeholder. Enforced at
81
+ // the source rather than trusted, since the region is copied verbatim.
82
+ if (region.includes('{{')) {
83
+ throw new VerifySourceError(`${VERIFY_SOURCE_FILE} verify-steps region contains a '{{' placeholder sequence; it is inlined literally and must not use placeholder syntax`);
84
+ }
85
+ return region;
86
+ }
87
+ /**
88
+ * Wrap verification steps in the delimiters that mark them machine-managed.
89
+ *
90
+ * Re-emit replaces only the bytes between these markers, which is what lets a
91
+ * content-package update reach existing skills while leaving user-authored
92
+ * content untouched (AC-50 as scoped by the design).
93
+ *
94
+ * @param steps - Verification-steps text.
95
+ * @returns The delimited block.
96
+ */
97
+ export function wrapVerifySection(steps) {
98
+ return `${VERIFY_BEGIN}\n${steps}\n${VERIFY_END}`;
99
+ }
100
+ /**
101
+ * Extract the managed region from a generated skill body.
102
+ *
103
+ * @param body - Generated skill body.
104
+ * @returns The verification text, or null when no managed region is present.
105
+ */
106
+ export function readVerifySection(body) {
107
+ const beginIdx = body.indexOf(VERIFY_BEGIN);
108
+ const endIdx = body.indexOf(VERIFY_END);
109
+ if (beginIdx === -1 || endIdx === -1 || endIdx < beginIdx)
110
+ return null;
111
+ return body.slice(beginIdx + VERIFY_BEGIN.length, endIdx).replace(/^\n+|\n+$/g, '');
112
+ }
113
+ /**
114
+ * Replace the managed region of a body, leaving every other byte alone.
115
+ *
116
+ * @param body - Existing skill body.
117
+ * @param steps - Replacement verification steps.
118
+ * @returns The updated body, or null when the body has no managed region.
119
+ */
120
+ export function replaceVerifySection(body, steps) {
121
+ const beginIdx = body.indexOf(VERIFY_BEGIN);
122
+ const endIdx = body.indexOf(VERIFY_END);
123
+ if (beginIdx === -1 || endIdx === -1 || endIdx < beginIdx)
124
+ return null;
125
+ return body.slice(0, beginIdx) + wrapVerifySection(steps) + body.slice(endIdx + VERIFY_END.length);
126
+ }
127
+ /**
128
+ * Smoke-check a generated operational skill.
129
+ *
130
+ * Assertions, in order:
131
+ * 1. The file parses against the operational-skill schema.
132
+ * 2. A verification section is present, and the managed region contains no `{{`.
133
+ * 3. Every path declared in `meta.paths` exists.
134
+ *
135
+ * Path checking reads **only** `meta.paths` — never prose, never fenced code
136
+ * blocks. That is how AC-38's false-failure exclusion is satisfied structurally
137
+ * rather than by heuristic. Likewise the `{{` check is scoped to the managed
138
+ * region, so a skill that legitimately documents Handlebars or `${{ }}` syntax in
139
+ * its own instructions does not fail its own smoke check.
140
+ *
141
+ * @param raw - Full content of the generated skill file.
142
+ * @param projectRoot - Root the declared paths are relative to.
143
+ * @returns Pass/fail plus every failure found (not just the first).
144
+ */
145
+ export function checkOperationalSkill(raw, projectRoot) {
146
+ const failures = [];
147
+ let parsed;
148
+ try {
149
+ parsed = parseOperationalSkill(raw);
150
+ }
151
+ catch (err) {
152
+ const reason = err instanceof OperationalSchemaError ? err.message : err.message;
153
+ // Nothing downstream is meaningful without a parse, so stop here.
154
+ return { ok: false, failures: [`does not parse: ${reason}`] };
155
+ }
156
+ const section = readVerifySection(parsed.body);
157
+ if (section === null) {
158
+ failures.push(`missing verification section (expected ${VERIFY_BEGIN} … ${VERIFY_END})`);
159
+ }
160
+ else {
161
+ if (section.length === 0) {
162
+ failures.push('verification section is empty');
163
+ }
164
+ if (section.includes('{{')) {
165
+ failures.push("verification section contains an unresolved '{{' placeholder — it must be literal text");
166
+ }
167
+ }
168
+ for (const declared of parsed.meta.paths ?? []) {
169
+ if (!existsSync(join(projectRoot, declared))) {
170
+ failures.push(`declared path does not exist: ${declared}`);
171
+ }
172
+ }
173
+ return { ok: failures.length === 0, failures };
174
+ }
175
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/operational/verify.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rasensio/aidlc",
3
- "version": "1.8.1",
3
+ "version": "1.9.1",
4
4
  "description": "AI Development Lifecycle Framework — structured lifecycle guidance for AI coding agents across platforms",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
@@ -24,7 +24,7 @@
24
24
  "commander": "15.0.0",
25
25
  "picomatch": "4.0.5",
26
26
  "yaml": "2.9.0",
27
- "@rasensio/aidlc-content": "1.8.1"
27
+ "@rasensio/aidlc-content": "1.9.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "22.15.32",