@agentplaneorg/core 0.1.7 → 0.1.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAClD,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,cAAc,EAAE,CAAC,CAAC;IAClB,aAAa,EAAE,YAAY,CAAC;IAC5B,oBAAoB,EAAE,kBAAkB,CAAC;IACzC,yBAAyB,EAAE,OAAO,CAAC;IACnC,MAAM,CAAC,EAAE;QACP,SAAS,EAAE;YACT,YAAY,EAAE,OAAO,CAAC;YACtB,eAAe,EAAE,OAAO,CAAC;YACzB,cAAc,EAAE,OAAO,CAAC;SACzB,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE;QACR,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;KAC7C,CAAC;IACF,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC1D,KAAK,EAAE;QACL,wBAAwB,EAAE,MAAM,CAAC;QACjC,MAAM,EAAE;YAAE,aAAa,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QACpC,GAAG,EAAE;YAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QACzD,QAAQ,EAAE;YACR,KAAK,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;YAC7C,OAAO,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;YAC/C,QAAQ,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;SACjD,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACrC,aAAa,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,gCAAgC,EAAE,OAAO,CAAC;CAC3C,CAAC;AAEF,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD;AAkED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAa7D;AAID,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B,CAAC;AAQF,wBAAsB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8B7E;AAkBD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,IAAI,CAgBN;AAED,wBAAsB,UAAU,CAC9B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAS3B"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAClD,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,cAAc,EAAE,CAAC,CAAC;IAClB,aAAa,EAAE,YAAY,CAAC;IAC5B,oBAAoB,EAAE,kBAAkB,CAAC;IACzC,yBAAyB,EAAE,OAAO,CAAC;IACnC,MAAM,CAAC,EAAE;QACP,SAAS,EAAE;YACT,YAAY,EAAE,OAAO,CAAC;YACtB,eAAe,EAAE,OAAO,CAAC;YACzB,cAAc,EAAE,OAAO,CAAC;SACzB,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE;QACR,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;KAC7C,CAAC;IACF,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC1D,KAAK,EAAE;QACL,wBAAwB,EAAE,MAAM,CAAC;QACjC,MAAM,EAAE;YAAE,aAAa,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QACpC,GAAG,EAAE;YAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC;QACzD,QAAQ,EAAE;YACR,KAAK,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;YAC7C,OAAO,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;YAC/C,QAAQ,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,CAAC;SACjD,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACrC,aAAa,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,gCAAgC,EAAE,OAAO,CAAC;CAC3C,CAAC;AAEF,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD;AAkED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAa7D;AAID,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B,CAAC;AAQF,wBAAsB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8B7E;AAkBD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,IAAI,CAgBN;AAED,wBAAsB,UAAU,CAC9B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAS3B"}
@@ -1,9 +1,10 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { mkdir, readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import AjvModule from "ajv";
6
6
  import AjvFormatsModule from "ajv-formats";
7
+ import { atomicWriteFile } from "../fs/atomic-write.js";
7
8
  export function defaultConfig() {
8
9
  return structuredClone(DEFAULT_CONFIG);
9
10
  }
@@ -148,6 +149,6 @@ export async function saveConfig(agentplaneDir, raw) {
148
149
  await mkdir(agentplaneDir, { recursive: true });
149
150
  const filePath = path.join(agentplaneDir, "config.json");
150
151
  const text = `${JSON.stringify(sanitized.sanitized, null, 2)}\n`;
151
- await writeFile(filePath, text, "utf8");
152
+ await atomicWriteFile(filePath, text, "utf8");
152
153
  return validated;
153
154
  }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export declare const CORE_VERSION = "0.0.0";
2
2
  export { findGitRoot, resolveProject, type ResolvedProject, type ResolveProjectOptions, } from "./project/project-root.js";
3
3
  export { defaultConfig, loadConfig, saveConfig, setByDottedKey, validateConfig, type AgentplaneConfig, type LoadedConfig, type StatusCommitPolicy, type WorkflowMode, } from "./config/config.js";
4
4
  export { parseTaskReadme, renderTaskFrontmatter, renderTaskReadme, type ParsedTaskReadme, } from "./tasks/task-readme.js";
5
+ export { readTaskReadme, updateTaskReadmeAtomic } from "./tasks/task-readme-io.js";
5
6
  export { docChanged, ensureDocSections, extractTaskDoc, mergeTaskDoc, normalizeDocSectionName, normalizeTaskDoc, parseDocSections, setMarkdownSection, splitCombinedHeadingLines, } from "./tasks/task-doc.js";
6
7
  export { atomicWriteFile } from "./fs/atomic-write.js";
7
8
  export { generateTaskId, timestampIdPrefix, TASK_ID_ALPHABET } from "./tasks/task-id.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,OAAO,EACL,WAAW,EACX,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,qBAAqB,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EACL,UAAU,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,kBAAkB,GACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,OAAO,EACL,WAAW,EACX,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,qBAAqB,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnF,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EACL,UAAU,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,kBAAkB,GACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export const CORE_VERSION = "0.0.0";
2
2
  export { findGitRoot, resolveProject, } from "./project/project-root.js";
3
3
  export { defaultConfig, loadConfig, saveConfig, setByDottedKey, validateConfig, } from "./config/config.js";
4
4
  export { parseTaskReadme, renderTaskFrontmatter, renderTaskReadme, } from "./tasks/task-readme.js";
5
+ export { readTaskReadme, updateTaskReadmeAtomic } from "./tasks/task-readme-io.js";
5
6
  export { docChanged, ensureDocSections, extractTaskDoc, mergeTaskDoc, normalizeDocSectionName, normalizeTaskDoc, parseDocSections, setMarkdownSection, splitCombinedHeadingLines, } from "./tasks/task-doc.js";
6
7
  export { atomicWriteFile } from "./fs/atomic-write.js";
7
8
  export { generateTaskId, timestampIdPrefix, TASK_ID_ALPHABET } from "./tasks/task-id.js";
@@ -0,0 +1,7 @@
1
+ import { type ParsedTaskReadme } from "./task-readme.js";
2
+ export declare function readTaskReadme(readmePath: string): Promise<ParsedTaskReadme>;
3
+ export declare function updateTaskReadmeAtomic(readmePath: string, updater: (parsed: ParsedTaskReadme) => {
4
+ frontmatter: Record<string, unknown>;
5
+ body: string;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=task-readme-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-readme-io.d.ts","sourceRoot":"","sources":["../../src/tasks/task-readme-io.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE5F,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAGlF;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK;IAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5F,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,14 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { atomicWriteFile } from "../fs/atomic-write.js";
3
+ import { parseTaskReadme, renderTaskReadme } from "./task-readme.js";
4
+ export async function readTaskReadme(readmePath) {
5
+ const text = await readFile(readmePath, "utf8");
6
+ return parseTaskReadme(text);
7
+ }
8
+ export async function updateTaskReadmeAtomic(readmePath, updater) {
9
+ const text = await readFile(readmePath, "utf8");
10
+ const parsed = parseTaskReadme(text);
11
+ const next = updater(parsed);
12
+ const rendered = renderTaskReadme(next.frontmatter, next.body);
13
+ await atomicWriteFile(readmePath, rendered.endsWith("\n") ? rendered : `${rendered}\n`);
14
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"task-readme.d.ts","sourceRoot":"","sources":["../../src/tasks/task-readme.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAqBF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAYlE;AAiED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA8BlF;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3F"}
1
+ {"version":3,"file":"task-readme.d.ts","sourceRoot":"","sources":["../../src/tasks/task-readme.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAqBF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAYlE;AAkFD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAiClF;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3F"}
@@ -2,6 +2,18 @@ import { parse as parseYaml } from "yaml";
2
2
  function isRecord(value) {
3
3
  return !!value && typeof value === "object" && !Array.isArray(value);
4
4
  }
5
+ function orderedKeys(value, preferredKeyOrder) {
6
+ const keys = Object.keys(value);
7
+ const ordered = [];
8
+ if (preferredKeyOrder) {
9
+ for (const k of preferredKeyOrder)
10
+ if (k in value)
11
+ ordered.push(k);
12
+ }
13
+ const remaining = keys.filter((k) => !ordered.includes(k)).toSorted((a, b) => a.localeCompare(b));
14
+ ordered.push(...remaining);
15
+ return ordered;
16
+ }
5
17
  function stripLeadingFrontmatterBlocks(body) {
6
18
  let next = body.replaceAll("\r\n", "\n");
7
19
  while (true) {
@@ -44,58 +56,69 @@ function renderScalar(value) {
44
56
  return value ? "true" : "false";
45
57
  throw new TypeError(`Unsupported scalar type: ${typeof value}`);
46
58
  }
47
- function renderInlineMap(value, preferredKeyOrder) {
48
- const keys = Object.keys(value);
49
- const ordered = [];
50
- if (preferredKeyOrder) {
51
- for (const k of preferredKeyOrder)
52
- if (k in value)
53
- ordered.push(k);
54
- }
55
- const remaining = keys.filter((k) => !ordered.includes(k)).toSorted((a, b) => a.localeCompare(b));
56
- ordered.push(...remaining);
57
- const parts = ordered.map((k) => {
58
- const v = value[k];
59
- if (Array.isArray(v))
60
- return `${k}: ${renderFlowSeq(v)}`;
61
- if (isRecord(v))
62
- return `${k}: ${renderInlineMap(v, null)}`;
63
- return `${k}: ${renderScalar(v)}`;
64
- });
65
- return `{ ${parts.join(", ")} }`;
66
- }
67
59
  function renderFlowSeq(value) {
68
60
  const parts = value.map((v) => {
69
61
  if (Array.isArray(v))
70
62
  return renderFlowSeq(v);
71
63
  if (isRecord(v))
72
- return renderInlineMap(v, null);
64
+ return `{ ${orderedKeys(v, null)
65
+ .map((k) => `${k}: ${renderScalar(v[k])}`)
66
+ .join(", ")} }`;
73
67
  return renderScalar(v);
74
68
  });
75
69
  return `[${parts.join(", ")}]`;
76
70
  }
77
- function renderValue(key, value) {
71
+ function renderMapLines(value, indent, preferredKeyOrder) {
72
+ const keys = orderedKeys(value, preferredKeyOrder);
73
+ const lines = [];
74
+ for (const k of keys) {
75
+ const v = value[k];
76
+ lines.push(...renderValueLines(k, v, indent));
77
+ }
78
+ return lines;
79
+ }
80
+ function isStringArray(value) {
81
+ return value.every((v) => typeof v === "string");
82
+ }
83
+ function renderValueLines(key, value, indent) {
78
84
  if (Array.isArray(value)) {
79
85
  if (value.length === 0)
80
- return [`${key}: []`];
86
+ return [`${indent}${key}: []`];
87
+ if (isStringArray(value)) {
88
+ return [`${indent}${key}:`, ...value.map((item) => `${indent} - ${renderScalar(item)}`)];
89
+ }
81
90
  const allObjects = value.every((v) => isRecord(v));
82
91
  if (!allObjects)
83
- return [`${key}: ${renderFlowSeq(value)}`];
92
+ return [`${indent}${key}: ${renderFlowSeq(value)}`];
84
93
  return [
85
- `${key}:`,
86
- ...value.map((item) => {
94
+ `${indent}${key}:`,
95
+ ...value.flatMap((item) => {
87
96
  if (!isRecord(item))
88
97
  throw new TypeError("Expected an object item in YAML sequence");
89
98
  const preferred = key === "comments" ? ["author", "body"] : null;
90
- return ` - ${renderInlineMap(item, preferred)}`;
99
+ const itemLines = renderMapLines(item, `${indent} `, preferred);
100
+ if (itemLines.length === 0)
101
+ return [`${indent} - {}`];
102
+ return [`${indent} -`, ...itemLines];
91
103
  }),
92
104
  ];
93
105
  }
94
106
  if (isRecord(value)) {
95
- const preferred = key === "commit" ? ["hash", "message"] : null;
96
- return [`${key}: ${renderInlineMap(value, preferred)}`];
107
+ const preferred = key === "origin"
108
+ ? ["system", "issue_id", "url"]
109
+ : key === "plan_approval"
110
+ ? ["state", "updated_at", "updated_by", "note"]
111
+ : key === "verification"
112
+ ? ["state", "updated_at", "updated_by", "note"]
113
+ : key === "commit"
114
+ ? ["hash", "message"]
115
+ : null;
116
+ const inner = renderMapLines(value, `${indent} `, preferred);
117
+ if (inner.length === 0)
118
+ return [`${indent}${key}: {}`];
119
+ return [`${indent}${key}:`, ...inner];
97
120
  }
98
- return [`${key}: ${renderScalar(value)}`];
121
+ return [`${indent}${key}: ${renderScalar(value)}`];
99
122
  }
100
123
  export function renderTaskFrontmatter(frontmatter) {
101
124
  const preferredKeyOrder = [
@@ -104,26 +127,27 @@ export function renderTaskFrontmatter(frontmatter) {
104
127
  "status",
105
128
  "priority",
106
129
  "owner",
130
+ "created_at",
131
+ "created_by",
132
+ "origin",
107
133
  "depends_on",
108
134
  "tags",
109
135
  "verify",
136
+ "plan_approval",
137
+ "verification",
110
138
  "commit",
111
139
  "comments",
112
140
  "doc_version",
113
141
  "doc_updated_at",
114
142
  "doc_updated_by",
115
143
  "description",
144
+ "id_source",
145
+ "dirty",
116
146
  ];
117
- const keys = Object.keys(frontmatter);
118
- const ordered = [];
119
- for (const k of preferredKeyOrder)
120
- if (k in frontmatter)
121
- ordered.push(k);
122
- const remaining = keys.filter((k) => !ordered.includes(k)).toSorted((a, b) => a.localeCompare(b));
123
- ordered.push(...remaining);
147
+ const ordered = orderedKeys(frontmatter, preferredKeyOrder);
124
148
  const lines = [];
125
149
  for (const k of ordered) {
126
- lines.push(...renderValue(k, frontmatter[k]));
150
+ lines.push(...renderValueLines(k, frontmatter[k], ""));
127
151
  }
128
152
  return `---\n${lines.join("\n")}\n---\n`;
129
153
  }
@@ -10,6 +10,18 @@ export type TaskFrontmatter = {
10
10
  depends_on: string[];
11
11
  tags: string[];
12
12
  verify: string[];
13
+ plan_approval?: {
14
+ state: "pending" | "approved" | "rejected";
15
+ updated_at: string | null;
16
+ updated_by: string | null;
17
+ note: string | null;
18
+ };
19
+ verification?: {
20
+ state: "pending" | "ok" | "needs_rework";
21
+ updated_at: string | null;
22
+ updated_by: string | null;
23
+ note: string | null;
24
+ };
13
25
  comments: {
14
26
  author: string;
15
27
  body: string;
@@ -1 +1 @@
1
- {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/tasks/task-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/tasks/task-store.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
- import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
1
+ import { mkdir, readdir, readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { loadConfig } from "../config/config.js";
4
+ import { atomicWriteFile } from "../fs/atomic-write.js";
4
5
  import { resolveProject } from "../project/project-root.js";
5
6
  import { parseTaskReadme, renderTaskReadme } from "./task-readme.js";
7
+ import { updateTaskReadmeAtomic } from "./task-readme-io.js";
6
8
  import { ensureDocSections, setMarkdownSection } from "./task-doc.js";
7
9
  import { generateTaskId } from "./task-id.js";
8
10
  function nowIso() {
@@ -55,15 +57,25 @@ function defaultTaskBody() {
55
57
  "## Scope",
56
58
  "",
57
59
  "",
58
- "## Risks",
60
+ "## Plan",
59
61
  "",
60
62
  "",
61
- "## Verify Steps",
63
+ "## Risks",
62
64
  "",
63
65
  "",
64
66
  "## Verification",
65
67
  "",
66
68
  "",
69
+ "### Plan",
70
+ "",
71
+ "",
72
+ "### Results",
73
+ "",
74
+ "",
75
+ "<!-- BEGIN VERIFICATION RESULTS -->",
76
+ "<!-- END VERIFICATION RESULTS -->",
77
+ "",
78
+ "",
67
79
  "## Rollback Plan",
68
80
  "",
69
81
  ].join("\n");
@@ -133,6 +145,18 @@ export async function createTask(opts) {
133
145
  depends_on: opts.dependsOn,
134
146
  tags: opts.tags,
135
147
  verify: opts.verify,
148
+ plan_approval: {
149
+ state: "pending",
150
+ updated_at: null,
151
+ updated_by: null,
152
+ note: null,
153
+ },
154
+ verification: {
155
+ state: "pending",
156
+ updated_at: null,
157
+ updated_by: null,
158
+ note: null,
159
+ },
136
160
  comments: [],
137
161
  doc_version: 2,
138
162
  doc_updated_at: nowIso(),
@@ -141,8 +165,7 @@ export async function createTask(opts) {
141
165
  };
142
166
  const body = defaultTaskBody();
143
167
  const text = renderTaskReadme(frontmatter, body);
144
- await mkdir(path.dirname(readmePath), { recursive: true });
145
- await writeFile(readmePath, text, "utf8");
168
+ await atomicWriteFile(readmePath, text, "utf8");
146
169
  return { id, readmePath };
147
170
  }
148
171
  export async function setTaskDocSection(opts) {
@@ -154,19 +177,18 @@ export async function setTaskDocSection(opts) {
154
177
  }
155
178
  const tasksDir = path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
156
179
  const readmePath = taskReadmePath(tasksDir, opts.taskId);
157
- const original = await readFile(readmePath, "utf8");
158
- const parsed = parseTaskReadme(original);
159
- const updatedBy = resolveDocUpdatedBy(parsed.frontmatter, opts.updatedBy);
160
- const nextFrontmatter = {
161
- ...parsed.frontmatter,
162
- doc_version: 2,
163
- doc_updated_at: nowIso(),
164
- doc_updated_by: updatedBy,
165
- };
166
- const baseDoc = ensureDocSections(parsed.body, loaded.config.tasks.doc.required_sections);
167
- const nextBody = ensureDocSections(setMarkdownSection(baseDoc, opts.section, opts.text), loaded.config.tasks.doc.required_sections);
168
- const nextText = renderTaskReadme(nextFrontmatter, nextBody);
169
- await writeFile(readmePath, nextText, "utf8");
180
+ await updateTaskReadmeAtomic(readmePath, (parsed) => {
181
+ const updatedBy = resolveDocUpdatedBy(parsed.frontmatter, opts.updatedBy);
182
+ const nextFrontmatter = {
183
+ ...parsed.frontmatter,
184
+ doc_version: 2,
185
+ doc_updated_at: nowIso(),
186
+ doc_updated_by: updatedBy,
187
+ };
188
+ const baseDoc = ensureDocSections(parsed.body, loaded.config.tasks.doc.required_sections);
189
+ const nextBody = ensureDocSections(setMarkdownSection(baseDoc, opts.section, opts.text), loaded.config.tasks.doc.required_sections);
190
+ return { frontmatter: nextFrontmatter, body: nextBody };
191
+ });
170
192
  return { readmePath };
171
193
  }
172
194
  export async function readTask(opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentplaneorg/core",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Core utilities and models for the Agent Plane CLI.",
5
5
  "keywords": [
6
6
  "agentplane",
@@ -111,6 +111,7 @@
111
111
  "Summary",
112
112
  "Context",
113
113
  "Scope",
114
+ "Plan",
114
115
  "Risks",
115
116
  "Verify Steps",
116
117
  "Verification",
@@ -120,8 +121,8 @@
120
121
  "required_sections": [
121
122
  "Summary",
122
123
  "Scope",
124
+ "Plan",
123
125
  "Risks",
124
- "Verify Steps",
125
126
  "Verification",
126
127
  "Rollback Plan"
127
128
  ]
@@ -162,6 +163,7 @@
162
163
  "Summary",
163
164
  "Context",
164
165
  "Scope",
166
+ "Plan",
165
167
  "Risks",
166
168
  "Verify Steps",
167
169
  "Verification",
@@ -171,8 +173,8 @@
171
173
  "required_sections": [
172
174
  "Summary",
173
175
  "Scope",
176
+ "Plan",
174
177
  "Risks",
175
- "Verify Steps",
176
178
  "Verification",
177
179
  "Rollback Plan"
178
180
  ]
@@ -185,6 +187,7 @@
185
187
  "Summary",
186
188
  "Context",
187
189
  "Scope",
190
+ "Plan",
188
191
  "Risks",
189
192
  "Verify Steps",
190
193
  "Verification",
@@ -195,14 +198,7 @@
195
198
  "required_sections": {
196
199
  "type": "array",
197
200
  "items": { "type": "string", "minLength": 1 },
198
- "default": [
199
- "Summary",
200
- "Scope",
201
- "Risks",
202
- "Verify Steps",
203
- "Verification",
204
- "Rollback Plan"
205
- ]
201
+ "default": ["Summary", "Scope", "Plan", "Risks", "Verification", "Rollback Plan"]
206
202
  }
207
203
  }
208
204
  },