@agent-plan/core 0.2.26 → 0.2.27

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 (47) hide show
  1. package/dist/description-freshness.d.ts +37 -0
  2. package/dist/description-freshness.d.ts.map +1 -0
  3. package/dist/description-freshness.js +84 -0
  4. package/dist/handoff-context.d.ts +134 -3
  5. package/dist/handoff-context.d.ts.map +1 -1
  6. package/dist/handoff-context.js +334 -16
  7. package/dist/index.d.ts +4 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +4 -1
  10. package/dist/package-version.d.ts +2 -0
  11. package/dist/package-version.d.ts.map +1 -1
  12. package/dist/package-version.js +1 -1
  13. package/dist/payload-fallback.d.ts +1 -1
  14. package/dist/payload-fallback.d.ts.map +1 -1
  15. package/dist/payload-fallback.js +6 -0
  16. package/dist/plan-store.d.ts +129 -30
  17. package/dist/plan-store.d.ts.map +1 -1
  18. package/dist/plan-store.js +685 -115
  19. package/dist/planner-rules.d.ts.map +1 -1
  20. package/dist/planner-rules.js +6 -2
  21. package/dist/read-tracking.d.ts +27 -3
  22. package/dist/read-tracking.d.ts.map +1 -1
  23. package/dist/read-tracking.js +53 -4
  24. package/dist/recap.d.ts.map +1 -1
  25. package/dist/recap.js +33 -9
  26. package/dist/renderer.d.ts.map +1 -1
  27. package/dist/renderer.js +0 -1
  28. package/dist/requirement-macro-tasks.d.ts +2 -2
  29. package/dist/requirement-macro-tasks.d.ts.map +1 -1
  30. package/dist/requirement-macro-tasks.js +2 -2
  31. package/dist/runtime-diagnostics.d.ts +34 -0
  32. package/dist/runtime-diagnostics.d.ts.map +1 -0
  33. package/dist/runtime-diagnostics.js +39 -0
  34. package/dist/schema.d.ts +487 -17
  35. package/dist/schema.d.ts.map +1 -1
  36. package/dist/schema.js +24 -4
  37. package/dist/task-context.d.ts +41 -2
  38. package/dist/task-context.d.ts.map +1 -1
  39. package/dist/task-context.js +102 -4
  40. package/dist/task-selection.d.ts +44 -1
  41. package/dist/task-selection.d.ts.map +1 -1
  42. package/dist/task-selection.js +158 -7
  43. package/dist/write-coordination.d.ts +27 -0
  44. package/dist/write-coordination.d.ts.map +1 -0
  45. package/dist/write-coordination.js +223 -0
  46. package/package.json +1 -1
  47. package/planner-skill.md +36 -20
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"planner-rules.d.ts","sourceRoot":"","sources":["../src/planner-rules.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,uBAAuB,EAAE,MAAM,EA6B3C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAWD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW/E"}
@@ -14,6 +14,8 @@ const DETAIL_WRITING_RULE = "Write relevant points (decisions, constraints, curr
14
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
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
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.";
17
+ const LEGACY_PROJECT_GUIDELINES_RULE = "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.";
18
+ const PROJECT_GUIDELINES_RULE = "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, verification process, best practices, and other project-specific rules only in Project Guidelines. Requirements are separate declarative user, business, or system outcomes with no lifecycle status; never store guidelines or agent behavior in Requirements. Nested Requirement macro-tasks retain implementation status.";
17
19
  export const PLANNER_EXTENSION_RULES = [
18
20
  // §1 — source of truth
19
21
  "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.",
@@ -22,7 +24,7 @@ export const PLANNER_EXTENSION_RULES = [
22
24
  // §3 — markdown not source of truth
23
25
  "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
26
  // §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.",
27
+ PROJECT_GUIDELINES_RULE,
26
28
  // §5 — plan location
27
29
  "The plan lives in .planner/ within the target project. Whether .planner/ is git-tracked is at the project's discretion.",
28
30
  // §6 — discuss per phase
@@ -34,7 +36,7 @@ export const PLANNER_EXTENSION_RULES = [
34
36
  // §10 — references
35
37
  "Reference entities with human, unique, composite IDs — Feature 'F001 - Name', Phase 'P001(F001) - Title', Task 'T003 - Number'. Short forms P003/T007 and the 5-char global shortId (e.g. UUXD1) are also valid. Never reference raw UUIDs. To locate an entity, use the compact list tools (feature_list/phase_list/task_list), not by reading .planner/*.json files.",
36
38
  // §12 — handoff
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.",
39
+ "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 before drafting, use its exact scaffold, review conversation/approvals, planner and sibling context, diff/implementation, verification/runtime evidence, and peer-agent/network messages, then inventory concrete files, symbols, ownership/completion state, work not started, runtime wiring, preservation constraints, proof observations, related planned work, operator actions, and ordered resume steps. Every inventory item must appear in the handoff or a validated supporting document. Reconcile all still-relevant existing content and synchronize durable task/phase/feature context in the same handoff_write operation. A pending handoff never blocks task_start; every canonical terminal phase outcome archives it automatically, explicit clear also archives it, and refresh must not create superseded copies.",
38
40
  // §12 — operational hygiene
39
41
  "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.",
40
42
  // Planner startup
@@ -50,6 +52,8 @@ function normalizeLegacyRules(rules) {
50
52
  return DETAIL_WRITING_RULE;
51
53
  if (rule === LEGACY_EXPECTED_OPERATIONAL_RULE)
52
54
  return EXPECTED_OPERATIONAL_RULE;
55
+ if (rule === LEGACY_PROJECT_GUIDELINES_RULE)
56
+ return PROJECT_GUIDELINES_RULE;
53
57
  return rule;
54
58
  });
55
59
  }
@@ -22,7 +22,19 @@ type ProjectGuidelinesTrackedProject = {
22
22
  sessionInfo?: SessionInfoEntry[];
23
23
  };
24
24
  };
