@agentplaneorg/core 0.1.4 → 0.1.6

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 (52) hide show
  1. package/dist/commit/commit-policy.d.ts.map +1 -0
  2. package/dist/{config.d.ts → config/config.d.ts} +1 -0
  3. package/dist/config/config.d.ts.map +1 -0
  4. package/dist/config/config.js +124 -0
  5. package/dist/fs/atomic-write.d.ts +2 -0
  6. package/dist/fs/atomic-write.d.ts.map +1 -0
  7. package/dist/fs/atomic-write.js +9 -0
  8. package/dist/git/base-branch.d.ts.map +1 -0
  9. package/dist/{base-branch.js → git/base-branch.js} +1 -1
  10. package/dist/git/git-utils.d.ts.map +1 -0
  11. package/dist/{git-utils.js → git/git-utils.js} +1 -1
  12. package/dist/index.d.ts +12 -9
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +12 -9
  15. package/dist/project/project-root.d.ts.map +1 -0
  16. package/dist/tasks/task-doc.d.ts +16 -0
  17. package/dist/tasks/task-doc.d.ts.map +1 -0
  18. package/dist/tasks/task-doc.js +326 -0
  19. package/dist/tasks/task-id.d.ts +9 -0
  20. package/dist/tasks/task-id.d.ts.map +1 -0
  21. package/dist/tasks/task-id.js +28 -0
  22. package/dist/tasks/task-readme.d.ts.map +1 -0
  23. package/dist/{task-store.d.ts → tasks/task-store.d.ts} +2 -0
  24. package/dist/tasks/task-store.d.ts.map +1 -0
  25. package/dist/tasks/task-store.js +212 -0
  26. package/dist/tasks/tasks-export.d.ts.map +1 -0
  27. package/dist/{tasks-export.js → tasks/tasks-export.js} +5 -4
  28. package/dist/{tasks-lint.d.ts → tasks/tasks-lint.d.ts} +1 -1
  29. package/dist/tasks/tasks-lint.d.ts.map +1 -0
  30. package/dist/{tasks-lint.js → tasks/tasks-lint.js} +2 -2
  31. package/package.json +4 -1
  32. package/schemas/config.schema.json +278 -0
  33. package/dist/base-branch.d.ts.map +0 -1
  34. package/dist/commit-policy.d.ts.map +0 -1
  35. package/dist/config.d.ts.map +0 -1
  36. package/dist/config.js +0 -237
  37. package/dist/git-utils.d.ts.map +0 -1
  38. package/dist/project-root.d.ts.map +0 -1
  39. package/dist/task-readme.d.ts.map +0 -1
  40. package/dist/task-store.d.ts.map +0 -1
  41. package/dist/task-store.js +0 -359
  42. package/dist/tasks-export.d.ts.map +0 -1
  43. package/dist/tasks-lint.d.ts.map +0 -1
  44. /package/dist/{commit-policy.d.ts → commit/commit-policy.d.ts} +0 -0
  45. /package/dist/{commit-policy.js → commit/commit-policy.js} +0 -0
  46. /package/dist/{base-branch.d.ts → git/base-branch.d.ts} +0 -0
  47. /package/dist/{git-utils.d.ts → git/git-utils.d.ts} +0 -0
  48. /package/dist/{project-root.d.ts → project/project-root.d.ts} +0 -0
  49. /package/dist/{project-root.js → project/project-root.js} +0 -0
  50. /package/dist/{task-readme.d.ts → tasks/task-readme.d.ts} +0 -0
  51. /package/dist/{task-readme.js → tasks/task-readme.js} +0 -0
  52. /package/dist/{tasks-export.d.ts → tasks/tasks-export.d.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ import { generateTaskId } from "./task-id.js";
1
2
  export type TaskStatus = "TODO" | "DOING" | "DONE" | "BLOCKED";
2
3
  export type TaskPriority = "low" | "normal" | "med" | "high";
3
4
  export type TaskFrontmatter = {
@@ -48,6 +49,7 @@ export declare function createTask(opts: {
48
49
  tags: string[];
49
50
  dependsOn: string[];
50
51
  verify: string[];
52
+ idGenerator?: typeof generateTaskId;
51
53
  }): Promise<{
52
54
  id: string;
53
55
  readmePath: string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/tasks/task-store.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,WAAW,EAAE,CAAC,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAUF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAgBtF;AAWD,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC;IAC9F,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CASD;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvE;AAkED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,cAAc,CAAC;CACrC,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAoC9C;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CA+BlC;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,UAAU,CAAC,CActB;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BxB"}
@@ -0,0 +1,212 @@
1
+ import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { loadConfig } from "../config/config.js";
4
+ import { resolveProject } from "../project/project-root.js";
5
+ import { parseTaskReadme, renderTaskReadme } from "./task-readme.js";
6
+ import { ensureDocSections, setMarkdownSection } from "./task-doc.js";
7
+ import { generateTaskId } from "./task-id.js";
8
+ function nowIso() {
9
+ return new Date().toISOString();
10
+ }
11
+ function isRecord(value) {
12
+ return !!value && typeof value === "object" && !Array.isArray(value);
13
+ }
14
+ export function validateTaskDocMetadata(frontmatter) {
15
+ const errors = [];
16
+ if (frontmatter.doc_version !== 2)
17
+ errors.push("doc_version must be 2");
18
+ const updatedAt = frontmatter.doc_updated_at;
19
+ if (typeof updatedAt !== "string" || Number.isNaN(Date.parse(updatedAt))) {
20
+ errors.push("doc_updated_at must be an ISO timestamp");
21
+ }
22
+ const updatedBy = frontmatter.doc_updated_by;
23
+ if (typeof updatedBy !== "string" || updatedBy.trim().length === 0) {
24
+ errors.push("doc_updated_by must be a non-empty string");
25
+ }
26
+ return errors;
27
+ }
28
+ async function fileExists(filePath) {
29
+ try {
30
+ await readFile(filePath, "utf8");
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ export async function getTasksDir(opts) {
38
+ const resolved = await resolveProject({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null });
39
+ const loaded = await loadConfig(resolved.agentplaneDir);
40
+ const tasksDir = path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
41
+ return {
42
+ gitRoot: resolved.gitRoot,
43
+ tasksDir,
44
+ idSuffixLengthDefault: loaded.config.tasks.id_suffix_length_default,
45
+ };
46
+ }
47
+ export function taskReadmePath(tasksDir, taskId) {
48
+ return path.join(tasksDir, taskId, "README.md");
49
+ }
50
+ function defaultTaskBody() {
51
+ return [
52
+ "## Summary",
53
+ "",
54
+ "",
55
+ "## Scope",
56
+ "",
57
+ "",
58
+ "## Risks",
59
+ "",
60
+ "",
61
+ "## Verify Steps",
62
+ "",
63
+ "",
64
+ "## Verification",
65
+ "",
66
+ "",
67
+ "## Rollback Plan",
68
+ "",
69
+ ].join("\n");
70
+ }
71
+ function getLastCommentAuthor(frontmatter) {
72
+ const comments = frontmatter.comments;
73
+ if (!Array.isArray(comments))
74
+ return null;
75
+ const entries = comments;
76
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
77
+ const entry = entries[i];
78
+ if (!isRecord(entry))
79
+ continue;
80
+ const author = entry.author;
81
+ if (typeof author === "string") {
82
+ const trimmed = author.trim();
83
+ if (trimmed)
84
+ return trimmed;
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+ function resolveDocUpdatedBy(frontmatter, updatedBy) {
90
+ if (updatedBy != null) {
91
+ const explicit = updatedBy.trim();
92
+ if (explicit.length === 0) {
93
+ throw new Error("doc_updated_by must be a non-empty string");
94
+ }
95
+ return explicit;
96
+ }
97
+ const lastAuthor = getLastCommentAuthor(frontmatter);
98
+ if (lastAuthor)
99
+ return lastAuthor;
100
+ const existing = frontmatter.doc_updated_by;
101
+ if (typeof existing === "string") {
102
+ const trimmed = existing.trim();
103
+ if (trimmed && trimmed.toLowerCase() !== "agentplane")
104
+ return trimmed;
105
+ }
106
+ const owner = frontmatter.owner;
107
+ if (typeof owner === "string") {
108
+ const trimmed = owner.trim();
109
+ if (trimmed)
110
+ return trimmed;
111
+ }
112
+ return "agentplane";
113
+ }
114
+ export async function createTask(opts) {
115
+ const { tasksDir, idSuffixLengthDefault } = await getTasksDir({
116
+ cwd: opts.cwd,
117
+ rootOverride: opts.rootOverride ?? null,
118
+ });
119
+ await mkdir(tasksDir, { recursive: true });
120
+ const suffixLength = idSuffixLengthDefault;
121
+ const id = await (opts.idGenerator ?? generateTaskId)({
122
+ length: suffixLength,
123
+ attempts: 20,
124
+ isAvailable: async (taskId) => !(await fileExists(taskReadmePath(tasksDir, taskId))),
125
+ });
126
+ const readmePath = taskReadmePath(tasksDir, id);
127
+ const frontmatter = {
128
+ id,
129
+ title: opts.title,
130
+ status: "TODO",
131
+ priority: opts.priority,
132
+ owner: opts.owner,
133
+ depends_on: opts.dependsOn,
134
+ tags: opts.tags,
135
+ verify: opts.verify,
136
+ comments: [],
137
+ doc_version: 2,
138
+ doc_updated_at: nowIso(),
139
+ doc_updated_by: opts.owner,
140
+ description: opts.description,
141
+ };
142
+ const body = defaultTaskBody();
143
+ const text = renderTaskReadme(frontmatter, body);
144
+ await mkdir(path.dirname(readmePath), { recursive: true });
145
+ await writeFile(readmePath, text, "utf8");
146
+ return { id, readmePath };
147
+ }
148
+ export async function setTaskDocSection(opts) {
149
+ const resolved = await resolveProject({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null });
150
+ const loaded = await loadConfig(resolved.agentplaneDir);
151
+ const allowed = loaded.config.tasks.doc.sections;
152
+ if (!allowed.includes(opts.section)) {
153
+ throw new Error(`Unknown doc section: ${opts.section}`);
154
+ }
155
+ const tasksDir = path.join(resolved.gitRoot, loaded.config.paths.workflow_dir);
156
+ 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");
170
+ return { readmePath };
171
+ }
172
+ export async function readTask(opts) {
173
+ const { tasksDir } = await getTasksDir({
174
+ cwd: opts.cwd,
175
+ rootOverride: opts.rootOverride ?? null,
176
+ });
177
+ const readmePath = taskReadmePath(tasksDir, opts.taskId);
178
+ const text = await readFile(readmePath, "utf8");
179
+ const parsed = parseTaskReadme(text);
180
+ return {
181
+ id: opts.taskId,
182
+ frontmatter: parsed.frontmatter,
183
+ body: parsed.body,
184
+ readmePath,
185
+ };
186
+ }
187
+ export async function listTasks(opts) {
188
+ const { tasksDir } = await getTasksDir({
189
+ cwd: opts.cwd,
190
+ rootOverride: opts.rootOverride ?? null,
191
+ });
192
+ const entries = await readdir(tasksDir, { withFileTypes: true }).catch(() => []);
193
+ const ids = entries.filter((e) => e.isDirectory()).map((e) => e.name);
194
+ const tasks = [];
195
+ for (const id of ids) {
196
+ const readmePath = taskReadmePath(tasksDir, id);
197
+ try {
198
+ const text = await readFile(readmePath, "utf8");
199
+ const parsed = parseTaskReadme(text);
200
+ tasks.push({
201
+ id,
202
+ frontmatter: parsed.frontmatter,
203
+ body: parsed.body,
204
+ readmePath,
205
+ });
206
+ }
207
+ catch {
208
+ // Skip unreadable/broken tasks for now; lint will handle this later.
209
+ }
210
+ }
211
+ return tasks.toSorted((a, b) => a.id.localeCompare(b.id));
212
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-export.d.ts","sourceRoot":"","sources":["../../src/tasks/tasks-export.ts"],"names":[],"mappings":"AAaA,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWxD;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,QAAQ,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,WAAW,EAAE,CAAC,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,IAAI,EAAE,eAAe,CAAC;CACvB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAEtE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAGrE;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqE/B;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAW3D"}
@@ -1,8 +1,9 @@
1
1
  import { createHash } from "node:crypto";
2
- import { mkdir, writeFile } from "node:fs/promises";
2
+ import { mkdir } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { loadConfig } from "./config.js";
5
- import { resolveProject } from "./project-root.js";
4
+ import { loadConfig } from "../config/config.js";
5
+ import { atomicWriteFile } from "../fs/atomic-write.js";
6
+ import { resolveProject } from "../project/project-root.js";
6
7
  import { listTasks } from "./task-store.js";
7
8
  function isRecord(value) {
8
9
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -91,6 +92,6 @@ export async function writeTasksExport(opts) {
91
92
  const outPath = path.join(resolved.gitRoot, loaded.config.paths.tasks_path);
92
93
  const snapshot = await buildTasksExportSnapshot(opts);
93
94
  await mkdir(path.dirname(outPath), { recursive: true });
94
- await writeFile(outPath, `${JSON.stringify(snapshot, null, 2)}\n`, "utf8");
95
+ await atomicWriteFile(outPath, `${JSON.stringify(snapshot, null, 2)}\n`);
95
96
  return { path: outPath, snapshot };
96
97
  }
@@ -1,4 +1,4 @@
1
- import type { AgentplaneConfig } from "./config.js";
1
+ import type { AgentplaneConfig } from "../config/config.js";
2
2
  import { type TasksExportSnapshot } from "./tasks-export.js";
3
3
  export type TasksLintResult = {
4
4
  errors: string[];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-lint.d.ts","sourceRoot":"","sources":["../../src/tasks/tasks-lint.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AA2DF,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,gBAAgB,GACvB,eAAe,CA4GjB;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAOrF;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,eAAe,CAAC,CAG3B"}
@@ -1,7 +1,7 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { loadConfig } from "./config.js";
4
- import { resolveProject } from "./project-root.js";
3
+ import { loadConfig } from "../config/config.js";
4
+ import { resolveProject } from "../project/project-root.js";
5
5
  import { computeTasksChecksum, } from "./tasks-export.js";
6
6
  function isRecord(value) {
7
7
  return !!value && typeof value === "object" && !Array.isArray(value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentplaneorg/core",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Core utilities and models for the Agent Plane CLI.",
5
5
  "keywords": [
6
6
  "agentplane",
@@ -30,6 +30,7 @@
30
30
  "types": "./dist/index.d.ts",
31
31
  "files": [
32
32
  "dist",
33
+ "schemas",
33
34
  "README.md",
34
35
  "LICENSE"
35
36
  ],
@@ -43,6 +44,8 @@
43
44
  "prepack": "bun run clean && bun run build"
44
45
  },
45
46
  "dependencies": {
47
+ "ajv": "^8.17.1",
48
+ "ajv-formats": "^3.0.1",
46
49
  "yaml": "^2.8.2"
47
50
  }
48
51
  }
@@ -0,0 +1,278 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://agentplane.dev/schemas/config.schema.json",
4
+ "title": "agentplane config.json (v1)",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema_version", "workflow_mode", "paths", "tasks", "commit", "tasks_backend"],
8
+ "properties": {
9
+ "schema_version": { "type": "integer", "const": 1, "default": 1 },
10
+ "workflow_mode": {
11
+ "type": "string",
12
+ "enum": ["direct", "branch_pr"],
13
+ "default": "direct"
14
+ },
15
+ "status_commit_policy": {
16
+ "type": "string",
17
+ "enum": ["off", "warn", "confirm"],
18
+ "default": "warn"
19
+ },
20
+ "finish_auto_status_commit": { "type": "boolean", "default": true },
21
+ "base_branch": { "type": "string", "minLength": 1, "default": "main" },
22
+ "agents": {
23
+ "type": "object",
24
+ "additionalProperties": true,
25
+ "required": ["approvals"],
26
+ "default": {
27
+ "approvals": { "require_plan": true, "require_network": true, "require_verify": true }
28
+ },
29
+ "properties": {
30
+ "approvals": {
31
+ "type": "object",
32
+ "additionalProperties": true,
33
+ "required": ["require_plan", "require_network", "require_verify"],
34
+ "default": { "require_plan": true, "require_network": true, "require_verify": true },
35
+ "properties": {
36
+ "require_plan": { "type": "boolean", "default": true },
37
+ "require_network": { "type": "boolean", "default": true },
38
+ "require_verify": { "type": "boolean", "default": true }
39
+ }
40
+ }
41
+ }
42
+ },
43
+ "recipes": {
44
+ "type": "object",
45
+ "additionalProperties": true,
46
+ "required": ["storage_default"],
47
+ "default": { "storage_default": "link" },
48
+ "properties": {
49
+ "storage_default": {
50
+ "type": "string",
51
+ "enum": ["link", "copy", "global"],
52
+ "default": "link"
53
+ }
54
+ }
55
+ },
56
+ "paths": {
57
+ "type": "object",
58
+ "additionalProperties": true,
59
+ "required": ["agents_dir", "tasks_path", "workflow_dir", "worktrees_dir"],
60
+ "default": {
61
+ "agents_dir": ".agentplane/agents",
62
+ "tasks_path": ".agentplane/tasks.json",
63
+ "workflow_dir": ".agentplane/tasks",
64
+ "worktrees_dir": ".agentplane/worktrees"
65
+ },
66
+ "properties": {
67
+ "agents_dir": { "type": "string", "minLength": 1, "default": ".agentplane/agents" },
68
+ "tasks_path": { "type": "string", "minLength": 1, "default": ".agentplane/tasks.json" },
69
+ "workflow_dir": { "type": "string", "minLength": 1, "default": ".agentplane/tasks" },
70
+ "worktrees_dir": { "type": "string", "minLength": 1, "default": ".agentplane/worktrees" }
71
+ }
72
+ },
73
+ "branch": {
74
+ "type": "object",
75
+ "additionalProperties": true,
76
+ "required": ["task_prefix"],
77
+ "default": { "task_prefix": "task" },
78
+ "properties": {
79
+ "task_prefix": { "type": "string", "minLength": 1, "default": "task" }
80
+ }
81
+ },
82
+ "framework": {
83
+ "type": "object",
84
+ "additionalProperties": true,
85
+ "required": ["source", "last_update"],
86
+ "default": {
87
+ "source": "https://github.com/basilisk-labs/agent-plane",
88
+ "last_update": null
89
+ },
90
+ "properties": {
91
+ "source": {
92
+ "type": "string",
93
+ "minLength": 1,
94
+ "default": "https://github.com/basilisk-labs/agent-plane"
95
+ },
96
+ "last_update": {
97
+ "type": ["string", "null"],
98
+ "format": "date-time",
99
+ "default": null
100
+ }
101
+ }
102
+ },
103
+ "tasks": {
104
+ "type": "object",
105
+ "additionalProperties": true,
106
+ "required": ["id_suffix_length_default", "verify", "doc", "comments"],
107
+ "default": {
108
+ "id_suffix_length_default": 6,
109
+ "verify": { "required_tags": ["code", "backend", "frontend"] },
110
+ "doc": {
111
+ "sections": [
112
+ "Summary",
113
+ "Context",
114
+ "Scope",
115
+ "Risks",
116
+ "Verify Steps",
117
+ "Verification",
118
+ "Rollback Plan",
119
+ "Notes"
120
+ ],
121
+ "required_sections": [
122
+ "Summary",
123
+ "Scope",
124
+ "Risks",
125
+ "Verify Steps",
126
+ "Verification",
127
+ "Rollback Plan"
128
+ ]
129
+ },
130
+ "comments": {
131
+ "start": { "prefix": "Start:", "min_chars": 40 },
132
+ "blocked": { "prefix": "Blocked:", "min_chars": 40 },
133
+ "verified": { "prefix": "Verified:", "min_chars": 60 }
134
+ }
135
+ },
136
+ "properties": {
137
+ "id_suffix_length_default": {
138
+ "type": "integer",
139
+ "minimum": 3,
140
+ "maximum": 16,
141
+ "default": 6
142
+ },
143
+ "verify": {
144
+ "type": "object",
145
+ "additionalProperties": true,
146
+ "required": ["required_tags"],
147
+ "default": { "required_tags": ["code", "backend", "frontend"] },
148
+ "properties": {
149
+ "required_tags": {
150
+ "type": "array",
151
+ "items": { "type": "string", "minLength": 1 },
152
+ "uniqueItems": true,
153
+ "default": ["code", "backend", "frontend"]
154
+ }
155
+ }
156
+ },
157
+ "doc": {
158
+ "type": "object",
159
+ "additionalProperties": true,
160
+ "required": ["sections", "required_sections"],
161
+ "default": {
162
+ "sections": [
163
+ "Summary",
164
+ "Context",
165
+ "Scope",
166
+ "Risks",
167
+ "Verify Steps",
168
+ "Verification",
169
+ "Rollback Plan",
170
+ "Notes"
171
+ ],
172
+ "required_sections": [
173
+ "Summary",
174
+ "Scope",
175
+ "Risks",
176
+ "Verify Steps",
177
+ "Verification",
178
+ "Rollback Plan"
179
+ ]
180
+ },
181
+ "properties": {
182
+ "sections": {
183
+ "type": "array",
184
+ "items": { "type": "string", "minLength": 1 },
185
+ "default": [
186
+ "Summary",
187
+ "Context",
188
+ "Scope",
189
+ "Risks",
190
+ "Verify Steps",
191
+ "Verification",
192
+ "Rollback Plan",
193
+ "Notes"
194
+ ]
195
+ },
196
+ "required_sections": {
197
+ "type": "array",
198
+ "items": { "type": "string", "minLength": 1 },
199
+ "default": [
200
+ "Summary",
201
+ "Scope",
202
+ "Risks",
203
+ "Verify Steps",
204
+ "Verification",
205
+ "Rollback Plan"
206
+ ]
207
+ }
208
+ }
209
+ },
210
+ "comments": {
211
+ "type": "object",
212
+ "additionalProperties": true,
213
+ "required": ["start", "blocked", "verified"],
214
+ "default": {
215
+ "start": { "prefix": "Start:", "min_chars": 40 },
216
+ "blocked": { "prefix": "Blocked:", "min_chars": 40 },
217
+ "verified": { "prefix": "Verified:", "min_chars": 60 }
218
+ },
219
+ "properties": {
220
+ "start": {
221
+ "$ref": "#/$defs/comment_policy",
222
+ "default": { "prefix": "Start:", "min_chars": 40 }
223
+ },
224
+ "blocked": {
225
+ "$ref": "#/$defs/comment_policy",
226
+ "default": { "prefix": "Blocked:", "min_chars": 40 }
227
+ },
228
+ "verified": {
229
+ "$ref": "#/$defs/comment_policy",
230
+ "default": { "prefix": "Verified:", "min_chars": 60 }
231
+ }
232
+ }
233
+ }
234
+ }
235
+ },
236
+ "commit": {
237
+ "type": "object",
238
+ "additionalProperties": true,
239
+ "required": ["generic_tokens"],
240
+ "default": {
241
+ "generic_tokens": ["start", "status", "mark", "done", "wip", "update", "tasks", "task"]
242
+ },
243
+ "properties": {
244
+ "generic_tokens": {
245
+ "type": "array",
246
+ "items": { "type": "string", "minLength": 1 },
247
+ "uniqueItems": true,
248
+ "default": ["start", "status", "mark", "done", "wip", "update", "tasks", "task"]
249
+ }
250
+ }
251
+ },
252
+ "tasks_backend": {
253
+ "type": "object",
254
+ "additionalProperties": true,
255
+ "required": ["config_path"],
256
+ "default": { "config_path": ".agentplane/backends/local/backend.json" },
257
+ "properties": {
258
+ "config_path": {
259
+ "type": "string",
260
+ "minLength": 1,
261
+ "default": ".agentplane/backends/local/backend.json"
262
+ }
263
+ }
264
+ },
265
+ "closure_commit_requires_approval": { "type": "boolean", "default": false }
266
+ },
267
+ "$defs": {
268
+ "comment_policy": {
269
+ "type": "object",
270
+ "additionalProperties": true,
271
+ "required": ["prefix", "min_chars"],
272
+ "properties": {
273
+ "prefix": { "type": "string", "minLength": 1 },
274
+ "min_chars": { "type": "integer", "minimum": 0 }
275
+ }
276
+ }
277
+ }
278
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-branch.d.ts","sourceRoot":"","sources":["../src/base-branch.ts"],"names":[],"mappings":"AA0BA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGzB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAMlB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"commit-policy.d.ts","sourceRoot":"","sources":["../src/commit-policy.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAMF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,CAOlF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,kBAAkB,CAerB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,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,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QACP,SAAS,EAAE;YACT,YAAY,EAAE,OAAO,CAAC;YACtB,eAAe,EAAE,OAAO,CAAC;SAC1B,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,CAmDhD;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAiG7D;AAED,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,CAyB7E;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,CAO3B"}