@agent-plan/core 0.2.26 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/description-freshness.d.ts +37 -0
- package/dist/description-freshness.d.ts.map +1 -0
- package/dist/description-freshness.js +84 -0
- package/dist/handoff-context.d.ts +135 -3
- package/dist/handoff-context.d.ts.map +1 -1
- package/dist/handoff-context.js +336 -25
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.d.ts.map +1 -1
- package/dist/package-version.js +1 -1
- package/dist/payload-fallback.d.ts +1 -1
- package/dist/payload-fallback.d.ts.map +1 -1
- package/dist/payload-fallback.js +6 -0
- package/dist/plan-store.d.ts +129 -30
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +690 -115
- package/dist/planner-rules.d.ts.map +1 -1
- package/dist/planner-rules.js +6 -2
- package/dist/read-tracking.d.ts +27 -3
- package/dist/read-tracking.d.ts.map +1 -1
- package/dist/read-tracking.js +53 -4
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +33 -9
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +0 -1
- package/dist/requirement-macro-tasks.d.ts +2 -2
- package/dist/requirement-macro-tasks.d.ts.map +1 -1
- package/dist/requirement-macro-tasks.js +2 -2
- package/dist/runtime-diagnostics.d.ts +34 -0
- package/dist/runtime-diagnostics.d.ts.map +1 -0
- package/dist/runtime-diagnostics.js +39 -0
- package/dist/schema.d.ts +487 -17
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +24 -4
- package/dist/task-context.d.ts +41 -2
- package/dist/task-context.d.ts.map +1 -1
- package/dist/task-context.js +102 -4
- package/dist/task-selection.d.ts +44 -1
- package/dist/task-selection.d.ts.map +1 -1
- package/dist/task-selection.js +158 -7
- package/dist/write-coordination.d.ts +27 -0
- package/dist/write-coordination.d.ts.map +1 -0
- package/dist/write-coordination.js +223 -0
- package/package.json +1 -1
- package/planner-skill.md +36 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-rules.d.ts","sourceRoot":"","sources":["../src/planner-rules.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/planner-rules.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
}
|
package/dist/read-tracking.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
83
|
-
*
|
|
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":"AAAA;;;;;;;GAOG;AAIH,KAAK,gBAAgB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAClC,CAAC;AAEF,KAAK,+BAA+B,GAAG;IACrC,iBAAiB,CAAC,EAAE;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAClC,CAAC;CACH,CAAC;AAUF,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"read-tracking.d.ts","sourceRoot":"","sources":["../src/read-tracking.ts"],"names":[],"mappings":"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"}
|
package/dist/read-tracking.js
CHANGED
|
@@ -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
|
-
*
|
|
188
|
-
*
|
|
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
|
|
226
|
+
export function requirementReadEligibilityForSession(sessionId, requirementIds, requirements = []) {
|
|
191
227
|
const state = stateFor(sessionId);
|
|
192
|
-
|
|
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) {
|
package/dist/recap.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
|
54
|
-
|
|
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 (
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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]}`);
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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:
|
|
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,
|
|
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
|
|
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 (!
|
|
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
|
+
}
|