@agent-plan/pi-adapter 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AA+xBtF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8vF9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AAszBtF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAqxF9D"}
package/dist/index.js CHANGED
@@ -429,6 +429,24 @@ async function buildHandoffMarkdown(st, reason, overrides) {
429
429
  : inferredRecentChanges.length > 0
430
430
  ? inferredRecentChanges.map((entry) => `- ${entry}`)
431
431
  : ["- No recent activity recorded"];
432
+ // Auto-derived: all task statuses for the current phase, so a resuming agent
433
+ // sees the full picture (not just the single in-progress task).
434
+ const currentPhaseTaskLines = currentPhase && currentPhase.tasks.length > 0
435
+ ? [...currentPhase.tasks]
436
+ .sort((a, b) => a.number - b.number || a.createdAt.localeCompare(b.createdAt))
437
+ .map((task) => `- ${statusIcon(task.status)} \`${task.id}\` — ${task.title} (${task.status})`)
438
+ : [];
439
+ // Caller-supplied rich context sections (locked design decisions,
440
+ // architecture, mode/state flows, plugin/API contracts, data mappings,
441
+ // known gaps, ...) injected between "What was being done" and "How to resume".
442
+ const extraSectionLines = (overrides?.extraSections ?? []).flatMap((section) => [
443
+ "",
444
+ `## ${section.heading}`,
445
+ section.body,
446
+ ]);
447
+ const autoCurrentTaskSection = currentPhaseTaskLines.length > 0
448
+ ? ["", `## Current Task Statuses (phase ${currentPhase.id})`, ...currentPhaseTaskLines]
449
+ : [];
432
450
  return [
433
451
  "# Handoff",
434
452
  "",
@@ -448,6 +466,8 @@ async function buildHandoffMarkdown(st, reason, overrides) {
448
466
  "",
449
467
  "## What was being done",
450
468
  whatWasBeingDone || "No additional execution notes were captured.",
469
+ ...extraSectionLines,
470
+ ...autoCurrentTaskSection,
451
471
  "",
452
472
  "## How to resume",
453
473
  howToResume,
@@ -865,7 +885,9 @@ export default function planPiExtension(pi) {
865
885
  await st.ensureStructureOrdering().catch(() => { });
866
886
  // Reconcile derived statuses once on startup: backfills any drift from
867
887
  // manual edits, pre-fix data, or tools that bypassed the rollup.
868
- await st.syncStatuses().catch(() => { });
888
+ // Uses maybeHealStatuses (idempotent via healedStatusRoots guard) so the
889
+ // later call below and before_agent_start don't re-run it (startup dedup).
890
+ await maybeHealStatuses(st).catch(() => { });
869
891
  // Decide whether to start the web UI based on persisted prefs or prompt.
870
892
  let startWeb = false;
871
893
  if (project?.plannerAutoStartWeb) {
@@ -917,13 +939,19 @@ export default function planPiExtension(pi) {
917
939
  const url = server?.url ?? "Starting server...";
918
940
  ctx.ui.notify(`Planner enabled. Dashboard: ${url}\nAnalyzing project state and preparing resume summary...`, "info");
919
941
  await ensureProjectLanguagePreferences(st).catch(() => null);
920
- await maybeHealStatuses(st).catch(() => { });
942
+ // (maybeHealStatuses already ran above — skipped here thanks to the guard.)
921
943
  // Background cleanup of orphan .bak/.tmp.* files (non-blocking)
922
944
  st.cleanupOrphanBackups().catch(() => { });
923
945
  const handoff = await st.loadHandoff().catch(() => null);
924
946
  if (handoff?.content) {
925
947
  ctx.ui.notify(`Handoff detected at .planner/HANDOFF.md (updated ${handoff.updatedAt}). It will be loaded automatically when the agent starts.`, "info");
926
948
  }
949
+ // Mark heavy init done so before_agent_start doesn't re-run migration,
950
+ // status healing, and language prefs on the first turn (startup dedup:
951
+ // all of these already ran in this session_start block). refreshResume is
952
+ // safe to skip here because the per-turn context builder falls back to
953
+ // loadResume() ?? refreshResume() when building the system prompt.
954
+ plannerHeavyInitDone = true;
927
955
  pi.sendMessage({
928
956
  customType: "planner-resume-trigger",
929
957
  content: "Emit the mandatory planner startup resume summary now.",
@@ -2748,11 +2776,15 @@ export default function planPiExtension(pi) {
2748
2776
  pi.registerTool({
2749
2777
  name: "plan_write_handoff",
2750
2778
  label: "Plan Write Handoff",
2751
- description: "Write or refresh the canonical .planner/HANDOFF.md document.",
2779
+ description: "Write or refresh the canonical .planner/HANDOFF.md document. Capture full design context, not just operational resume steps: pass extraSections with locked decisions, architecture (with file:line refs), mode/state flows, plugin/API contracts, data mappings, files touched, and known gaps so a resuming agent doesn't re-discover decisions already made.",
2752
2780
  parameters: Type.Object({
2753
2781
  reason: Type.Optional(Type.String({ description: "Why the handoff is being written" })),
2754
2782
  whatWasBeingDone: Type.Optional(Type.String({ description: "Optional override for the current work summary" })),
2755
2783
  howToResume: Type.Optional(Type.String({ description: "Optional override for resume instructions" })),
2784
+ extraSections: Type.Optional(Type.Array(Type.Object({
2785
+ heading: Type.String({ description: "Section heading (without the leading ## markers)" }),
2786
+ body: Type.String({ description: "Markdown body of the section. Use file:line refs, IDs, and concrete mappings." }),
2787
+ }), { description: "Rich context sections injected between 'What was being done' and 'How to resume'. Use for: Locked Design Decisions ({id,title,decision,rationale}), Architecture (new modules with file:line), Mode/State Flow (textual diagrams), Plugin/API Contracts, Data Mappings, Files Touched (new/modified/planner), Known Gaps. Maximize the design context a resuming agent needs." })),
2756
2788
  }),
2757
2789
  async execute(_id, params, _signal, _onUpdate, ctx) {
2758
2790
  const st = await requirePlan(ctx);
@@ -2761,6 +2793,13 @@ export default function planPiExtension(pi) {
2761
2793
  await writeProjectHandoff(st, params.reason?.trim() || "manual tool handoff", {
2762
2794
  ...(params.whatWasBeingDone?.trim() ? { whatWasBeingDone: params.whatWasBeingDone.trim() } : {}),
2763
2795
  ...(params.howToResume?.trim() ? { howToResume: params.howToResume.trim() } : {}),
2796
+ ...(params.extraSections && params.extraSections.length > 0
2797
+ ? {
2798
+ extraSections: params.extraSections
2799
+ .map((section) => ({ heading: section.heading?.trim() ?? "", body: section.body ?? "" }))
2800
+ .filter((section) => section.heading),
2801
+ }
2802
+ : {}),
2764
2803
  });
2765
2804
  const handoff = await st.loadHandoff();
2766
2805
  return { content: [{ type: "text", text: "Wrote .planner/HANDOFF.md" }], details: handoff ?? {} };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-plan/pi-adapter",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "private": false,
5
5
  "description": "Pi agent extension for Agent Plan — structured project planning in .planner/",
6
6
  "keywords": [
@@ -25,11 +25,6 @@
25
25
  "."
26
26
  ]
27
27
  },
28
- "scripts": {
29
- "build": "tsc -p tsconfig.json && rm -f dist/.tsbuildinfo",
30
- "build:full": "pnpm build && ../../scripts/copy-web-ui.sh",
31
- "check": "tsc -p tsconfig.json --noEmit"
32
- },
33
28
  "dependencies": {
34
29
  "@agent-plan/core": "^0.2.0",
35
30
  "@agent-plan/server": "^0.2.0",
@@ -39,5 +34,10 @@
39
34
  "devDependencies": {
40
35
  "@earendil-works/pi-coding-agent": "^0.74.0",
41
36
  "@earendil-works/pi-ai": "^0.74.0"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.json && rm -f dist/.tsbuildinfo",
40
+ "build:full": "pnpm build && ../../scripts/copy-web-ui.sh",
41
+ "check": "tsc -p tsconfig.json --noEmit"
42
42
  }
43
- }
43
+ }