@agent-plan/core 0.2.24 → 0.2.26

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 (50) hide show
  1. package/dist/display-status.d.ts +3 -3
  2. package/dist/display-status.d.ts.map +1 -1
  3. package/dist/display-status.js +5 -4
  4. package/dist/handoff-context.d.ts +91 -1
  5. package/dist/handoff-context.d.ts.map +1 -1
  6. package/dist/handoff-context.js +134 -2
  7. package/dist/index.d.ts +5 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +4 -0
  10. package/dist/naming.d.ts +3 -0
  11. package/dist/naming.d.ts.map +1 -1
  12. package/dist/naming.js +7 -0
  13. package/dist/payload-fallback.d.ts +38 -0
  14. package/dist/payload-fallback.d.ts.map +1 -0
  15. package/dist/payload-fallback.js +73 -0
  16. package/dist/plan-store.d.ts +65 -8
  17. package/dist/plan-store.d.ts.map +1 -1
  18. package/dist/plan-store.js +391 -39
  19. package/dist/planner-rules.d.ts +3 -11
  20. package/dist/planner-rules.d.ts.map +1 -1
  21. package/dist/planner-rules.js +23 -6
  22. package/dist/planner-skill.d.ts +24 -0
  23. package/dist/planner-skill.d.ts.map +1 -0
  24. package/dist/planner-skill.js +113 -0
  25. package/dist/project-context-migration.d.ts +47 -0
  26. package/dist/project-context-migration.d.ts.map +1 -0
  27. package/dist/project-context-migration.js +168 -0
  28. package/dist/read-tracking.d.ts +27 -8
  29. package/dist/read-tracking.d.ts.map +1 -1
  30. package/dist/read-tracking.js +79 -34
  31. package/dist/recap.d.ts.map +1 -1
  32. package/dist/recap.js +2 -6
  33. package/dist/refs.d.ts +6 -1
  34. package/dist/refs.d.ts.map +1 -1
  35. package/dist/refs.js +25 -0
  36. package/dist/renderer.d.ts.map +1 -1
  37. package/dist/renderer.js +24 -1
  38. package/dist/requirement-macro-tasks.d.ts +18 -0
  39. package/dist/requirement-macro-tasks.d.ts.map +1 -0
  40. package/dist/requirement-macro-tasks.js +55 -0
  41. package/dist/schema.d.ts +1088 -273
  42. package/dist/schema.d.ts.map +1 -1
  43. package/dist/schema.js +65 -0
  44. package/dist/task-selection.js +2 -2
  45. package/dist/task-start-outcome.d.ts +1 -1
  46. package/dist/task-start-outcome.d.ts.map +1 -1
  47. package/dist/task-start-outcome.js +1 -0
  48. package/package.json +3 -1
  49. package/planner-skill.md +210 -0
  50. package/skills/grill-me/SKILL.md +10 -0
@@ -1,13 +1,3 @@
1
- /**
2
- * Canonical planner extension rules — the agent-behavior contract that applies
3
- * to EVERY project using the Agent Plan extension (Pi, MCP / Claude Code / Codex,
4
- * future harnesses). These are STATIC: no timestamps, no dynamic content, so the
5
- * same text seeds every .planner/ and never diverges across worktrees or
6
- * branches (no conflict from date/timestamp changes).
7
- *
8
- * AGENTS.md governs ONLY the development of the agent-plan extension and must
9
- * not duplicate these rules.
10
- */
11
1
  export declare const PLANNER_EXTENSION_RULES: string[];
