@rasensio/aidlc 1.8.0 → 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/cost.d.ts +2 -0
- package/dist/commands/cost.d.ts.map +1 -1
- package/dist/commands/cost.js +16 -1
- package/dist/commands/cost.js.map +1 -1
- 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/cost/providers/claude-code.d.ts +2 -0
- package/dist/cost/providers/claude-code.d.ts.map +1 -1
- package/dist/cost/providers/claude-code.js +34 -12
- package/dist/cost/providers/claude-code.js.map +1 -1
- package/dist/cost/providers/kiro.d.ts.map +1 -1
- package/dist/cost/providers/kiro.js +23 -10
- package/dist/cost/providers/kiro.js.map +1 -1
- package/dist/cost/providers/provider.d.ts +9 -4
- package/dist/cost/providers/provider.d.ts.map +1 -1
- package/dist/cost/providers/provider.js.map +1 -1
- package/dist/cost/recorder.d.ts +27 -3
- package/dist/cost/recorder.d.ts.map +1 -1
- package/dist/cost/recorder.js +116 -11
- package/dist/cost/recorder.js.map +1 -1
- package/dist/cost/sync.js +2 -2
- package/dist/cost/sync.js.map +1 -1
- package/dist/cost/types.d.ts +20 -0
- package/dist/cost/types.d.ts.map +1 -1
- package/dist/cost/types.js +2 -0
- package/dist/cost/types.js.map +1 -1
- package/dist/doctor/migrations/index.d.ts.map +1 -1
- package/dist/doctor/migrations/index.js +2 -0
- package/dist/doctor/migrations/index.js.map +1 -1
- package/dist/doctor/migrations/prune-capture-log.d.ts +11 -0
- package/dist/doctor/migrations/prune-capture-log.d.ts.map +1 -0
- package/dist/doctor/migrations/prune-capture-log.js +31 -0
- package/dist/doctor/migrations/prune-capture-log.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,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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
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 { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
|
|
18
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
19
|
+
import { adapters } from '../compile/adapters/index.js';
|
|
20
|
+
import { mergeBlock } from '../compile/merger.js';
|
|
21
|
+
import { canonicalBodyPath, packagerFor } from './packagers.js';
|
|
22
|
+
import { serializeOperationalSkill } from './schema.js';
|
|
23
|
+
/** Thrown when staging or committing fails. */
|
|
24
|
+
export class EmitError extends Error {
|
|
25
|
+
committed;
|
|
26
|
+
constructor(reason,
|
|
27
|
+
/** Ops whose rename already completed, when a commit fails part-way. */
|
|
28
|
+
committed = []) {
|
|
29
|
+
super(reason);
|
|
30
|
+
this.committed = committed;
|
|
31
|
+
this.name = 'EmitError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Planning
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
/**
|
|
38
|
+
* Build the InstallPlan for one operational skill.
|
|
39
|
+
*
|
|
40
|
+
* Every packager is resolved **before** any op is produced, so a mixed
|
|
41
|
+
* supported/unsupported `platforms:` list throws during planning with nothing
|
|
42
|
+
* staged — AC-47's all-or-nothing guarantee.
|
|
43
|
+
*
|
|
44
|
+
* @param req - The emission request.
|
|
45
|
+
* @returns A plan whose ops cover the canonical body plus every platform artifact.
|
|
46
|
+
* @throws {UnsupportedPlatformError} When any configured platform lacks packaging.
|
|
47
|
+
*/
|
|
48
|
+
export function planEmit(req) {
|
|
49
|
+
// Resolve first — this is the AC-47 gate.
|
|
50
|
+
const packagers = req.platforms.map((p) => packagerFor(p));
|
|
51
|
+
const ops = [];
|
|
52
|
+
const warnings = [];
|
|
53
|
+
// 1. Canonical body — the single source of full instructions (AC-13).
|
|
54
|
+
ops.push({
|
|
55
|
+
kind: 'create',
|
|
56
|
+
path: canonicalBodyPath(req.skill.meta.name),
|
|
57
|
+
content: serializeOperationalSkill(req.skill),
|
|
58
|
+
});
|
|
59
|
+
// 2. Per-skill platform artifacts.
|
|
60
|
+
for (const packager of packagers) {
|
|
61
|
+
ops.push(...packager.plan(req.skill));
|
|
62
|
+
}
|
|
63
|
+
// 3. Index artifacts, one per index-shaped platform.
|
|
64
|
+
for (const packager of packagers) {
|
|
65
|
+
if (!packager.planIndex)
|
|
66
|
+
continue;
|
|
67
|
+
const op = packager.planIndex(req.allSkills);
|
|
68
|
+
if (op)
|
|
69
|
+
ops.push(op);
|
|
70
|
+
}
|
|
71
|
+
// 4. Platform validators, where the platform defines one. This is how the
|
|
72
|
+
// ownership-marker placement stays honest: a first-line comment before
|
|
73
|
+
// frontmatter fails claude-code's and cursor's own checks.
|
|
74
|
+
for (const op of ops) {
|
|
75
|
+
for (const platform of req.platforms) {
|
|
76
|
+
const adapter = adapters.get(platform);
|
|
77
|
+
if (!adapter)
|
|
78
|
+
continue;
|
|
79
|
+
const result = adapter.validate(op);
|
|
80
|
+
warnings.push(...result.warnings);
|
|
81
|
+
if (!result.valid) {
|
|
82
|
+
throw new EmitError(`emitted file ${op.path} fails ${platform} validation: ${result.errors.join('; ')}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { ops, warnings };
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Content resolution
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
/** Final on-disk content for one op, including merge-block composition. */
|
|
92
|
+
function resolveContent(op, rootDir) {
|
|
93
|
+
if (op.kind === 'merge-block') {
|
|
94
|
+
const abs = join(rootDir, op.path);
|
|
95
|
+
const existing = existsSync(abs) ? readFileSync(abs, 'utf8') : '';
|
|
96
|
+
return mergeBlock(existing, op.blockId, op.content);
|
|
97
|
+
}
|
|
98
|
+
return op.content;
|
|
99
|
+
}
|
|
100
|
+
/** Reject any op path that escapes the project root. */
|
|
101
|
+
function assertInsideRoot(rootDir, opPath) {
|
|
102
|
+
const abs = join(rootDir, opPath);
|
|
103
|
+
const rel = relative(rootDir, abs);
|
|
104
|
+
if (rel.startsWith('..') || rel.startsWith(`..${sep}`)) {
|
|
105
|
+
throw new EmitError(`refusing to write outside the project root: ${opPath}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Staged execution (AC-45)
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
/**
|
|
112
|
+
* Apply a plan atomically-as-possible.
|
|
113
|
+
*
|
|
114
|
+
* Three phases:
|
|
115
|
+
* 1. **Resolve and validate** — compute final content for every op. Pure. Every
|
|
116
|
+
* predictable failure lands here, before a single byte is written.
|
|
117
|
+
* 2. **Stage** — write each op into one scratch directory outside every path the
|
|
118
|
+
* project enumerates. On failure, remove the scratch dir and abort; the tree is
|
|
119
|
+
* exactly as it was.
|
|
120
|
+
* 3. **Commit** — create parent directories, then rename each staged file onto its
|
|
121
|
+
* target.
|
|
122
|
+
*
|
|
123
|
+
* Honest bound: phase 3 is a rename sequence, not one transaction. A failure there
|
|
124
|
+
* reports which renames completed, and the residual state is repaired by
|
|
125
|
+
* `--re-emit`, which is idempotent. Directories this run created are removed on a
|
|
126
|
+
* phase-3 failure only when still empty.
|
|
127
|
+
*
|
|
128
|
+
* Skip-if-identical is preserved, so re-emitting unchanged input writes nothing
|
|
129
|
+
* (NFR-7, AC-17).
|
|
130
|
+
*
|
|
131
|
+
* @param plan - The plan to apply.
|
|
132
|
+
* @param rootDir - Absolute project root.
|
|
133
|
+
* @returns What was written and skipped.
|
|
134
|
+
*/
|
|
135
|
+
export function executePlanStaged(plan, rootDir) {
|
|
136
|
+
// --- Phase 1: resolve + validate ---------------------------------------
|
|
137
|
+
const resolved = [];
|
|
138
|
+
for (const op of plan.ops) {
|
|
139
|
+
assertInsideRoot(rootDir, op.path);
|
|
140
|
+
resolved.push({
|
|
141
|
+
op,
|
|
142
|
+
content: resolveContent(op, rootDir),
|
|
143
|
+
abs: join(rootDir, op.path),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const toWrite = resolved.filter((r) => !(existsSync(r.abs) && readFileSync(r.abs, 'utf8') === r.content));
|
|
147
|
+
const filesSkipped = resolved
|
|
148
|
+
.filter((r) => !toWrite.includes(r))
|
|
149
|
+
.map((r) => r.op.path);
|
|
150
|
+
if (toWrite.length === 0) {
|
|
151
|
+
return { filesWritten: [], filesSkipped, warnings: [...plan.warnings] };
|
|
152
|
+
}
|
|
153
|
+
// --- Phase 2: stage ----------------------------------------------------
|
|
154
|
+
const scratch = join(rootDir, '.aidlc', `.tmp-emit-${process.pid}`);
|
|
155
|
+
const staged = [];
|
|
156
|
+
try {
|
|
157
|
+
mkdirSync(scratch, { recursive: true });
|
|
158
|
+
for (let i = 0; i < toWrite.length; i++) {
|
|
159
|
+
const { op, content, abs } = toWrite[i];
|
|
160
|
+
// Flat, index-keyed names: no nesting to recreate, and no chance of a
|
|
161
|
+
// staged file colliding with another op's directory.
|
|
162
|
+
const tmp = join(scratch, `${i}.staged`);
|
|
163
|
+
writeFileSync(tmp, content, 'utf8');
|
|
164
|
+
staged.push({ tmp, abs, path: op.path });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
169
|
+
throw new EmitError(`staging failed, nothing was written: ${err.message}`);
|
|
170
|
+
}
|
|
171
|
+
// --- Phase 3: commit ---------------------------------------------------
|
|
172
|
+
const filesWritten = [];
|
|
173
|
+
const createdDirs = [];
|
|
174
|
+
try {
|
|
175
|
+
for (const { tmp, abs, path } of staged) {
|
|
176
|
+
const dir = dirname(abs);
|
|
177
|
+
if (!existsSync(dir)) {
|
|
178
|
+
mkdirSync(dir, { recursive: true });
|
|
179
|
+
createdDirs.push(dir);
|
|
180
|
+
}
|
|
181
|
+
renameSync(tmp, abs);
|
|
182
|
+
filesWritten.push(path);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
// Remove directories we created that are still empty, so a failed commit
|
|
187
|
+
// does not leave scaffolding behind.
|
|
188
|
+
for (const dir of createdDirs.reverse()) {
|
|
189
|
+
try {
|
|
190
|
+
rmSync(dir, { recursive: false });
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Non-empty (a rename landed inside it) — leave it.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
197
|
+
throw new EmitError(`commit failed after writing ${filesWritten.length}/${staged.length} files: ` +
|
|
198
|
+
`${err.message}. Repair with: aidlc add skill --re-emit`, filesWritten);
|
|
199
|
+
}
|
|
200
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
201
|
+
return { filesWritten, filesSkipped, warnings: [...plan.warnings] };
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Simulate `executePlanStaged` without touching the filesystem.
|
|
205
|
+
*
|
|
206
|
+
* Uses the same resolution, so `--dry-run` is provably equivalent to a real run.
|
|
207
|
+
*
|
|
208
|
+
* @param plan - The plan to simulate.
|
|
209
|
+
* @param rootDir - Absolute project root.
|
|
210
|
+
*/
|
|
211
|
+
export function dryRunPlanStaged(plan, rootDir) {
|
|
212
|
+
const filesWritten = [];
|
|
213
|
+
const filesSkipped = [];
|
|
214
|
+
for (const op of plan.ops) {
|
|
215
|
+
assertInsideRoot(rootDir, op.path);
|
|
216
|
+
const abs = join(rootDir, op.path);
|
|
217
|
+
const content = resolveContent(op, rootDir);
|
|
218
|
+
if (existsSync(abs) && readFileSync(abs, 'utf8') === content) {
|
|
219
|
+
filesSkipped.push(op.path);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
filesWritten.push(op.path);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return { filesWritten, filesSkipped, warnings: [...plan.warnings] };
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=emit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/operational/emit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Knowledge-graph registration for operational skills.
|
|
3
|
+
*
|
|
4
|
+
* Registers each generated skill so `aidlc knowledge query <name>` finds it and a
|
|
5
|
+
* developer returning months later does not write a second skill for the same job
|
|
6
|
+
* (US-6, AC-28…AC-30, AC-49).
|
|
7
|
+
*
|
|
8
|
+
* Two properties are load-bearing and neither is free:
|
|
9
|
+
*
|
|
10
|
+
* - **The entity type is not gate-counted.** `custom:operational-skill` rather than
|
|
11
|
+
* `module`, because the ideation seeding gate counts `module`, `convention`, and
|
|
12
|
+
* `depends-on` (`knowledge/gate-criterion.ts`). Registering skills as modules
|
|
13
|
+
* would let generated files satisfy a lifecycle gate meant to measure real
|
|
14
|
+
* architecture.
|
|
15
|
+
* - **The id is namespaced and collisions are refused.** `addEntity` merges into any
|
|
16
|
+
* pre-existing entity with the same id, and `mergeEntities` never overrides
|
|
17
|
+
* `type` — so an unnamespaced id colliding with an existing `module` would stay
|
|
18
|
+
* gate-counted *and* clobber an architecture fact. Registration therefore checks
|
|
19
|
+
* the resolved type first and refuses rather than merging.
|
|
20
|
+
*
|
|
21
|
+
* Registration is best-effort: failure warns and generation still succeeds (AC-30).
|
|
22
|
+
*
|
|
23
|
+
* Requirements: AC-28, AC-29, AC-30, AC-49
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
import type { OperationalSkill } from './schema.js';
|
|
28
|
+
/** Entity type for operational skills — deliberately not gate-counted (AC-28). */
|
|
29
|
+
export declare const OPERATIONAL_ENTITY_TYPE = "custom:operational-skill";
|
|
30
|
+
/** Id prefix keeping operational entities out of the general id namespace. */
|
|
31
|
+
export declare const OPERATIONAL_ID_PREFIX = "operational-skill-";
|
|
32
|
+
/** Outcome of a registration attempt. */
|
|
33
|
+
export interface RegistrationResult {
|
|
34
|
+
/** True when the entity now exists with the operational type. */
|
|
35
|
+
registered: boolean;
|
|
36
|
+
/** Non-fatal explanation when `registered` is false, or a merge note. */
|
|
37
|
+
warning?: string;
|
|
38
|
+
/** The entity id used. */
|
|
39
|
+
id: string;
|
|
40
|
+
}
|
|
41
|
+
/** Namespaced entity id for a skill name. */
|
|
42
|
+
export declare function operationalEntityId(name: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Register (or repair) an operational skill in the knowledge graph.
|
|
45
|
+
*
|
|
46
|
+
* Never throws: a graph problem must not lose a skill the user already confirmed
|
|
47
|
+
* (AC-30). Re-running for a skill whose files exist but whose entity is missing
|
|
48
|
+
* recreates it, which is the AC-49 repair path.
|
|
49
|
+
*
|
|
50
|
+
* @param projectRoot - Absolute project root.
|
|
51
|
+
* @param skill - The skill to register.
|
|
52
|
+
* @returns Whether the entity is now present, plus any warning to surface.
|
|
53
|
+
*/
|
|
54
|
+
export declare function registerOperationalSkill(projectRoot: string, skill: OperationalSkill): RegistrationResult;
|
|
55
|
+
/**
|
|
56
|
+
* Is this skill already registered with the operational type?
|
|
57
|
+
*
|
|
58
|
+
* Used to decide whether a re-run needs to repair registration (AC-49).
|
|
59
|
+
*
|
|
60
|
+
* @param projectRoot - Absolute project root.
|
|
61
|
+
* @param name - Skill name.
|
|
62
|
+
*/
|
|
63
|
+
export declare function isOperationalSkillRegistered(projectRoot: string, name: string): boolean;
|
|
64
|
+
//# sourceMappingURL=knowledge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../src/operational/knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,kFAAkF;AAClF,eAAO,MAAM,uBAAuB,6BAA6B,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,UAAU,EAAE,OAAO,CAAC;IACpB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,6CAA6C;AAC7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,gBAAgB,GACtB,kBAAkB,CAiEpB;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAoBvF"}
|