contract-driven-delivery 2.0.15 → 2.0.16
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/CHANGELOG.md +21 -0
- package/dist/cli/index.js +29 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.16] - 2026-05-06
|
|
4
|
+
|
|
5
|
+
New-change scaffold hardening so freshly opened proposals use the installed
|
|
6
|
+
kit version even when an existing project has stale templates on disk.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **`cdd-kit new` stamps `tasks.yml` with the real change id**: new changes no
|
|
11
|
+
longer start with the `<change-id>` placeholder in the machine-validated task
|
|
12
|
+
metadata.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **Fresh proposals ignore stale project templates**: regression coverage now
|
|
17
|
+
locks `cdd-kit new` to bundled package templates, so old
|
|
18
|
+
`specs/templates/*` files in a user repo cannot leak into a newly created
|
|
19
|
+
change.
|
|
20
|
+
- **Postinstall sync coverage includes workflow skills**: regression coverage
|
|
21
|
+
now verifies npm postinstall updates standalone skills such as `/cdd-new`,
|
|
22
|
+
keeping agent-log instructions aligned with the installed gate.
|
|
23
|
+
|
|
3
24
|
## [2.0.15] - 2026-05-06
|
|
4
25
|
|
|
5
26
|
Prompt guidance patch for agent-log evidence and closeout learning ownership.
|
package/dist/cli/index.js
CHANGED
|
@@ -8678,7 +8678,7 @@ __export(migrate_exports, {
|
|
|
8678
8678
|
});
|
|
8679
8679
|
import { join as join18 } from "path";
|
|
8680
8680
|
import { cpSync as cpSync2, existsSync as existsSync15, mkdirSync as mkdirSync7, readdirSync as readdirSync8, readFileSync as readFileSync18, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
8681
|
-
import
|
|
8681
|
+
import yaml2 from "js-yaml";
|
|
8682
8682
|
function backupChangeDir(cwd, changeId, sessionStamp) {
|
|
8683
8683
|
const backupRoot = join18(cwd, ".cdd", "migrate-backup", sessionStamp);
|
|
8684
8684
|
const backupDir2 = join18(backupRoot, changeId);
|
|
@@ -8854,7 +8854,7 @@ function migrateTasksFile(changeId, changeDir, enableContextGovernance, detected
|
|
|
8854
8854
|
out["section"] = r.section;
|
|
8855
8855
|
return out;
|
|
8856
8856
|
});
|
|
8857
|
-
const yamlOut =
|
|
8857
|
+
const yamlOut = yaml2.dump(data, { lineWidth: -1, noRefs: true });
|
|
8858
8858
|
pendingWrites.push({ path: newPath, content: yamlOut });
|
|
8859
8859
|
pendingDeletes.push({ path: legacyPath });
|
|
8860
8860
|
changed.push(`tasks.md -> tasks.yml (${tasksRows.length} task(s) migrated)`);
|
|
@@ -8922,7 +8922,7 @@ function migrateAgentLogs(changeDir, changed, pendingWrites, pendingDeletes) {
|
|
|
8922
8922
|
continue;
|
|
8923
8923
|
const raw = readFileSync18(fullPath, "utf8");
|
|
8924
8924
|
const parsed = parseLegacyAgentLog(raw);
|
|
8925
|
-
const yamlOut =
|
|
8925
|
+
const yamlOut = yaml2.dump(parsed, { lineWidth: -1, noRefs: true });
|
|
8926
8926
|
pendingWrites.push({ path: yamlFull, content: yamlOut });
|
|
8927
8927
|
pendingDeletes.push({ path: fullPath });
|
|
8928
8928
|
changed.push(`agent-log/${f} -> agent-log/${yamlName}`);
|
|
@@ -10146,7 +10146,7 @@ __export(archive_exports, {
|
|
|
10146
10146
|
});
|
|
10147
10147
|
import { join as join23 } from "path";
|
|
10148
10148
|
import { existsSync as existsSync19, mkdirSync as mkdirSync10, renameSync as renameSync2, readFileSync as readFileSync23, writeFileSync as writeFileSync11, appendFileSync, cpSync as cpSync3, rmSync as rmSync3 } from "fs";
|
|
10149
|
-
import
|
|
10149
|
+
import yaml3 from "js-yaml";
|
|
10150
10150
|
async function archive(changeId) {
|
|
10151
10151
|
const cwd = process.cwd();
|
|
10152
10152
|
const changeDir = join23(cwd, "specs", "changes", changeId);
|
|
@@ -10166,7 +10166,7 @@ async function archive(changeId) {
|
|
|
10166
10166
|
if (existsSync19(tasksPath)) {
|
|
10167
10167
|
try {
|
|
10168
10168
|
const raw = readFileSync23(tasksPath, "utf8");
|
|
10169
|
-
const data =
|
|
10169
|
+
const data = yaml3.load(raw);
|
|
10170
10170
|
if (data?.status === "gate-blocked") {
|
|
10171
10171
|
log.warn("tasks.yml has status: gate-blocked \u2014 archiving anyway (change was paused).");
|
|
10172
10172
|
}
|
|
@@ -10222,7 +10222,7 @@ __export(abandon_exports, {
|
|
|
10222
10222
|
});
|
|
10223
10223
|
import { join as join24 } from "path";
|
|
10224
10224
|
import { existsSync as existsSync20, readFileSync as readFileSync24, writeFileSync as writeFileSync12, appendFileSync as appendFileSync2, mkdirSync as mkdirSync11 } from "fs";
|
|
10225
|
-
import
|
|
10225
|
+
import yaml4 from "js-yaml";
|
|
10226
10226
|
async function abandon(changeId, opts) {
|
|
10227
10227
|
const cwd = process.cwd();
|
|
10228
10228
|
const changeDir = join24(cwd, "specs", "changes", changeId);
|
|
@@ -10233,12 +10233,12 @@ async function abandon(changeId, opts) {
|
|
|
10233
10233
|
}
|
|
10234
10234
|
if (existsSync20(tasksPath)) {
|
|
10235
10235
|
const raw = readFileSync24(tasksPath, "utf8");
|
|
10236
|
-
const data =
|
|
10236
|
+
const data = yaml4.load(raw) ?? {};
|
|
10237
10237
|
data["status"] = "abandoned";
|
|
10238
10238
|
if (!data["change-id"]) {
|
|
10239
10239
|
data["change-id"] = changeId;
|
|
10240
10240
|
}
|
|
10241
|
-
writeFileSync12(tasksPath,
|
|
10241
|
+
writeFileSync12(tasksPath, yaml4.dump(data, { lineWidth: -1, noRefs: true }), "utf8");
|
|
10242
10242
|
}
|
|
10243
10243
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10244
10244
|
const archiveDir = join24(cwd, "specs", "archive");
|
|
@@ -10276,7 +10276,7 @@ __export(list_changes_exports, {
|
|
|
10276
10276
|
});
|
|
10277
10277
|
import { join as join25 } from "path";
|
|
10278
10278
|
import { existsSync as existsSync21, readdirSync as readdirSync13, readFileSync as readFileSync25 } from "fs";
|
|
10279
|
-
import
|
|
10279
|
+
import yaml5 from "js-yaml";
|
|
10280
10280
|
async function listChanges() {
|
|
10281
10281
|
const cwd = process.cwd();
|
|
10282
10282
|
const changesDir = join25(cwd, "specs", "changes");
|
|
@@ -10296,7 +10296,7 @@ async function listChanges() {
|
|
|
10296
10296
|
if (existsSync21(tasksPath)) {
|
|
10297
10297
|
try {
|
|
10298
10298
|
const raw = readFileSync25(tasksPath, "utf8");
|
|
10299
|
-
const data =
|
|
10299
|
+
const data = yaml5.load(raw);
|
|
10300
10300
|
if (data?.status)
|
|
10301
10301
|
status = data.status;
|
|
10302
10302
|
pending = (data?.tasks ?? []).filter((t) => t.status === "pending").length;
|
|
@@ -11104,7 +11104,6 @@ init_paths();
|
|
|
11104
11104
|
import { join as join9, relative as relative3 } from "path";
|
|
11105
11105
|
import { createHash as createHash4 } from "crypto";
|
|
11106
11106
|
import { existsSync as existsSync8, readFileSync as readFileSync8, readdirSync as readdirSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
11107
|
-
import yaml from "js-yaml";
|
|
11108
11107
|
init_logger();
|
|
11109
11108
|
init_context_scan();
|
|
11110
11109
|
init_digest();
|
|
@@ -11173,6 +11172,20 @@ function parseDependsOn(raw) {
|
|
|
11173
11172
|
return [];
|
|
11174
11173
|
return raw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
11175
11174
|
}
|
|
11175
|
+
function applyScaffoldMetadata(tasksPath, changeId, dependencies) {
|
|
11176
|
+
if (!existsSync8(tasksPath))
|
|
11177
|
+
return;
|
|
11178
|
+
let raw = readFileSync8(tasksPath, "utf8");
|
|
11179
|
+
raw = raw.replace(/^change-id:\s*<change-id>\s*$/m, `change-id: ${changeId}`);
|
|
11180
|
+
if (dependencies.length > 0) {
|
|
11181
|
+
const dependsOn = [
|
|
11182
|
+
"depends-on:",
|
|
11183
|
+
...dependencies.map((dep) => ` - ${JSON.stringify(dep)}`)
|
|
11184
|
+
].join("\n");
|
|
11185
|
+
raw = raw.replace(/^depends-on:\s*\[\]\s*$/m, dependsOn);
|
|
11186
|
+
}
|
|
11187
|
+
writeFileSync4(tasksPath, raw, "utf8");
|
|
11188
|
+
}
|
|
11176
11189
|
async function newChange(name, opts) {
|
|
11177
11190
|
if (!SAFE_NAME.test(name)) {
|
|
11178
11191
|
log.error(`Invalid change name: "${name}". Use letters, numbers, hyphens, or underscores (max 64 chars).`);
|
|
@@ -11220,15 +11233,10 @@ async function newChange(name, opts) {
|
|
|
11220
11233
|
log.dim(tmpl);
|
|
11221
11234
|
written += 1;
|
|
11222
11235
|
}
|
|
11236
|
+
const tasksPath = join9(changeDir, "tasks.yml");
|
|
11237
|
+
applyScaffoldMetadata(tasksPath, name, dependencies);
|
|
11223
11238
|
if (dependencies.length > 0) {
|
|
11224
|
-
|
|
11225
|
-
if (existsSync8(tasksPath)) {
|
|
11226
|
-
const raw = readFileSync8(tasksPath, "utf8");
|
|
11227
|
-
const data = yaml.load(raw) ?? {};
|
|
11228
|
-
data["depends-on"] = dependencies;
|
|
11229
|
-
writeFileSync4(tasksPath, yaml.dump(data, { lineWidth: -1, noRefs: true }), "utf8");
|
|
11230
|
-
log.dim(`depends-on: ${dependencies.join(", ")}`);
|
|
11231
|
-
}
|
|
11239
|
+
log.dim(`depends-on: ${dependencies.join(", ")}`);
|
|
11232
11240
|
}
|
|
11233
11241
|
log.blank();
|
|
11234
11242
|
log.ok(`${written} template(s) created in specs/changes/${name}`);
|
|
@@ -11330,7 +11338,7 @@ init_logger();
|
|
|
11330
11338
|
import { existsSync as existsSync13, readFileSync as readFileSync16, readdirSync as readdirSync7 } from "fs";
|
|
11331
11339
|
import { homedir as homedir3 } from "os";
|
|
11332
11340
|
import { join as join16 } from "path";
|
|
11333
|
-
import
|
|
11341
|
+
import yaml from "js-yaml";
|
|
11334
11342
|
import picomatch2 from "picomatch";
|
|
11335
11343
|
|
|
11336
11344
|
// src/schemas/agent-log.schema.ts
|
|
@@ -11571,7 +11579,7 @@ function loadContextPolicy(cwd) {
|
|
|
11571
11579
|
function loadYamlFile(path) {
|
|
11572
11580
|
try {
|
|
11573
11581
|
const raw = readFileSync16(path, "utf8");
|
|
11574
|
-
return { data:
|
|
11582
|
+
return { data: yaml.load(raw, { schema: yaml.JSON_SCHEMA }), parseError: null };
|
|
11575
11583
|
} catch (err) {
|
|
11576
11584
|
return { data: null, parseError: err.message };
|
|
11577
11585
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contract-driven-delivery",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
4
4
|
"description": "Contract-driven delivery kit for AI coding agents with deterministic context indexes, manifest-backed read-scope governance, and orchestrated contracts-first delivery.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contract-driven",
|