@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.
Files changed (75) 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/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +1 -10
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/update.d.ts.map +1 -1
  18. package/dist/commands/update.js +1 -9
  19. package/dist/commands/update.js.map +1 -1
  20. package/dist/compile/adapters/claude-code.d.ts.map +1 -1
  21. package/dist/compile/adapters/claude-code.js +3 -24
  22. package/dist/compile/adapters/claude-code.js.map +1 -1
  23. package/dist/compile/adapters/codex.d.ts.map +1 -1
  24. package/dist/compile/adapters/codex.js +3 -2
  25. package/dist/compile/adapters/codex.js.map +1 -1
  26. package/dist/compile/adapters/cursor.d.ts.map +1 -1
  27. package/dist/compile/adapters/cursor.js +4 -2
  28. package/dist/compile/adapters/cursor.js.map +1 -1
  29. package/dist/compile/adapters/kiro.d.ts.map +1 -1
  30. package/dist/compile/adapters/kiro.js +6 -10
  31. package/dist/compile/adapters/kiro.js.map +1 -1
  32. package/dist/compile/adapters/windsurf.d.ts.map +1 -1
  33. package/dist/compile/adapters/windsurf.js +9 -11
  34. package/dist/compile/adapters/windsurf.js.map +1 -1
  35. package/dist/compile/content-root.d.ts +22 -0
  36. package/dist/compile/content-root.d.ts.map +1 -0
  37. package/dist/compile/content-root.js +28 -0
  38. package/dist/compile/content-root.js.map +1 -0
  39. package/dist/compile/limits.d.ts +20 -0
  40. package/dist/compile/limits.d.ts.map +1 -0
  41. package/dist/compile/limits.js +20 -0
  42. package/dist/compile/limits.js.map +1 -0
  43. package/dist/compile/naming.d.ts +92 -0
  44. package/dist/compile/naming.d.ts.map +1 -0
  45. package/dist/compile/naming.js +105 -0
  46. package/dist/compile/naming.js.map +1 -0
  47. package/dist/operational/discover.d.ts +89 -0
  48. package/dist/operational/discover.d.ts.map +1 -0
  49. package/dist/operational/discover.js +132 -0
  50. package/dist/operational/discover.js.map +1 -0
  51. package/dist/operational/emit.d.ts +93 -0
  52. package/dist/operational/emit.d.ts.map +1 -0
  53. package/dist/operational/emit.js +227 -0
  54. package/dist/operational/emit.js.map +1 -0
  55. package/dist/operational/knowledge.d.ts +64 -0
  56. package/dist/operational/knowledge.d.ts.map +1 -0
  57. package/dist/operational/knowledge.js +144 -0
  58. package/dist/operational/knowledge.js.map +1 -0
  59. package/dist/operational/packagers.d.ts +67 -0
  60. package/dist/operational/packagers.d.ts.map +1 -0
  61. package/dist/operational/packagers.js +252 -0
  62. package/dist/operational/packagers.js.map +1 -0
  63. package/dist/operational/redact.d.ts +49 -0
  64. package/dist/operational/redact.d.ts.map +1 -0
  65. package/dist/operational/redact.js +135 -0
  66. package/dist/operational/redact.js.map +1 -0
  67. package/dist/operational/schema.d.ts +80 -0
  68. package/dist/operational/schema.d.ts.map +1 -0
  69. package/dist/operational/schema.js +205 -0
  70. package/dist/operational/schema.js.map +1 -0
  71. package/dist/operational/verify.d.ts +100 -0
  72. package/dist/operational/verify.d.ts.map +1 -0
  73. package/dist/operational/verify.js +175 -0
  74. package/dist/operational/verify.js.map +1 -0
  75. package/package.json +2 -2
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Per-platform packaging for operational skills.
3
+ *
4
+ * Mirrors the framework adapter seam — one canonical body, N platform-native
5
+ * files — but never passes through `loadSkills`/`parseSkillFile`, which require a
6
+ * lifecycle `phase` an operational skill does not have (D-1, AC-33).
7
+ *
8
+ * Two shapes, because two platforms have no natural one-skill-one-file form:
9
+ *
10
+ * - **Per-skill** (claude-code, kiro, cursor): one pointer file per skill.
11
+ * - **Index** (codex, windsurf): one artifact listing every operational skill.
12
+ * Codex reads only `AGENTS.md`; windsurf has a per-file character budget that
13
+ * O(n) rule files would exhaust.
14
+ *
15
+ * Every platform artifact is a **pointer** to the canonical body — the full
16
+ * instructions and the verification text live in
17
+ * `.aidlc/operational-skills/<name>.md` only. That scoping is what makes
18
+ * AC-35/AC-37/AC-38 well-defined.
19
+ *
20
+ * Requirements: AC-13, AC-14, AC-15, AC-16, AC-20, AC-47, AC-48
21
+ *
22
+ * @module
23
+ */
24
+ import { MAX_FILE_CHARS } from '../compile/limits.js';
25
+ import { canonicalSkillFilename, normalizeSkillName } from '../compile/naming.js';
26
+ // ---------------------------------------------------------------------------
27
+ // Constants
28
+ // ---------------------------------------------------------------------------
29
+ /** Directory holding canonical operational-skill bodies (AC-13, D-2). */
30
+ export const OPERATIONAL_DIR = '.aidlc/operational-skills';
31
+ /** Merge-block id for operational skills. Distinct from every framework id. */
32
+ export const OPERATIONAL_BLOCK_ID = 'aidlc-operational-skills';
33
+ /** Windsurf index rule path — unprefixed, so it cannot collide with framework rules. */
34
+ export const WINDSURF_INDEX_PATH = '.windsurf/rules/operational-skills.md';
35
+ // ---------------------------------------------------------------------------
36
+ // Ownership marker (AC-20)
37
+ // ---------------------------------------------------------------------------
38
+ /**
39
+ * Build the app-owned marker comment.
40
+ *
41
+ * Placement differs per target because two adapters validate that their files
42
+ * *begin* with frontmatter (`claude-code.ts`, `cursor.ts`), so a first-line
43
+ * comment would fail their own validators.
44
+ */
45
+ export function ownershipMarker(name) {
46
+ return `<!-- aidlc:operational-skill ${name} — app-owned, not framework-managed -->`;
47
+ }
48
+ /** Marker for an index artifact covering many skills. */
49
+ function indexMarker() {
50
+ return '<!-- aidlc:operational-skills — app-owned, not framework-managed -->';
51
+ }
52
+ /** Thrown when a configured platform has no operational packaging (AC-16). */
53
+ export class UnsupportedPlatformError extends Error {
54
+ platform;
55
+ constructor(platform, supported) {
56
+ super(`platform '${platform}' has no operational-skill packaging; ` +
57
+ `supported platforms are: ${supported.join(', ')}`);
58
+ this.platform = platform;
59
+ this.name = 'UnsupportedPlatformError';
60
+ }
61
+ }
62
+ /** Relative path of a skill's canonical body. */
63
+ export function canonicalBodyPath(name) {
64
+ return `${OPERATIONAL_DIR}/${canonicalSkillFilename(name)}`;
65
+ }
66
+ /** Pointer sentence shared by every platform artifact. */
67
+ function pointerLine(skill) {
68
+ return `Read \`${canonicalBodyPath(skill.meta.name)}\` and follow its instructions.`;
69
+ }
70
+ /**
71
+ * Platform directory/file segment for an operational skill.
72
+ *
73
+ * `prefix: false` is the whole point — the `aidlc-` namespace stays
74
+ * framework-owned (AC-19, AC-41).
75
+ */
76
+ function segment(name) {
77
+ return normalizeSkillName(name, { prefix: false });
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Per-skill packagers
81
+ // ---------------------------------------------------------------------------
82
+ /** claude-code: `.claude/skills/<name>/SKILL.md` (AC-14). */
83
+ const claudeCodePackager = {
84
+ platform: 'claude-code',
85
+ plan(skill) {
86
+ const dir = segment(skill.meta.name);
87
+ // Frontmatter first — claude-code's validator requires `---\n` at byte 0.
88
+ const content = [
89
+ '---',
90
+ `name: ${dir}`,
91
+ `description: ${skill.meta.description}`,
92
+ '---',
93
+ '',
94
+ ownershipMarker(skill.meta.name),
95
+ '',
96
+ pointerLine(skill),
97
+ '',
98
+ ].join('\n');
99
+ return [{ kind: 'create', path: `.claude/skills/${dir}/SKILL.md`, content }];
100
+ },
101
+ };
102
+ /** kiro: `.kiro/skills/<name>/SKILL.md`. */
103
+ const kiroPackager = {
104
+ platform: 'kiro',
105
+ plan(skill) {
106
+ const dir = segment(skill.meta.name);
107
+ const content = [
108
+ '---',
109
+ `name: ${dir}`,
110
+ `description: ${skill.meta.description}`,
111
+ '---',
112
+ '',
113
+ ownershipMarker(skill.meta.name),
114
+ '',
115
+ pointerLine(skill),
116
+ '',
117
+ ].join('\n');
118
+ return [{ kind: 'create', path: `.kiro/skills/${dir}/SKILL.md`, content }];
119
+ },
120
+ };
121
+ /**
122
+ * cursor: `.cursor/rules/<name>.mdc`.
123
+ *
124
+ * The marker rides in frontmatter as `aidlc_kind`. Cursor's validator requires
125
+ * only that `description:` and `alwaysApply:` be present, so an extra key is
126
+ * permitted — verified before relying on it.
127
+ */
128
+ const cursorPackager = {
129
+ platform: 'cursor',
130
+ plan(skill) {
131
+ const file = `${segment(skill.meta.name)}.mdc`;
132
+ const content = [
133
+ '---',
134
+ `description: ${skill.meta.description}`,
135
+ 'globs:',
136
+ 'alwaysApply: false',
137
+ 'aidlc_kind: operational',
138
+ '---',
139
+ '',
140
+ pointerLine(skill),
141
+ '',
142
+ ].join('\n');
143
+ return [{ kind: 'create', path: `.cursor/rules/${file}`, content }];
144
+ },
145
+ };
146
+ // ---------------------------------------------------------------------------
147
+ // Index packagers
148
+ // ---------------------------------------------------------------------------
149
+ /** Shared index body: marker, heading, one bullet per skill. */
150
+ function indexLines(skills) {
151
+ const lines = [indexMarker(), '', '# Operational Skills', ''];
152
+ if (skills.length === 0) {
153
+ lines.push('_No operational skills are defined in this project._');
154
+ return lines;
155
+ }
156
+ lines.push('App-owned skills for repeatable operations. Each entry points at its canonical', 'body; read that file and follow its instructions.', '');
157
+ // Sorted by name so output does not depend on directory-read order (AC-17).
158
+ for (const skill of [...skills].sort((a, b) => a.meta.name.localeCompare(b.meta.name))) {
159
+ lines.push(`- **${skill.meta.name}** — ${skill.meta.description}. ` +
160
+ `Read \`${canonicalBodyPath(skill.meta.name)}\`.`);
161
+ }
162
+ return lines;
163
+ }
164
+ /**
165
+ * codex: one merge-block in `AGENTS.md`.
166
+ *
167
+ * Shares the file with the framework block but never its id — the framework uses
168
+ * `aidlc` (`codex.ts:161`), and `mergeBlock` preserves every byte outside its own
169
+ * delimiters, so the two coexist (AC-43 as refined by DD-2).
170
+ */
171
+ const codexPackager = {
172
+ platform: 'codex',
173
+ plan() {
174
+ return [];
175
+ },
176
+ planIndex(skills) {
177
+ if (skills.length === 0)
178
+ return null;
179
+ return {
180
+ kind: 'merge-block',
181
+ path: 'AGENTS.md',
182
+ blockId: OPERATIONAL_BLOCK_ID,
183
+ content: indexLines(skills).join('\n'),
184
+ };
185
+ },
186
+ };
187
+ /**
188
+ * windsurf: one index rule file.
189
+ *
190
+ * One file regardless of skill count, but O(n) characters within it — so the
191
+ * per-file cap binds sooner, not later. On exceeding it the index degrades to a
192
+ * directory pointer rather than dropping the list, which keeps operational skills
193
+ * discoverable (US-6). The cross-plan total budget is deliberately not enforced;
194
+ * see AC-48's recorded limitation.
195
+ */
196
+ const windsurfPackager = {
197
+ platform: 'windsurf',
198
+ plan() {
199
+ return [];
200
+ },
201
+ planIndex(skills) {
202
+ if (skills.length === 0)
203
+ return null;
204
+ const full = indexLines(skills).join('\n') + '\n';
205
+ if (full.length <= MAX_FILE_CHARS) {
206
+ return { kind: 'create', path: WINDSURF_INDEX_PATH, content: full };
207
+ }
208
+ const degraded = [
209
+ indexMarker(),
210
+ '',
211
+ '# Operational Skills',
212
+ '',
213
+ `This project defines ${skills.length} app-owned operational skills — too many to`,
214
+ 'list within the windsurf rule size limit.',
215
+ '',
216
+ `Read \`${OPERATIONAL_DIR}/\` and follow the instructions in the relevant skill.`,
217
+ '',
218
+ ].join('\n');
219
+ return { kind: 'create', path: WINDSURF_INDEX_PATH, content: degraded };
220
+ },
221
+ };
222
+ // ---------------------------------------------------------------------------
223
+ // Registry
224
+ // ---------------------------------------------------------------------------
225
+ const PACKAGERS = new Map([
226
+ ['claude-code', claudeCodePackager],
227
+ ['kiro', kiroPackager],
228
+ ['cursor', cursorPackager],
229
+ ['codex', codexPackager],
230
+ ['windsurf', windsurfPackager],
231
+ ]);
232
+ /** Platforms with operational packaging, sorted for stable error messages. */
233
+ export const supportedOperationalPlatforms = [...PACKAGERS.keys()].sort();
234
+ /**
235
+ * Look up the packager for a platform.
236
+ *
237
+ * @param platform - Platform identifier from `.aidlc/config.yaml`.
238
+ * @returns The packager.
239
+ * @throws {UnsupportedPlatformError} When the platform has no packaging (AC-16).
240
+ */
241
+ export function packagerFor(platform) {
242
+ const packager = PACKAGERS.get(platform);
243
+ if (!packager) {
244
+ throw new UnsupportedPlatformError(platform, supportedOperationalPlatforms);
245
+ }
246
+ return packager;
247
+ }
248
+ /** Does this platform have operational packaging? */
249
+ export function hasOperationalPackaging(platform) {
250
+ return PACKAGERS.has(platform);
251
+ }
252
+ //# sourceMappingURL=packagers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packagers.js","sourceRoot":"","sources":["../../src/operational/packagers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Best-effort credential redaction for generated operational skills.
3
+ *
4
+ * Two rules, and the second matters as much as the first (AC-11):
5
+ *
6
+ * - Credential **values** are redacted. A generated skill is instructions an
7
+ * agent will later execute, and it is committed to the repo, so a pasted token
8
+ * would become a secret at rest (NFR-3).
9
+ * - Credential **references** are preserved. `$GITHUB_TOKEN`,
10
+ * `op://vault/item/field`, `arn:aws:secretsmanager:...` are legitimate
11
+ * operational content; stripping them would produce a skill that cannot work.
12
+ *
13
+ * **This is explicitly best-effort and not a security guarantee.** Detection is
14
+ * pattern- plus entropy-based, so novel credential formats will pass through. The
15
+ * real control is the confirmation gate: redaction runs *before* the preview is
16
+ * rendered (AC-44), so a human sees the redacted text and nothing reaches disk
17
+ * without their approval. Callers must not present this as a guarantee to users.
18
+ *
19
+ * Requirements: AC-11, AC-44, NFR-3
20
+ *
21
+ * @module
22
+ */
23
+ /** Placeholder substituted for a redacted value. */
24
+ export declare const REDACTION_PLACEHOLDER = "<REDACTED>";
25
+ /** Result of a redaction pass. */
26
+ export interface RedactionResult {
27
+ /** Text with detected credential values replaced. */
28
+ text: string;
29
+ /**
30
+ * Human-readable labels for what was redacted (never the values themselves —
31
+ * echoing them back would defeat the purpose).
32
+ */
33
+ redacted: string[];
34
+ }
35
+ /**
36
+ * Redact credential values from text, preserving credential references.
37
+ *
38
+ * @param text - Text that may contain credentials.
39
+ * @returns The redacted text plus labels describing what was removed.
40
+ */
41
+ export declare function redactSecrets(text: string): RedactionResult;
42
+ /**
43
+ * Convenience: did this text contain anything that looked like a credential?
44
+ *
45
+ * @param text - Text to inspect.
46
+ * @returns True when `redactSecrets` would change the text.
47
+ */
48
+ export declare function containsSecrets(text: string): boolean;
49
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/operational/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD,kCAAkC;AAClC,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAkC3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Best-effort credential redaction for generated operational skills.
3
+ *
4
+ * Two rules, and the second matters as much as the first (AC-11):
5
+ *
6
+ * - Credential **values** are redacted. A generated skill is instructions an
7
+ * agent will later execute, and it is committed to the repo, so a pasted token
8
+ * would become a secret at rest (NFR-3).
9
+ * - Credential **references** are preserved. `$GITHUB_TOKEN`,
10
+ * `op://vault/item/field`, `arn:aws:secretsmanager:...` are legitimate
11
+ * operational content; stripping them would produce a skill that cannot work.
12
+ *
13
+ * **This is explicitly best-effort and not a security guarantee.** Detection is
14
+ * pattern- plus entropy-based, so novel credential formats will pass through. The
15
+ * real control is the confirmation gate: redaction runs *before* the preview is
16
+ * rendered (AC-44), so a human sees the redacted text and nothing reaches disk
17
+ * without their approval. Callers must not present this as a guarantee to users.
18
+ *
19
+ * Requirements: AC-11, AC-44, NFR-3
20
+ *
21
+ * @module
22
+ */
23
+ /** Placeholder substituted for a redacted value. */
24
+ export const REDACTION_PLACEHOLDER = '<REDACTED>';
25
+ /**
26
+ * Named provider token shapes. Anchored on distinctive prefixes so they do not
27
+ * fire on ordinary prose.
28
+ */
29
+ const TOKEN_PATTERNS = [
30
+ { label: 'GitHub token', re: /\bgh[pousr]_[A-Za-z0-9]{16,}\b/g },
31
+ { label: 'GitHub fine-grained token', re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g },
32
+ { label: 'AWS access key id', re: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
33
+ { label: 'Slack token', re: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
34
+ { label: 'Google API key', re: /\bAIza[0-9A-Za-z_-]{35}\b/g },
35
+ { label: 'Stripe key', re: /\b[sr]k_(?:live|test)_[0-9A-Za-z]{16,}\b/g },
36
+ { label: 'OpenAI key', re: /\bsk-[A-Za-z0-9]{20,}\b/g },
37
+ { label: 'Anthropic key', re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g },
38
+ { label: 'npm token', re: /\bnpm_[A-Za-z0-9]{30,}\b/g },
39
+ { label: 'JSON Web Token', re: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
40
+ { label: 'private key block', re: /-----BEGIN (?:[A-Z ]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z ]+ )?PRIVATE KEY-----/g },
41
+ ];
42
+ /**
43
+ * `KEY=value` / `key: value` assignments whose *name* implies a secret. The value
44
+ * is redacted only when it is a literal — a `$VAR` or secret-manager reference on
45
+ * the right-hand side is a reference, not a value, and is kept.
46
+ */
47
+ const ASSIGNMENT_RE = /\b([A-Za-z_][A-Za-z0-9_]*(?:SECRET|TOKEN|PASSWORD|PASSWD|APIKEY|API_KEY|ACCESS_KEY|PRIVATE_KEY|CREDENTIAL)[A-Za-z0-9_]*)\s*[:=]\s*(['"]?)([^\s'"#]+)\2/gi;
48
+ /**
49
+ * Right-hand sides that are references rather than values, and must survive.
50
+ * Preserving these is required by AC-11, not merely nice to have.
51
+ */
52
+ const REFERENCE_RE = /^(?:\$|\$\{|%|<|op:\/\/|vault:|secret:|arn:aws:secretsmanager:|projects\/[^/]+\/secrets\/|sm:\/\/|env:|process\.env)/i;
53
+ /** Shannon entropy in bits per character. */
54
+ function entropy(s) {
55
+ const freq = new Map();
56
+ for (const ch of s)
57
+ freq.set(ch, (freq.get(ch) ?? 0) + 1);
58
+ let h = 0;
59
+ for (const n of freq.values()) {
60
+ const p = n / s.length;
61
+ h -= p * Math.log2(p);
62
+ }
63
+ return h;
64
+ }
65
+ /**
66
+ * Does this look like a high-entropy secret rather than a word or a path?
67
+ *
68
+ * Conservative on purpose: a false positive silently mangles a legitimate skill,
69
+ * and the confirmation gate is the real backstop.
70
+ */
71
+ function looksLikeSecret(token) {
72
+ if (token.length < 24)
73
+ return false;
74
+ if (REFERENCE_RE.test(token))
75
+ return false;
76
+ // Paths, URLs, and dotted identifiers are common and are not secrets.
77
+ if (/[/\\]/.test(token) || token.includes('://'))
78
+ return false;
79
+ // Require mixed character classes — long lowercase words are not secrets.
80
+ const classes = [/[a-z]/, /[A-Z]/, /[0-9]/].filter((re) => re.test(token)).length;
81
+ if (classes < 2)
82
+ return false;
83
+ return entropy(token) >= 3.5;
84
+ }
85
+ /**
86
+ * Redact credential values from text, preserving credential references.
87
+ *
88
+ * @param text - Text that may contain credentials.
89
+ * @returns The redacted text plus labels describing what was removed.
90
+ */
91
+ export function redactSecrets(text) {
92
+ const redacted = [];
93
+ let out = text;
94
+ // 1. Named provider token shapes.
95
+ for (const { label, re } of TOKEN_PATTERNS) {
96
+ out = out.replace(re, () => {
97
+ if (!redacted.includes(label))
98
+ redacted.push(label);
99
+ return REDACTION_PLACEHOLDER;
100
+ });
101
+ }
102
+ // 2. Secret-named assignments with a literal right-hand side.
103
+ out = out.replace(ASSIGNMENT_RE, (match, key, quote, value) => {
104
+ if (REFERENCE_RE.test(value))
105
+ return match; // a reference — preserve (AC-11)
106
+ if (value === REDACTION_PLACEHOLDER)
107
+ return match; // already handled above
108
+ const label = `value assigned to ${key}`;
109
+ if (!redacted.includes(label))
110
+ redacted.push(label);
111
+ return `${key}=${quote}${REDACTION_PLACEHOLDER}${quote}`.replace('=', match.includes(':') && !match.includes('=') ? ': ' : '=');
112
+ });
113
+ // 3. Free-standing high-entropy strings.
114
+ out = out.replace(/[A-Za-z0-9+/_=-]{24,}/g, (token) => {
115
+ if (token === REDACTION_PLACEHOLDER)
116
+ return token;
117
+ if (!looksLikeSecret(token))
118
+ return token;
119
+ const label = 'high-entropy string';
120
+ if (!redacted.includes(label))
121
+ redacted.push(label);
122
+ return REDACTION_PLACEHOLDER;
123
+ });
124
+ return { text: out, redacted };
125
+ }
126
+ /**
127
+ * Convenience: did this text contain anything that looked like a credential?
128
+ *
129
+ * @param text - Text to inspect.
130
+ * @returns True when `redactSecrets` would change the text.
131
+ */
132
+ export function containsSecrets(text) {
133
+ return redactSecrets(text).redacted.length > 0;
134
+ }
135
+ //# sourceMappingURL=redact.js.map
@@ -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"}