25
- export type ContextReadEntityKind = "task" | "phase" | "feature";
25
+ export type ContextReadEntityKind = "task" | "phase" | "feature" | "requirement";
26
+ export type CanonicalFullReadEntityKind = "task" | "phase" | "feature";
27
+ type CanonicalReadEntity = ReadTrackedEntity & {
28
+ id: string;
29
+ acceptedDecisions?: Array<{
30
+ id: string;
31
+ title: string;
32
+ decision: string;
33
+ rationale: string;
34
+ implementationNotes: string;
35
+ acceptedAt: string;
36
+ }>;
37
+ };
26
38
  export type RequiredContextRead = {
27
39
  kind: ContextReadEntityKind;
28
40
  id: string;
@@ -50,6 +62,12 @@ export interface SessionContextReadInput {
50
62
  export declare function markFeatureRead(featureId: string): void;
51
63
  /** Record a full feature read for an explicit harness session. */
52
64
  export declare function markFeatureReadForSessionId(sessionId: string, featureId: string): void;
65
+ /**
66
+ * Record a canonical feature/phase/task full read only after its visible tool
67
+ * content contains every field of every Accepted Decision. This prevents an
68
+ * adapter from certifying a title-only or otherwise incomplete decision read.
69
+ */
70
+ export declare function markCanonicalFullReadForSessionId(sessionId: string, kind: CanonicalFullReadEntityKind, entity: CanonicalReadEntity, deliveredContent: string): void;
53
71
  /** Record a full phase read in the default compatibility session. */
54
72
  export declare function markPhaseRead(phaseId: string, _featureId?: string): void;
55
73
  /** Record a full phase read for an explicit harness session. */
@@ -79,9 +97,15 @@ export declare function contextReadEligibility(taskId: string, phaseId: string,
79
97
  /** Legacy parent-read check retained for callers that only need independent parent state. */
80
98
  export declare function hasReadParents(featureId: string | undefined, phaseId: string): boolean;
81
99
  /**
82
- * Whether linked requirements are read in memory or have valid persisted
83
- * attestations for the current session and entity revisions.
100
+ * Report the exact linked requirements whose delivered read evidence is missing
101
+ * or stale for this session. A broad requirement inventory must not call the
102
+ * mark function; only a target-scoped response that actually includes the
103
+ * linked requirement records may create fresh in-memory evidence.
84
104
  */
105
+ export declare function requirementReadEligibilityForSession(sessionId: string, requirementIds: string[], requirements?: Array<ReadTrackedEntity & {
106
+ id: string;
107
+ }>): ContextReadEligibility;
108
+ /** Whether every linked requirement has fresh delivered read evidence. */
85
109
  export declare function hasReadRequirementsForSession(sessionId: string, requirementIds: string[], requirements?: Array<ReadTrackedEntity & {
86
110
  id: string;
87
111
  }>): boolean;
@@ -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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"}
@@ -51,6 +51,40 @@ export function markFeatureRead(featureId) {
51
51
  export function markFeatureReadForSessionId(sessionId, featureId) {
52
52
  markFeatureReadForSession(sessionId, featureId);
53
53
  }
54
+ function deliveredAcceptedDecisionField(content, value) {
55
+ const lines = value.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
56
+ return lines.every((line) => content.includes(line));
57
+ }
58
+ /**
59
+ * Record a canonical feature/phase/task full read only after its visible tool
60
+ * content contains every field of every Accepted Decision. This prevents an
61
+ * adapter from certifying a title-only or otherwise incomplete decision read.
62
+ */
63
+ export function markCanonicalFullReadForSessionId(sessionId, kind, entity, deliveredContent) {
64
+ const acceptedDecisions = entity.acceptedDecisions ?? [];
65
+ const omitted = [
66
+ ...(!deliveredContent.includes(`Accepted Decisions (${acceptedDecisions.length}):`) ? ["context-marker"] : []),
67
+ ...acceptedDecisions.flatMap((acceptedDecision) => [
68
+ ["id", acceptedDecision.id],
69
+ ["title", acceptedDecision.title],
70
+ ["decision", acceptedDecision.decision],
71
+ ["rationale", acceptedDecision.rationale],
72
+ ["implementationNotes", acceptedDecision.implementationNotes],
73
+ ["acceptedAt", acceptedDecision.acceptedAt],
74
+ ]
75
+ .filter(([, value]) => !deliveredAcceptedDecisionField(deliveredContent, value))
76
+ .map(([field]) => `${acceptedDecision.id}.${field}`)),
77
+ ];
78
+ if (omitted.length > 0) {
79
+ throw new Error(`Cannot attest ${kind} ${entity.id} as fully read: omitted Accepted Decision fields: ${omitted.join(", ")}.`);
80
+ }
81
+ if (kind === "feature")
82
+ markFeatureReadForSession(sessionId, entity.id);
83
+ else if (kind === "phase")
84
+ markPhaseReadForSession(sessionId, entity.id);
85
+ else
86
+ markTaskReadForSession(sessionId, entity.id);
87
+ }
54
88
  /** Record a full phase read in the default compatibility session. */
55
89
  export function markPhaseRead(phaseId, _featureId) {
56
90
  markPhaseReadForSession(DEFAULT_SESSION_ID, phaseId);
@@ -184,12 +218,27 @@ export function hasReadParents(featureId, phaseId) {
184
218
  return state.phases.has(phaseId) && (!featureId || state.features.has(featureId));
185
219
  }
186
220
  /**
187
- * Whether linked requirements are read in memory or have valid persisted
188
- * attestations for the current session and entity revisions.
221
+ * Report the exact linked requirements whose delivered read evidence is missing
222
+ * or stale for this session. A broad requirement inventory must not call the
223
+ * mark function; only a target-scoped response that actually includes the
224
+ * linked requirement records may create fresh in-memory evidence.
189
225
  */
190
- export function hasReadRequirementsForSession(sessionId, requirementIds, requirements = []) {
226
+ export function requirementReadEligibilityForSession(sessionId, requirementIds, requirements = []) {
191
227
  const state = stateFor(sessionId);
192
- return requirementIds.every((id) => state.requirements.has(id) || validSessionInfo(requirements.find((requirement) => requirement.id === id), sessionId));
228
+ const requiredReads = [];
229
+ for (const id of [...new Set(requirementIds)]) {
230
+ const stored = storedReadState(requirements.find((requirement) => requirement.id === id), sessionId, "requirement");
231
+ if (state.requirements.has(id) || stored === "valid")
232
+ continue;
233
+ requiredReads.push({ kind: "requirement", id, state: stored === "stale" ? "stale" : "missing" });
234
+ }
235
+ if (requiredReads.length === 0)
236
+ return { eligible: true, reason: "" };
237
+ return { eligible: false, reason: requiredReadReason(requiredReads), requiredReads };
238
+ }
239
+ /** Whether every linked requirement has fresh delivered read evidence. */
240
+ export function hasReadRequirementsForSession(sessionId, requirementIds, requirements = []) {
241
+ return requirementReadEligibilityForSession(sessionId, requirementIds, requirements).eligible;
193
242
  }
194
243
  /** Legacy requirement check for the default compatibility session. */
195
244
  export function hasReadRequirements(requirementIds) {
@@ -1 +1 @@
1
- {"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../src/recap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,GAAE,YAAiB,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6OhH"}
1
+ {"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../src/recap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,GAAE,YAAiB,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4QhH"}
package/dist/recap.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { formatPhaseRef, formatTwoDigitNumber } from "./naming.js";
2
+ import { buildPhaseWorkMap } from "./task-context.js";
2
3
  const fref = (n) => `F${formatTwoDigitNumber(n)}`;
3
4
  const tref = (n) => `T${formatTwoDigitNumber(n)}`;
4
5
  /**
@@ -32,7 +33,8 @@ export async function buildRecap(st, web = {}, opts = {}) {
32
33
  const activeP = phases.filter((x) => x.status === "in-progress" || x.status === "discovery").length;
33
34
  const totalT = allTasks.length;
34
35
  const doneT = allTasks.filter(({ task }) => task.status === "done").length;
35
- const activeT = allTasks.filter(({ task }) => task.status === "in-progress").length;
36
+ const activeTasks = allTasks.filter(({ task }) => task.status === "in-progress");
37
+ const activeT = activeTasks.length;
36
38
  const checkpointedTasks = allTasks.filter(({ task }) => !["done", "canceled", "rejected"].includes(task.status) && task.pauseSnapshot);
37
39
  const checkpointedT = checkpointedTasks.length;
38
40
  const pendingDeviation = [...plan.project.workDeviations]
@@ -50,8 +52,9 @@ export async function buildRecap(st, web = {}, opts = {}) {
50
52
  // Plan is fully complete: there is work and all of it is done, nothing active.
51
53
  // (totalT > 0 guards the empty/unstarted case from looking "complete".)
52
54
  const planComplete = totalT > 0 && doneT === totalT && doneP === totalP && doneF === totalF;
53
- // Current focus = first in-progress task (and its phase/feature).
54
- const focusTask = allTasks.find(({ task }) => task.status === "in-progress");
55
+ // Current focus is authoritative only when exactly one task is in progress.
56
+ // Multiple active tasks are an explicit conflict, never a reason to pick the first silently.
57
+ const focusTask = activeTasks.length === 1 ? activeTasks[0] : undefined;
55
58
  const focusPhase = focusTask?.phase;
56
59
  const focusFeature = focusPhase ? feats.find((x) => x.id === focusPhase.featureId) : undefined;
57
60
  const italian = (plan.project.chatLanguage || "").toLowerCase().includes("ital");
@@ -71,7 +74,16 @@ export async function buildRecap(st, web = {}, opts = {}) {
71
74
  lines.push(italian
72
75
  ? `Avanzamento: feature ${doneF}/${totalF} completate (${activeF} attive) · fasi ${doneP}/${totalP} completate (${activeP} attive) · task ${doneT}/${totalT} completati (${activeT} attivi, ${checkpointedT} con checkpoint)`
73
76
  : `Progress: Features ${doneF}/${totalF} done (${activeF} active) · Phases ${doneP}/${totalP} done (${activeP} active) · Tasks ${doneT}/${totalT} done (${activeT} active, ${checkpointedT} with checkpoints)`);
74
- if (focusTask && focusPhase) {
77
+ if (activeTasks.length > 1) {
78
+ const conflicts = activeTasks.map(({ phase, task }) => {
79
+ const feature = feats.find((entry) => entry.id === phase.featureId);
80
+ return `${formatPhaseRef(phase.number, feature?.number)}/${tref(task.number)} — ${task.title}`;
81
+ });
82
+ lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "CONFLITTO TASK ATTIVI" : "ACTIVE TASK CONFLICT"} — ${activeTasks.length} ${italian ? "task risultano in-progress" : "tasks are in progress"}: ${conflicts.join("; ")}`, "", italian
83
+ ? `Esegui ${cmd("task_recommend", "planner-task-recommend")} e riconcilia esplicitamente il conflitto prima di dichiarare un focus.`
84
+ : `Run ${cmd("task_recommend", "planner-task-recommend")} and explicitly reconcile the conflict before claiming a current focus.`);
85
+ }
86
+ else if (focusTask && focusPhase) {
75
87
  const fr = focusFeature ? fref(focusFeature.number) : "?";
76
88
  const pr = formatPhaseRef(focusPhase.number, focusFeature?.number);
77
89
  const tr = tref(focusTask.task.number);
@@ -90,7 +102,7 @@ export async function buildRecap(st, web = {}, opts = {}) {
90
102
  }
91
103
  else if (handoffs.length > 0) {
92
104
  const top = handoffs[0];
93
- lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo" : "no active task"} · ${italian ? "handoff pendente più recente" : "most recent pending handoff"}: ${top.compositeRef} — "${top.firstLine}"`);
105
+ lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo (verificato dagli stati persistiti di tutti i task)" : "no active task (verified from all persisted task statuses)"} · ${italian ? "handoff pendente più recente" : "most recent pending handoff"}: ${top.compositeRef} — "${top.firstLine}" (${top.resumeReady ? "resume-ready" : italian ? "verifica read-back richiesta" : "read-back verification required"})`);
94
106
  }
95
107
  else if (planComplete) {
96
108
  lines.push(italian
@@ -98,7 +110,14 @@ export async function buildRecap(st, web = {}, opts = {}) {
98
110
  : "Current focus: plan complete — all features/phases/tasks are done.");
99
111
  }
100
112
  else {
101
- lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo — rivedi il piano e scegli il prossimo task concreto" : "no active task — review the plan and pick the next concrete task"}`);
113
+ lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo (verificato dagli stati persistiti di tutti i task) — rivedi il piano e scegli il prossimo task concreto" : "no active task (verified from all persisted task statuses) — review the plan and pick the next concrete task"}`);
114
+ }
115
+ const orientation = focusTask ?? pendingResume ?? latestStandaloneCheckpoint;
116
+ if (orientation) {
117
+ const feature = feats.find((entry) => entry.id === orientation.phase.featureId);
118
+ lines.push("", buildPhaseWorkMap(orientation.phase, feature?.number, orientation.task.id, 4_000).content, italian
119
+ ? "Prima di proporre nuovo lavoro, rileggi la fase canonica e il task fratello pertinente: non duplicare capability già assegnate."
120
+ : "Before proposing new work, reread the canonical phase and the relevant sibling task: do not duplicate an already-owned capability.");
102
121
  }
103
122
  // Next step: the phase handoff (phase.handoff) is the authoritative,
104
123
  // actively-managed resume context. When a handoff is pending, point to it
@@ -120,9 +139,14 @@ export async function buildRecap(st, web = {}, opts = {}) {
120
139
  : `Resume advisory: evaluate the newest checkpoint, ${ref}, with ${taskStartCmd} before deciding whether to return to it or start other work.`);
121
140
  }
122
141
  else if (handoffs.length > 0) {
123
- lines.push(italian
124
- ? `Prossimo step: leggi l'handoff di fase pendente sotto (fonte autorevole, gestita attivamente). I nextSteps legacy di resume.json sono soppressi perché possono essere stale.`
125
- : `Next step: read the pending phase handoff below (authoritative, actively maintained). Legacy resume.json nextSteps are suppressed because they may be stale.`);
142
+ const unverified = handoffs.filter((handoff) => !handoff.resumeReady);
143
+ lines.push(unverified.length > 0
144
+ ? (italian
145
+ ? `Prossimo step: ${unverified.length} handoff candidato richiede ancora verifica read-back; non trattarlo come completo o autorevole finché handoff_verify non restituisce resumeReady=true.`
146
+ : `Next step: ${unverified.length} handoff candidate still requires read-back verification; do not treat it as complete or authoritative until ${cmd("handoff_verify", "planner-handoff-verify")} returns resumeReady=true.`)
147
+ : (italian
148
+ ? `Prossimo step: leggi l'handoff di fase pendente sotto (fonte autorevole, gestita attivamente). I nextSteps legacy di resume.json sono soppressi perché possono essere stale.`
149
+ : `Next step: read the pending phase handoff below (authoritative, actively maintained). Legacy resume.json nextSteps are suppressed because they may be stale.`));
126
150
  }
127
151
  else if (!planComplete && resume?.nextSteps?.length) {
128
152
  lines.push(`${italian ? "Prossimo step" : "Next step"}: ${resume.nextSteps[0]}`);
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAAQ,KAAK,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAuB5G,qBAAa,YAAY;IACvB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAgMvC,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM;IAIjC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,eAAe;IA2GvB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM;IAmDxD,mEAAmE;IACnE,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAejD"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAAQ,KAAK,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAuB5G,qBAAa,YAAY;IACvB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IA+LvC,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM;IAIjC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,eAAe;IA2GvB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM;IAmDxD,mEAAmE;IACnE,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAejD"}
package/dist/renderer.js CHANGED
@@ -169,7 +169,6 @@ export class PlanRenderer {
169
169
  lines.push(req.description);
170
170
  }
171
171
  lines.push("");
172
- lines.push(`Status: ${statusBadge(req.status)}`);
173
172
  if (req.linkedPhaseIds.length > 0) {
174
173
  lines.push(`Phases: ${req.linkedPhaseIds.map((p) => `\`${p}\``).join(", ")}`);
175
174
  }
@@ -1,10 +1,10 @@
1
- import type { MacroTask, RequirementStatus } from "./schema.js";
1
+ import type { MacroTask, MacroTaskStatus } from "./schema.js";
2
2
  export interface MacroTaskMutationInput {
3
3
  /** Existing persisted ID only. Omit it for a new macro task. */
4
4
  id?: string;
5
5
  title: string;
6
6
  description?: string;
7
- status: RequirementStatus;
7
+ status: MacroTaskStatus;
8
8
  }
9
9
  export declare class RequirementMacroTaskError extends Error {
10
10
  constructor(message: string);
@@ -1 +1 @@
1
- {"version":3,"file":"requirement-macro-tasks.d.ts","sourceRoot":"","sources":["../src/requirement-macro-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAMhE,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAUD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,MAAM,EAAE,SAAS,sBAAsB,EAAE,EACzC,SAAS,EAAE,MAAM,GAChB,SAAS,EAAE,CA+Bb"}
1
+ {"version":3,"file":"requirement-macro-tasks.d.ts","sourceRoot":"","sources":["../src/requirement-macro-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAM9D,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AAUD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,MAAM,EAAE,SAAS,sBAAsB,EAAE,EACzC,SAAS,EAAE,MAAM,GAChB,SAAS,EAAE,CA+Bb"}
@@ -1,4 +1,4 @@
1
- const REQUIREMENT_STATUSES = new Set([
1
+ const MACRO_TASK_STATUSES = new Set([
2
2
  "planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting",
3
3
  ]);
4
4
  export class RequirementMacroTaskError extends Error {
@@ -28,7 +28,7 @@ export function reconcileRequirementMacroTasks(existing, inputs, timestamp) {
28
28
  const title = input.title.trim();
29
29
  if (!title)
30
30
  throw new RequirementMacroTaskError(`Macro task ${index + 1} requires a title.`);
31
- if (!REQUIREMENT_STATUSES.has(input.status)) {
31
+ if (!MACRO_TASK_STATUSES.has(input.status)) {
32
32
  throw new RequirementMacroTaskError(`Macro task ${index + 1} has an invalid status: ${input.status}.`);
33
33
  }
34
34
  const requestedId = input.id?.trim();
@@ -0,0 +1,34 @@
1
+ import type { RuntimePackageVersion } from "./package-version.js";
2
+ export declare const PLAN_SCHEMA_VERSION = 1;
3
+ export declare const ALLOCATION_REGISTRY_VERSION = 1;
4
+ export declare const SUPPORTED_ALLOCATION_KINDS: readonly ["feature", "phase", "task", "idea"];
5
+ export type AllocationKind = typeof SUPPORTED_ALLOCATION_KINDS[number];
6
+ export interface RuntimePackageDiagnostic {
7
+ name: string;
8
+ installedVersion: string;
9
+ loadedVersion: string;
10
+ runtimeState: "loaded";
11
+ versionSource: "loaded-package-manifest";
12
+ packageJsonPath?: string | undefined;
13
+ }
14
+ export interface RuntimeCapabilities {
15
+ planSchema: {
16
+ manifestSchemaVersion: typeof PLAN_SCHEMA_VERSION;
17
+ };
18
+ allocationRegistry: {
19
+ version: typeof ALLOCATION_REGISTRY_VERSION;
20
+ supportedKinds: readonly AllocationKind[];
21
+ };
22
+ }
23
+ export declare function runtimePackageDiagnostic(pkg: RuntimePackageVersion): RuntimePackageDiagnostic;
24
+ export declare function runtimePackagesDiagnostic(packages: RuntimePackageVersion[]): Record<string, RuntimePackageDiagnostic>;
25
+ export declare function runtimeCapabilities(): RuntimeCapabilities;
26
+ export declare function isSupportedAllocationKind(kind: string): kind is AllocationKind;
27
+ export declare function unsupportedAllocationKindDetails(kind: string): {
28
+ errorCode: "PLAN_UNSUPPORTED_ALLOCATION_KIND";
29
+ kind: string;
30
+ supportedKinds: readonly ["feature", "phase", "task", "idea"];
31
+ requiredCapability: string;
32
+ action: string;
33
+ };
34
+ //# sourceMappingURL=runtime-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-diagnostics.d.ts","sourceRoot":"","sources":["../src/runtime-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,0BAA0B,+CAAgD,CAAC;AAExF,MAAM,MAAM,cAAc,GAAG,OAAO,0BAA0B,CAAC,MAAM,CAAC,CAAC;AAEvE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,QAAQ,CAAC;IACvB,aAAa,EAAE,yBAAyB,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE;QACV,qBAAqB,EAAE,OAAO,mBAAmB,CAAC;KACnD,CAAC;IACF,kBAAkB,EAAE;QAClB,OAAO,EAAE,OAAO,2BAA2B,CAAC;QAC5C,cAAc,EAAE,SAAS,cAAc,EAAE,CAAC;KAC3C,CAAC;CACH;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,qBAAqB,GAAG,wBAAwB,CAS7F;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAErH;AAED,wBAAgB,mBAAmB,IAAI,mBAAmB,CAUzD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,cAAc,CAE9E;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM;;;;;;EAQ5D"}
@@ -0,0 +1,39 @@
1
+ export const PLAN_SCHEMA_VERSION = 1;
2
+ export const ALLOCATION_REGISTRY_VERSION = 1;
3
+ export const SUPPORTED_ALLOCATION_KINDS = ["feature", "phase", "task", "idea"];
4
+ export function runtimePackageDiagnostic(pkg) {
5
+ return {
6
+ name: pkg.name,
7
+ installedVersion: pkg.version,
8
+ loadedVersion: pkg.version,
9
+ runtimeState: "loaded",
10
+ versionSource: "loaded-package-manifest",
11
+ ...(pkg.packageJsonPath ? { packageJsonPath: pkg.packageJsonPath } : {}),
12
+ };
13
+ }
14
+ export function runtimePackagesDiagnostic(packages) {
15
+ return Object.fromEntries(packages.map((pkg) => [pkg.name, runtimePackageDiagnostic(pkg)]));
16
+ }
17
+ export function runtimeCapabilities() {
18
+ return {
19
+ planSchema: {
20
+ manifestSchemaVersion: PLAN_SCHEMA_VERSION,
21
+ },
22
+ allocationRegistry: {
23
+ version: ALLOCATION_REGISTRY_VERSION,
24
+ supportedKinds: SUPPORTED_ALLOCATION_KINDS,
25
+ },
26
+ };
27
+ }
28
+ export function isSupportedAllocationKind(kind) {
29
+ return SUPPORTED_ALLOCATION_KINDS.includes(kind);
30
+ }
31
+ export function unsupportedAllocationKindDetails(kind) {
32
+ return {
33
+ errorCode: "PLAN_UNSUPPORTED_ALLOCATION_KIND",
34
+ kind,
35
+ supportedKinds: SUPPORTED_ALLOCATION_KINDS,
36
+ requiredCapability: "allocationRegistry.supportedKinds",
37
+ action: "Upgrade all Agent Plan packages and reload the harness so the loaded runtime supports this allocation kind before retrying the mutation.",
38
+ };
39
+ }