12
2
  export interface ExtensionRulesFile {
13
3
  extensionRules: string[];
@@ -15,7 +5,9 @@ export interface ExtensionRulesFile {
15
5
  /**
16
6
  * Load the effective extension rules for a planner root. Returns the project's
17
7
  * own .planner/rules.json (static, user-overridable) when present and non-empty,
18
- * otherwise the canonical code set. Never returns timestamps or dynamic data.
8
+ * otherwise the canonical code set. Exact legacy canonical read-protocol rules
9
+ * are upgraded in memory without rewriting the project file; unrelated project
10
+ * overrides remain untouched. Never returns timestamps or dynamic data.
19
11
  */
20
12
  export declare function loadExtensionRules(plannerRoot: string): Promise<string[]>;
21
13
  //# sourceMappingURL=planner-rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"planner-rules.d.ts","sourceRoot":"","sources":["../src/planner-rules.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,EA2B3C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW/E"}
1
+ {"version":3,"file":"planner-rules.d.ts","sourceRoot":"","sources":["../src/planner-rules.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,uBAAuB,EAAE,MAAM,EA6B3C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAUD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW/E"}
@@ -10,6 +10,10 @@ import { join } from "node:path";
10
10
  * AGENTS.md governs ONLY the development of the agent-plan extension and must
11
11
  * not duplicate these rules.
12
12
  */
13
+ const DETAIL_WRITING_RULE = "Write relevant points (decisions, constraints, current state, file:line refs, edge cases) into the task/phase/feature description or notes as soon as they emerge. For starting, resuming, or switching, call the lifecycle tool first so valid session attestations can be reused. If it denies the operation, perform only the missing or stale full reads listed in nextActions, in any order within the current session, then retry; read linked requirements explicitly only when requested. Cite entities with composite IDs, not bare UUIDs.";
14
+ const EXPECTED_OPERATIONAL_RULE = "When you begin work, task_start and task_switch enforce session-scoped context reads plus a Project Guidelines read when that project section exists and is missing or stale for the current session. Read any relevant phase handoff as additional context, then update the planner before and after significant changes. If you change an architectural decision, document it explicitly.";
15
+ const LEGACY_DETAIL_WRITING_RULE = "Write relevant points (decisions, constraints, current state, file:line refs, edge cases) into the task/phase/feature description or notes as soon as they emerge. Before starting, resuming, or switching to a task, read task_get(full=true), then its parent phase_get(full=true), then its parent feature_get(full=true), in that exact order; read linked requirements explicitly when present. Cite entities with composite IDs, not bare UUIDs.";
16
+ const LEGACY_EXPECTED_OPERATIONAL_RULE = "When you begin work, task_start and task_switch enforce the required ordered full reads. Read any relevant phase handoff as additional context, then update the planner before and after significant changes. If you change an architectural decision, document it explicitly.";
13
17
  export const PLANNER_EXTENSION_RULES = [
14
18
  // §1 — source of truth
15
19
  "Keep the planner as the single operational source of truth while working: read the relevant planner state before starting; update it when an activity starts, changes state, blocks, or concludes; and record next steps, blockers, and decisions in the relevant planner entities. Never leave work only in the conversation.",
@@ -17,6 +21,8 @@ export const PLANNER_EXTENSION_RULES = [
17
21
  "Respect the task lifecycle strictly. Always call task_start before touching code, and task_complete with durable evidence of shipped work, verification (including partial verification), remaining/unverified work, files, and decisions when a deliverable is done. Never enter in-progress or done through task_update. Sync state changes (start/complete/block) to the planner at the exact moment they happen — never batch updates at session end. If task_start is denied, the task remains planned: satisfy the stated read prerequisites and retry, and never claim work started without an explicit successful start result. A task marked in-progress means you are actually working on it; if you stop, close or block it with a motivation in statusLog. Derived feature/phase status is computed from tasks, not stored in JSON.",
18
22
  // §3 — markdown not source of truth
19
23
  "Do not treat markdown as the source of truth for the plan. The plan's primary source is structured data in .planner/; markdown is a generated, human/agent-readable view.",
24
+ // §4 — project guidelines
25
+ "When a project defines the canonical Project Guidelines section, read it on planner load and before starting or switching task work whenever the current-session attestation is missing or stale. Keep coding standards, formatting, styling, and other project-specific rules from that section in working memory while executing the task.",
20
26
  // §5 — plan location
21
27
  "The plan lives in .planner/ within the target project. Whether .planner/ is git-tracked is at the project's discretion.",
22
28
  // §6 — discuss per phase
@@ -31,24 +37,35 @@ export const PLANNER_EXTENSION_RULES = [
31
37
  "Handoff is per-phase (phase.handoff), not a file. Write it only on explicit user request and only after the exact feature+phase target is confirmed. Run handoff_prepare for that phase, reconcile all still-relevant existing content into one active handoff, and synchronize durable task/phase/feature context in the same handoff_write operation. A pending handoff never blocks task_start and is archived only when the phase completes or the user explicitly clears it; refreshing it must not create superseded copies.",
32
38
  // §12 — operational hygiene
33
39
  "Operational hygiene: start the task (task_start) before thinking about implementation; complete it (task_complete) as part of delivering the deliverable, not after; motivate every block so a third party can understand the impediment.",
34
- // Avvio del planner
40
+ // Planner startup
35
41
  "The planner and Web UI never start automatically. Do not start the Web UI or show its URL unless the user runs load/recap/web-status. The Web UI URL appears only in the recap after load, or on explicit web status.",
36
- // Regola dettagli
37
- "Write relevant points (decisions, constraints, current state, file:line refs, edge cases) into the task/phase/feature description or notes as soon as they emerge. Before starting, resuming, or switching to a task, read task_get(full=true), then its parent phase_get(full=true), then its parent feature_get(full=true), in that exact order; read linked requirements explicitly when present. Cite entities with composite IDs, not bare UUIDs.",
42
+ // Detail-writing rule
43
+ DETAIL_WRITING_RULE,
38
44
  // Expected operational behavior
39
- "When you begin work, task_start and task_switch enforce the required ordered full reads. Read any relevant phase handoff as additional context, then update the planner before and after significant changes. If you change an architectural decision, document it explicitly.",
45
+ EXPECTED_OPERATIONAL_RULE,
40
46
  ];
47
+ function normalizeLegacyRules(rules) {
48
+ return rules.map((rule) => {
49
+ if (rule === LEGACY_DETAIL_WRITING_RULE)
50
+ return DETAIL_WRITING_RULE;
51
+ if (rule === LEGACY_EXPECTED_OPERATIONAL_RULE)
52
+ return EXPECTED_OPERATIONAL_RULE;
53
+ return rule;
54
+ });
55
+ }
41
56
  /**
42
57
  * Load the effective extension rules for a planner root. Returns the project's
43
58
  * own .planner/rules.json (static, user-overridable) when present and non-empty,
44
- * otherwise the canonical code set. Never returns timestamps or dynamic data.
59
+ * otherwise the canonical code set. Exact legacy canonical read-protocol rules
60
+ * are upgraded in memory without rewriting the project file; unrelated project
61
+ * overrides remain untouched. Never returns timestamps or dynamic data.
45
62
  */
46
63
  export async function loadExtensionRules(plannerRoot) {
47
64
  try {
48
65
  const raw = await readFile(join(plannerRoot, "rules.json"), "utf8");
49
66
  const parsed = JSON.parse(raw);
50
67
  if (Array.isArray(parsed.extensionRules) && parsed.extensionRules.length > 0) {
51
- return parsed.extensionRules.filter((r) => typeof r === "string" && r.length > 0);
68
+ return normalizeLegacyRules(parsed.extensionRules.filter((r) => typeof r === "string" && r.length > 0));
52
69
  }
53
70
  }
54
71
  catch {
@@ -0,0 +1,24 @@
1
+ export type PlannerSkillSyncStatus = "created" | "current" | "updated" | "customized";
2
+ export interface PlannerSkillSyncResult {
3
+ path: string;
4
+ status: PlannerSkillSyncStatus;
5
+ content: string;
6
+ canonicalHash: string;
7
+ customized: boolean;
8
+ message: string;
9
+ }
10
+ export declare function plannerSkillHash(content: string): string;
11
+ export declare function renderManagedPlannerSkill(content: string): string;
12
+ export declare function managedPlannerSkillBody(content: string): string;
13
+ export declare function loadCanonicalPlannerSkill(): Promise<string>;
14
+ export declare function loadCanonicalGrillMeSkill(): Promise<string>;
15
+ /** Create or safely refresh `.planner/SKILL.md`. */
16
+ export declare function syncProjectPlannerSkill(plannerRoot: string): Promise<PlannerSkillSyncResult>;
17
+ /** Create or safely refresh `.planner/skills/grill-me/SKILL.md`. */
18
+ export declare function syncProjectGrillMeSkill(plannerRoot: string): Promise<PlannerSkillSyncResult>;
19
+ /**
20
+ * Load the project-local Ideas discussion skill, safely creating/upgrading the
21
+ * managed copy first. Customized project copies are returned unchanged.
22
+ */
23
+ export declare function loadProjectGrillMeSkill(plannerRoot: string): Promise<string>;
24
+ //# sourceMappingURL=planner-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-skill.d.ts","sourceRoot":"","sources":["../src/planner-skill.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;AAEtF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,sBAAsB,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAcD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjE;AAyED,oDAAoD;AACpD,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAYlG;AAED,oEAAoE;AACpE,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAYlG;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElF"}
@@ -0,0 +1,113 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ const MANAGED_SKILL_HEADER = /^<!-- agent-plan-managed-skill sha256:([a-f0-9]{64}) -->\n/;
5
+ const CANONICAL_SKILL_URL = new URL("../planner-skill.md", import.meta.url);
6
+ const CANONICAL_GRILL_ME_SKILL_URL = new URL("../skills/grill-me/SKILL.md", import.meta.url);
7
+ function normalizeSkillContent(content) {
8
+ return `${content.replace(/\r\n/g, "\n").trimEnd()}\n`;
9
+ }
10
+ export function plannerSkillHash(content) {
11
+ return createHash("sha256").update(normalizeSkillContent(content), "utf8").digest("hex");
12
+ }
13
+ export function renderManagedPlannerSkill(content) {
14
+ const normalized = normalizeSkillContent(content);
15
+ return `<!-- agent-plan-managed-skill sha256:${plannerSkillHash(normalized)} -->\n${normalized}`;
16
+ }
17
+ export function managedPlannerSkillBody(content) {
18
+ return normalizeSkillContent(content.replace(MANAGED_SKILL_HEADER, ""));
19
+ }
20
+ export async function loadCanonicalPlannerSkill() {
21
+ return normalizeSkillContent(await readFile(CANONICAL_SKILL_URL, "utf8"));
22
+ }
23
+ export async function loadCanonicalGrillMeSkill() {
24
+ return normalizeSkillContent(await readFile(CANONICAL_GRILL_ME_SKILL_URL, "utf8"));
25
+ }
26
+ async function syncManagedProjectSkill(path, canonical, messages) {
27
+ const canonicalHash = plannerSkillHash(canonical);
28
+ const managedCanonical = renderManagedPlannerSkill(canonical);
29
+ const existing = await readFile(path, "utf8").catch(() => null);
30
+ if (existing == null) {
31
+ await mkdir(dirname(path), { recursive: true });
32
+ await writeFile(path, managedCanonical, "utf8");
33
+ return {
34
+ path,
35
+ status: "created",
36
+ content: canonical,
37
+ canonicalHash,
38
+ customized: false,
39
+ message: messages.created,
40
+ };
41
+ }
42
+ if (normalizeSkillContent(existing) === normalizeSkillContent(managedCanonical)) {
43
+ return {
44
+ path,
45
+ status: "current",
46
+ content: canonical,
47
+ canonicalHash,
48
+ customized: false,
49
+ message: messages.current,
50
+ };
51
+ }
52
+ // Adopt an exact unmarked canonical copy. This supports projects that copied
53
+ // a canonical skill before managed headers were introduced.
54
+ if (!MANAGED_SKILL_HEADER.test(existing) && normalizeSkillContent(existing) === canonical) {
55
+ await writeFile(path, managedCanonical, "utf8");
56
+ return {
57
+ path,
58
+ status: "updated",
59
+ content: canonical,
60
+ canonicalHash,
61
+ customized: false,
62
+ message: messages.adopted,
63
+ };
64
+ }
65
+ const marker = existing.match(MANAGED_SKILL_HEADER);
66
+ const existingBody = managedPlannerSkillBody(existing);
67
+ if (marker && plannerSkillHash(existingBody) === marker[1]) {
68
+ await writeFile(path, managedCanonical, "utf8");
69
+ return {
70
+ path,
71
+ status: "updated",
72
+ content: canonical,
73
+ canonicalHash,
74
+ customized: false,
75
+ message: messages.updated,
76
+ };
77
+ }
78
+ return {
79
+ path,
80
+ status: "customized",
81
+ content: existingBody,
82
+ canonicalHash,
83
+ customized: true,
84
+ message: messages.customized,
85
+ };
86
+ }
87
+ /** Create or safely refresh `.planner/SKILL.md`. */
88
+ export async function syncProjectPlannerSkill(plannerRoot) {
89
+ return syncManagedProjectSkill(join(plannerRoot, "SKILL.md"), await loadCanonicalPlannerSkill(), {
90
+ created: "Created the canonical project-local planner skill.",
91
+ current: "The project-local planner skill matches the canonical version.",
92
+ adopted: "Adopted and marked the unmodified canonical planner skill.",
93
+ updated: "Updated the unmodified project-local planner skill to the current canonical version.",
94
+ customized: "Preserved the customized .planner/SKILL.md. Reconcile it manually with the current canonical Agent Plan guide; Agent Plan did not overwrite project instructions.",
95
+ });
96
+ }
97
+ /** Create or safely refresh `.planner/skills/grill-me/SKILL.md`. */
98
+ export async function syncProjectGrillMeSkill(plannerRoot) {
99
+ return syncManagedProjectSkill(join(plannerRoot, "skills", "grill-me", "SKILL.md"), await loadCanonicalGrillMeSkill(), {
100
+ created: "Created the canonical project-local grill-me skill for Ideas discussions.",
101
+ current: "The project-local grill-me skill matches the canonical version.",
102
+ adopted: "Adopted and marked the unmodified canonical grill-me skill.",
103
+ updated: "Updated the unmodified project-local grill-me skill to the current canonical version.",
104
+ customized: "Preserved the customized .planner/skills/grill-me/SKILL.md. Reconcile it manually with the current canonical Agent Plan skill; Agent Plan did not overwrite project instructions.",
105
+ });
106
+ }
107
+ /**
108
+ * Load the project-local Ideas discussion skill, safely creating/upgrading the
109
+ * managed copy first. Customized project copies are returned unchanged.
110
+ */
111
+ export async function loadProjectGrillMeSkill(plannerRoot) {
112
+ return (await syncProjectGrillMeSkill(plannerRoot)).content;
113
+ }
@@ -0,0 +1,47 @@
1
+ import type { AcceptedDecision, Project } from "./schema.js";
2
+ export declare const LEGACY_PROJECT_CONTEXT_MIGRATION_VERSION = 1;
3
+ export type LegacyGuidelineSource = "global-rules" | "before-phase-start" | "before-task-start" | "after-phase-complete";
4
+ export interface LegacyGuidelineAddition {
5
+ source: LegacyGuidelineSource;
6
+ text: string;
7
+ }
8
+ export type LegacyDecisionAddition = Omit<AcceptedDecision, "acceptedAt">;
9
+ export interface LegacyProjectContextMigrationPreview {
10
+ version: number;
11
+ hasLegacyContext: boolean;
12
+ guidelinesChanged: boolean;
13
+ acceptedDecisionsChanged: boolean;
14
+ guidelineAdditions: LegacyGuidelineAddition[];
15
+ acceptedDecisionAdditions: LegacyDecisionAddition[];
16
+ skippedGuidelineDuplicates: number;
17
+ skippedDecisionDuplicates: number;
18
+ resultingGuidelinesContent: string;
19
+ legacyCounts: {
20
+ globalRules: number;
21
+ workflowRules: number;
22
+ decisions: number;
23
+ };
24
+ fieldsClearedOnApply: Array<"globalRules" | "workflowRules" | "decisions">;
25
+ }
26
+ export interface LegacyProjectContextMigrationResult {
27
+ applied: boolean;
28
+ preview: LegacyProjectContextMigrationPreview;
29
+ project: Project;
30
+ }
31
+ export interface PlannerSessionPreparationResult {
32
+ changed: boolean;
33
+ project: Project;
34
+ legacyProjectContext: {
35
+ migrated: boolean;
36
+ version: number;
37
+ guidelinesAdded: number;
38
+ acceptedDecisionsAdded: number;
39
+ duplicatesSkipped: number;
40
+ clearedFields: Array<"globalRules" | "workflowRules" | "decisions">;
41
+ summary: string;
42
+ };
43
+ }
44
+ export declare function plannerSessionPreparationResult(result: LegacyProjectContextMigrationResult): PlannerSessionPreparationResult;
45
+ export declare function previewLegacyProjectContextMigration(project: Project): LegacyProjectContextMigrationPreview;
46
+ export declare function applyLegacyProjectContextMigration(project: Project, acceptedAt: string): LegacyProjectContextMigrationResult;
47
+ //# sourceMappingURL=project-context-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context-migration.d.ts","sourceRoot":"","sources":["../src/project-context-migration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAE5E,eAAO,MAAM,wCAAwC,IAAI,CAAC;AAE1D,MAAM,MAAM,qBAAqB,GAC7B,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAE1E,MAAM,WAAW,oCAAoC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,wBAAwB,EAAE,OAAO,CAAC;IAClC,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;IAC9C,yBAAyB,EAAE,sBAAsB,EAAE,CAAC;IACpD,0BAA0B,EAAE,MAAM,CAAC;IACnC,yBAAyB,EAAE,MAAM,CAAC;IAClC,0BAA0B,EAAE,MAAM,CAAC;IACnC,YAAY,EAAE;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,oBAAoB,EAAE,KAAK,CAAC,aAAa,GAAG,eAAe,GAAG,WAAW,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,mCAAmC;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,oCAAoC,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB,EAAE;QACpB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,KAAK,CAAC,aAAa,GAAG,eAAe,GAAG,WAAW,CAAC,CAAC;QACpE,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,mCAAmC,GAC1C,+BAA+B,CAoBjC;AA0DD,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,OAAO,GAAG,oCAAoC,CAiE3G;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,GACjB,mCAAmC,CA0BrC"}
@@ -0,0 +1,168 @@
1
+ import { createHash } from "node:crypto";
2
+ export const LEGACY_PROJECT_CONTEXT_MIGRATION_VERSION = 1;
3
+ export function plannerSessionPreparationResult(result) {
4
+ const guidelinesAdded = result.preview.guidelineAdditions.length;
5
+ const acceptedDecisionsAdded = result.preview.acceptedDecisionAdditions.length;
6
+ const duplicatesSkipped = result.preview.skippedGuidelineDuplicates + result.preview.skippedDecisionDuplicates;
7
+ const summary = result.applied
8
+ ? `Migrated legacy project context: ${guidelinesAdded} guideline${guidelinesAdded === 1 ? "" : "s"}, ${acceptedDecisionsAdded} accepted decision${acceptedDecisionsAdded === 1 ? "" : "s"}, ${duplicatesSkipped} duplicate${duplicatesSkipped === 1 ? "" : "s"} skipped.`
9
+ : "Legacy project context is already canonical; no migration was needed.";
10
+ return {
11
+ changed: result.applied,
12
+ project: result.project,
13
+ legacyProjectContext: {
14
+ migrated: result.applied,
15
+ version: result.preview.version,
16
+ guidelinesAdded,
17
+ acceptedDecisionsAdded,
18
+ duplicatesSkipped,
19
+ clearedFields: result.preview.fieldsClearedOnApply,
20
+ summary,
21
+ },
22
+ };
23
+ }
24
+ const SOURCE_LABELS = {
25
+ "global-rules": "Global rules",
26
+ "before-phase-start": "Before phase start",
27
+ "before-task-start": "Before task start",
28
+ "after-phase-complete": "After phase complete",
29
+ };
30
+ function normalizeComparable(value) {
31
+ return value
32
+ .trim()
33
+ .replace(/^[\s#>*+-]+/, "")
34
+ .replace(/\s+/g, " ")
35
+ .toLocaleLowerCase("en-US");
36
+ }
37
+ function guidelineKeys(content) {
38
+ return new Set(content
39
+ .split(/\r?\n/)
40
+ .map(normalizeComparable)
41
+ .filter(Boolean));
42
+ }
43
+ function workflowEntries(workflowRules) {
44
+ return [
45
+ ...workflowRules.beforePhaseStart.map((text) => ({ source: "before-phase-start", text })),
46
+ ...workflowRules.beforeTaskStart.map((text) => ({ source: "before-task-start", text })),
47
+ ...workflowRules.afterPhaseComplete.map((text) => ({ source: "after-phase-complete", text })),
48
+ ];
49
+ }
50
+ function renderGuidelineAdditions(existing, additions) {
51
+ if (additions.length === 0)
52
+ return existing.trim();
53
+ const lines = ["## Migrated legacy project rules", ""];
54
+ for (const source of Object.keys(SOURCE_LABELS)) {
55
+ const entries = additions.filter((entry) => entry.source === source);
56
+ if (entries.length === 0)
57
+ continue;
58
+ lines.push(`### ${SOURCE_LABELS[source]}`, ...entries.map((entry) => `- ${entry.text}`), "");
59
+ }
60
+ const rendered = lines.join("\n").trim();
61
+ return existing.trim() ? `${existing.trim()}\n\n${rendered}` : rendered;
62
+ }
63
+ function decisionKey(value) {
64
+ if (typeof value === "string")
65
+ return normalizeComparable(value);
66
+ return normalizeComparable(value.decision || value.title);
67
+ }
68
+ function legacyDecisionId(decision) {
69
+ return `legacy-project-decision-${createHash("sha256").update(decisionKey(decision), "utf8").digest("hex").slice(0, 16)}`;
70
+ }
71
+ function legacyDecisionTitle(decision) {
72
+ const firstLine = decision.trim().split(/\r?\n/, 1)[0] ?? decision.trim();
73
+ return firstLine.length <= 100 ? firstLine : `${firstLine.slice(0, 97).trimEnd()}...`;
74
+ }
75
+ export function previewLegacyProjectContextMigration(project) {
76
+ const legacyGuidelines = [
77
+ ...project.globalRules.map((text) => ({ source: "global-rules", text })),
78
+ ...workflowEntries(project.workflowRules),
79
+ ];
80
+ const existingGuidelines = guidelineKeys(project.projectGuidelines.content);
81
+ const seenGuidelines = new Set(existingGuidelines);
82
+ const guidelineAdditions = [];
83
+ let skippedGuidelineDuplicates = 0;
84
+ for (const entry of legacyGuidelines) {
85
+ const text = entry.text.trim();
86
+ const key = normalizeComparable(text);
87
+ if (!key || seenGuidelines.has(key)) {
88
+ skippedGuidelineDuplicates += 1;
89
+ continue;
90
+ }
91
+ seenGuidelines.add(key);
92
+ guidelineAdditions.push({ ...entry, text });
93
+ }
94
+ const seenDecisions = new Set(project.acceptedDecisions.map(decisionKey));
95
+ const acceptedDecisionAdditions = [];
96
+ let skippedDecisionDuplicates = 0;
97
+ for (const legacyDecision of project.decisions) {
98
+ const decision = legacyDecision.trim();
99
+ const key = decisionKey(decision);
100
+ if (!key || seenDecisions.has(key)) {
101
+ skippedDecisionDuplicates += 1;
102
+ continue;
103
+ }
104
+ seenDecisions.add(key);
105
+ acceptedDecisionAdditions.push({
106
+ id: legacyDecisionId(decision),
107
+ title: legacyDecisionTitle(decision),
108
+ decision,
109
+ rationale: "Migrated from the legacy project decisions collection.",
110
+ implementationNotes: "Review and enrich this structured decision when additional rationale or implementation detail is available.",
111
+ });
112
+ }
113
+ const workflowRuleCount = project.workflowRules.beforePhaseStart.length
114
+ + project.workflowRules.beforeTaskStart.length
115
+ + project.workflowRules.afterPhaseComplete.length;
116
+ const fieldsClearedOnApply = [];
117
+ if (project.globalRules.length > 0)
118
+ fieldsClearedOnApply.push("globalRules");
119
+ if (workflowRuleCount > 0)
120
+ fieldsClearedOnApply.push("workflowRules");
121
+ if (project.decisions.length > 0)
122
+ fieldsClearedOnApply.push("decisions");
123
+ return {
124
+ version: LEGACY_PROJECT_CONTEXT_MIGRATION_VERSION,
125
+ hasLegacyContext: fieldsClearedOnApply.length > 0,
126
+ guidelinesChanged: guidelineAdditions.length > 0,
127
+ acceptedDecisionsChanged: acceptedDecisionAdditions.length > 0,
128
+ guidelineAdditions,
129
+ acceptedDecisionAdditions,
130
+ skippedGuidelineDuplicates,
131
+ skippedDecisionDuplicates,
132
+ resultingGuidelinesContent: renderGuidelineAdditions(project.projectGuidelines.content, guidelineAdditions),
133
+ legacyCounts: {
134
+ globalRules: project.globalRules.length,
135
+ workflowRules: workflowRuleCount,
136
+ decisions: project.decisions.length,
137
+ },
138
+ fieldsClearedOnApply,
139
+ };
140
+ }
141
+ export function applyLegacyProjectContextMigration(project, acceptedAt) {
142
+ const preview = previewLegacyProjectContextMigration(project);
143
+ if (!preview.hasLegacyContext)
144
+ return { applied: false, preview, project };
145
+ const acceptedDecisions = [
146
+ ...project.acceptedDecisions,
147
+ ...preview.acceptedDecisionAdditions.map((decision) => ({ ...decision, acceptedAt })),
148
+ ];
149
+ return {
150
+ applied: true,
151
+ preview,
152
+ project: {
153
+ ...project,
154
+ projectGuidelines: {
155
+ ...project.projectGuidelines,
156
+ content: preview.resultingGuidelinesContent,
157
+ },
158
+ globalRules: [],
159
+ workflowRules: {
160
+ beforePhaseStart: [],
161
+ beforeTaskStart: [],
162
+ afterPhaseComplete: [],
163
+ },
164
+ decisions: [],
165
+ acceptedDecisions,
166
+ },
167
+ };
168
+ }
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Session-scoped, ordered context-read enforcement for agent lifecycle operations.
2
+ * Session-scoped context-read enforcement for agent lifecycle operations.
3
3
  *
4
- * The first complete read for a task must be task(full) → phase(full) →
5
- * feature(full), with linked requirements read independently. A persisted
6
- * sessionInfo attestation may satisfy later checks in the same session while
7
- * every entity's updatedAt remains at or before its attestation timestamp.
4
+ * Task/phase/feature reads and linked requirements remain explicit, but fresh
5
+ * in-session reads may be performed in any order. Persisted sessionInfo
6
+ * attestations may satisfy later checks while the entity's current revision
7
+ * remains at or before the attested timestamp.
8
8
  */
9
9
  type SessionInfoEntry = {
10
10
  sessionId: string;
@@ -12,11 +12,26 @@ type SessionInfoEntry = {
12
12
  };
13
13
  type ReadTrackedEntity = {
14
14
  updatedAt: string;
15
+ descriptionUpdatedAt?: string;
15
16
  sessionInfo?: SessionInfoEntry[];
16
17
  };
18
+ type ProjectGuidelinesTrackedProject = {
19
+ projectGuidelines?: {
20
+ content?: string;
21
+ updatedAt?: string;
22
+ sessionInfo?: SessionInfoEntry[];
23
+ };
24
+ };
25
+ export type ContextReadEntityKind = "task" | "phase" | "feature";
26
+ export type RequiredContextRead = {
27
+ kind: ContextReadEntityKind;
28
+ id: string;
29
+ state: "missing" | "stale";
30
+ };
17
31
  export type ContextReadEligibility = {
18
32
  eligible: boolean;
19
33
  reason: string;
34
+ requiredReads?: RequiredContextRead[];
20
35
  };
21
36
  export interface SessionContextReadInput {
22
37
  sessionId: string;
@@ -48,11 +63,15 @@ export declare function markRequirementRead(requirementId: string): void;
48
63
  /** Record that a requirement was explicitly read for an explicit session. */
49
64
  export declare function markRequirementReadForSessionId(sessionId: string, requirementId: string): void;
50
65
  /**
51
- * Evaluate exact in-memory read ordering first, then a persisted attestation
52
- * for the same session and current entity revisions. A previously persisted
53
- * but now stale attestation always wins over stale in-memory ordering.
66
+ * Combine valid persisted attestations with fresh in-memory reads. An entity read
67
+ * in the current session satisfies eligibility regardless of sequence order,
68
+ * so agents can read task, phase, and feature in any order; only persisted
69
+ * attestations are checked for revision freshness (stale) and missing entities
70
+ * remain reported as missing.
54
71
  */
55
72
  export declare function contextReadEligibilityForSession(input: SessionContextReadInput): ContextReadEligibility;
73
+ export type ProjectGuidelinesReadState = "not-required" | "missing" | "stale" | "valid";
74
+ export declare function projectGuidelinesReadStateForSession(project: ProjectGuidelinesTrackedProject, sessionId: string): ProjectGuidelinesReadState;
56
75
  /** Return true only when the persisted attestation covers the current revisions. */
57
76
  export declare function hasValidSessionAttestation(input: SessionContextReadInput): boolean;
58
77
  /** Compatibility check for the default session and in-memory reads only. */
@@ -1 +1 @@
1
- {"version":3,"file":"read-tracking.d.ts","sourceRoot":"","sources":["../src/read-tracking.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-tracking.d.ts","sourceRoot":"","sources":["../src/read-tracking.ts"],"names":[],"mappings":"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"}