@eforge-build/eforge-plan
v0.8.1
Published
First-party eforge planning extension with backlog, session-plan, recommendation, and workstation contributions.
Maintainers
Readme
eforge-plan Extension
eforge-plan is a reference extension for curating a project-local backlog and promoting selected backlog items into normal eforge build inputs. It is intentionally dogfoodable: project teams can keep lightweight planning records in the repository, render a derived kanban board, promote work into session plans, and correlate later eforge lifecycle events back to the originating backlog item.
The extension does not replace session plans or normalized build-source preprocessing. It produces ordinary build-source Markdown and .eforge/session-plans/<session>.md artifacts that the existing eforge engine can consume.
Trust model
Extensions run as project-team code. Install and enable eforge-plan only in repositories where you trust the extension source and the team-maintained backlog content.
eforge-plan is not a sandbox boundary. Actions can read and write project-local files, and lifecycle hooks update extension-owned private storage. The Console workstation is served from packaged browser assets whose files are covered by the extension trust hash. Review extension changes with the same care as build tooling, scripts, or other automation that runs in the repository.
Private planning state is stored under .eforge/storage/extensions/eforge-plan/, including the normalized SQLite store at .eforge/storage/extensions/eforge-plan/eforge-plan-private.sqlite. Treat that directory as local/private project metadata: it can include backlog records, recommendation models, roadmap steering, lifecycle evidence, accepted-analysis baselines, revision annotations, and AI planning-task workflow indexes. Do not assume it is safe to publish without review.
Install and manage
eforge-plan is published as the first-party npm package @eforge-build/eforge-plan. The package declares eforge.extension.name: "eforge-plan" and loads from the compiled runtime entrypoint ./dist/index.js.
# Install from npm into the default local scope (.eforge/extensions/)
eforge extension install @eforge-build/eforge-plan
# Install from a local package directory or packed tarball after building
eforge extension install ./eforge/extensions/eforge-plan
eforge extension install ./eforge/extensions/eforge-plan/eforge-build-eforge-plan-<version>.tgz
# Install into the project/team scope and trust the reviewed artifact
eforge extension install @eforge-build/eforge-plan --scope project --trustScope behavior follows normal extension management rules:
local(default) installs under.eforge/extensions/and loads without a project/team trust record.projectinstalls undereforge/extensions/; each user must inspect and runeforge extension trust eforge-plan, or install/update with--trust, before it loads.userinstalls under the user eforge config directory and is trusted for that user.
Common lifecycle commands:
eforge extension validate eforge-plan
eforge extension trust eforge-plan
eforge extension reload
eforge extension show eforge-plan
eforge extension update eforge-plan
eforge extension update eforge-plan --version latest
eforge extension update eforge-plan --version 0.9.0
eforge extension remove eforge-plan--version <specifier> is for npm-installed extensions and may be a version, range, or dist-tag understood by npm. Local directory and tarball installs update from their recorded sidecar source rather than from a registry version specifier. Updating a project/team install changes the reviewed hash; update with --trust after inspection or run eforge extension trust eforge-plan again before reloading.
The npm artifact contains the compiled runtime in dist/, the generated workstation bundle in workstation-assets/plans/, README.md, LICENSE, and package metadata. Source-only workstation files, tests, and development config are not part of the runtime artifact.
Enable
After adding, installing, or changing the extension, validate, trust when required, and reload it from the repository root:
eforge extension validate eforge-plan
eforge extension trust eforge-plan
eforge extension reloadRun eforge extension show eforge-plan to confirm the registered actions, integration commands, deep links, Console workstation, and input source.
Declared capabilities
The directory extension manifest declares one stable first-party capability:
eforge.plan.planning-workstationversion1.0.0— the extension owns the rich planning workstation UI and generic planning entry continuation surface.
Planning entry is exposed through generic extension contribution discovery. Hosts can list or invoke the eforge-plan:open-planning-entry action or integration command, or follow the action-backed eforge-plan:planning-workstation deep link. All return or point at the workstation URL /console/workstations/eforge-plan%3Aplanning-workstation.
Usage
Registered action IDs can be invoked by hosts that expose extension actions:
Backlog captures are guarded to keep open items session-plan-ready: capture-item requires concrete acceptance criteria and rejects exploration/revisit/research-style language. Do exploration before capture, then record the chosen implementation change.
capture-itemexample input:{ "title": "Add import preview", "claim": "Add a preview step so users can inspect imports before enqueue.", "evidence": "Support tickets mention import mistakes.", "tags": ["ux"], "priority": "high", "epic": "planning", "dependsOn": [], "acceptanceCriteria": "Preview renders changed files and can be cancelled." }update-itemmetadata-only example input:{ "id": "add-import-preview", "status": "planned", "priority": "high", "tags": ["ux", "ready"], "evidenceNotes": "Validated with design review.", "recheckNotes": "Recheck after first import flow lands.", "dependsOn": ["import-parser"], "epic": "planning" }; metadata-only updates preserve body content and do not require a body lock.promote-itemexample input:{ "itemId": "add-import-preview", "status": "active", "session": "2026-06-05-add-import-preview", "profile": "excursion" }render-board-markdownexample input:{ "includeArchive": false }list-board-compactexample input:{ "epic": "planning", "limit": 20, "offset": 0 }; returns bounded open item summaries by default plus SQL-derived lane counts, total/open/closed counts, pagination metadata, effective lifecycle, user status, reason codes, backendplanEligible/eligibility reason fields, and compact evidence links without full board payloads. Closed lanes are lazy: request them explicitly with inputs such as{ "lane": "done", "includeClosed": true, "limit": 20, "offset": 0 }or{ "lane": "archive", "includeClosed": true, "includeArchive": true }. Projection flags: passincludeEpics: falseto omit compact epic summaries,includeLaneCounts: falseto omitlanesand aggregatecounts, orincludeDependencies: falseto omit dependency id arrays from item summaries.get-itemexample input:{ "id": "add-import-preview" }; returns one item withstatus/userStatusfrom the explicit backlog row, SQL-derived lifecycle state and reason codes, backendplanEligible/eligibility reason fields, compact dependency/dependent summaries, associated plan/build links, lifecycle evidence rows, Markdown sections, and body lock fields includingbodySha256/recordSha256. The workstation calls this lazily when a detail drawer opens. PassincludeBody: trueonly when raw item Markdown is needed. Projection flagsincludeEpic,includeSections,includeLifecycleRows,includeDependencies, andincludeDependentscan be set tofalseto omit those optional fields.get-epicexample input:{ "id": "planning", "limit": 20, "offset": 0 }; returns one epic with SQLite item counts, open item counts, and paginated compact item summaries. PassincludeBody: trueonly when raw epic Markdown is needed. Projection flags includeincludeItems: false,includeSections: false, andincludeItemDependencies: falsefor narrower responses. WithincludeItems: false, the response intentionally hasitems: []andtotalItems: 0; callers that need counts without item rows should read the compactepic.itemCountandepic.openItemCountfields.search-itemsexample input:{ "query": "import preview", "status": "planned", "limit": 20 }; searches canonical SQLite/FTS backlog item documents by id/title/tags/epic with bounded compact output, ranked matches, snippets, counts, pagination metadata, and explicit index freshness metadata. PasssearchBody: trueto include claim/evidence/acceptance-criteria/body-summary text in the FTS match,includeEpics: trueto include compact epics for matched items, orincludeDependencies: falseto omit dependency id arrays from item summaries. Limits default to20and are capped at100.search-planning-recordsexample input:{ "query": "import preview", "types": ["backlog_item", "session_plan"], "fields": ["snippet", "refs"], "limit": 20 }; searches the all-domain FTS index across backlog items, epics, flat session-plan summaries, and recommendation text. Results always includeid,type, andtitle; optionalfieldscan addrank,snippet,refs, andupdatedAt. The response includes counts by type, offset pagination, and the same dirty-index metadata assearch-itemswithout returning raw item bodies, recommendation JSON, or session-plan Markdown bodies.get-store-statusexample input:{}; reports whether the private SQLite store exists, DB/WAL/SHM byte sizes, schema version, table counts, retention eligibility counts, search-index status, and recent maintenance runs. It does not create the store when it is absent.compact-planning-storeexample input:{ "dryRun": true, "olderThanDays": 90 }; computes explicit retention candidates for prunable lifecycle event payloads, terminal planning-task raw payloads, and superseded non-current recommendation runs.dryRundefaults totrue; apply mode requires{ "dryRun": false }, keeps action output bounded, and never returns raw payload text.rebuild-search-indexexample input:{ "types": ["backlog_item", "epic"] }; rebuilds selected FTS document types through the shared search-index helpers and records maintenance metadata.optimize-search-indexexample input:{}; runs the explicit FTS optimize helper and records maintenance metadata.vacuum-planning-storeexample input:{ "checkpointWal": true }; checkpoints WAL when requested, runs SQLiteVACUUMoutside compaction, and reports before/after byte counts.list-planning-artifactsexample input:{ "includeSubmitted": false, "includeBoard": false, "limit": 50, "offset": 0 }; returns compact paginated planning artifacts (artifacts,plans,planSets,total,limit, andoffset) without rich board data. Plan artifacts include readiness plusreadinessSourceandreadinessFreshnessso callers can tell whether readiness came from the persisted cache or current Markdown. Flat session-plan metadata, canonical status/source disclosure, lifecycle rows, partial lifecycle reasons, and lifecycle timestamps (createdAt,updatedAt,readyAt,submittedAt, andlastBuildActivityAtwhen source data exists) come from SQLite; plan sets still come from the input adapter.plansandplanSetsare derived from the same returned page. Submitted flat plans and submitted plan sets are omitted unlessincludeSubmitted: true; legacy callers that intentionally need the old rich board field may passincludeBoard: truewithincludeArchive/epicfilters.show-session-planexample input:{ "session": "2026-06-05-add-import-preview" }; returns SQLite source refs, status source/source disclosure, lifecycle rows, partial lifecycle reasons when applicable, readiness,readinessSource,readinessFreshness, and the same lifecycle timestamp fields while loading the flat plan body from.eforge/session-plans/<session>.md.show-session-plan-setexample input:{ "planSetId": "import-workflow" }create-session-planexample input:{ "session": "2026-06-05-add-import-preview", "topic": "Add import preview", "planningType": "feature", "planningDepth": "focused", "profile": "excursion", "agentProfile": "frontend" }set-session-plan-sectionexample input:{ "session": "2026-06-05-add-import-preview", "dimension": "scope", "content": "Implement preview rendering and cancel handling." };dimension: "executive-summary"is also supported for editing the leading## Executive Summaryand is not a readiness dimension.skip-dimensionexample input:{ "session": "2026-06-05-add-import-preview", "dimension": "assumptions-and-validation", "reason": "No external assumptions need validation." }; records a skipped readiness dimension and syncs cached readiness for SQL-backed plan reads.check-session-plan-readinessexample input:{ "session": "2026-06-05-add-import-preview" }set-session-plan-readyexample input:{ "session": "2026-06-05-add-import-preview" }; returnskind: "not-ready"instead of mutating when required dimensions or acceptance criteria checks fail.handoff-session-planexample input:{ "session": "2026-06-05-add-import-preview" }; requires the plan to be ready andstatus: ready, then enqueues the session plan through the daemon build queue. Successful handoff records canonicalstatus: submitted,submittedAt, queue PRD correlation, and submitted lifecycle evidence in SQLite without rewriting the Markdown artifact status; enqueue failures leave the canonical plan ready and visible in default active artifact lists.resubmit-session-planexample input:{ "session": "2026-06-05-add-import-preview" }; requires a ready-bodied plan whose canonical status issubmittedorremovedand whose correlated queue/build evidence is terminal failed or removed, then enqueues the existing session-plan file again. Successful resubmit preserves the session id and source item/epic/recommendation refs, records fresh submitted lifecycle evidence, and supersedes stale current queue/build evidence.get-recommendationsreads the current SQLite recommendation run and returns the server-derived recommendation freshness view (missing,fresh, orstale), compatibility status/stale reason metadata, the private storage paths, any active recommendation refresh task, and additiverecommendationActionabilitymetadata. Actionability is computed on read (not stored in the recommendation model) from session plans, active planning tasks, queue/build/session/landing rows, lifecycle evidence, active build sessions, and open PR evidence. Entries retainstate: "actionable" | "non-actionable"for compatibility and adddisposition: "actionable" | "suppressed" | "de-actioned" | "relocated"; non-actionable entries include areasonCode/reasonMessage,lifecycleState, andassociatedLinks. Safe-parallel groups also includeactionableItemIdsandsuppressedItemIdsso mixed groups can still be planned for the actionable subset.put-recommendationsvalidates item/epic references and writes the private recommendation model, then records fresh status metadata for the current backlog fingerprint withlastRefreshedBy: "put-recommendations"; it does not create an accepted-analysis git baseline.get-roadmap-stateexample input:{ "includeLocalFocusContent": true }; reads private local-focus roadmap state, configured shared-source metadata, discovered conventional context such asdocs/roadmap.md, conflicts, assumptions, and truncation metadata.update-roadmap-stateexample input:{ "localFocusContent": "# Focus\n\nShip local roadmaps.\n", "expectedLocalFocusSha256": "..." }; writes only private local-focus roadmap content and/or shared-source configuration under extension storage. Shared-source paths are normalized before storage; disabled sources remain metadata only. Configured shared project files are read-only context and are not rewritten.analyze-all-backlogexample input:{}; starts or reuses an active daemon-owned backlog curation task without doing source assembly inside the short action request. The analysis audits open backlog items against current source; current source is the closure authority for shipped/superseded status, history is a navigation hint, ambiguous evidence should be resolved into actionable backlog updates, recommendations, or true needs-input rather than routine skips, and closed-status proposals require current-source citations. The task requests bothbacklogCurationDraftandrecommendationsoutput and does not enqueue builds. Its background curation source includes a bounded top-levelgitDeltaprojection (gitDelta.baseline.commit,gitDelta.baseline.time,gitDelta.baseline.source,gitDelta.currentHead,gitDelta.scannedCommitCount, scanned commits, scan caps, coverage, diagnostics, and deterministic affected item candidates) plus bounded git/PR shipped or superseded evidence alongside lifecycle evidence. Git-delta diagnostics includebaseline-missing,baseline-invalid-sidecar,baseline-unreachable,baseline-shallow,git-unavailable,git-command-failed,scan-cap-truncated, andpr-enrichment-unavailable; missing, invalid, unreachable, shallow, and no-git baseline states are fallback or unavailable coverage, not complete git-delta coverage. Previews expose server-provided audit coverage, caps, diagnostics, concurrency settings, per-item outcomes, current-source citations, historical navigation hints, evidence source, and confidence metadata. Drafts may include epic patches when justified from item-level findings, dependency state, roadmap context, or recommendation strategy. Optional PR enrichment throughghis fail-closed and not required. An unavailableghshould leave bounded git-only candidate evidence in place and recordpr-enrichment-unavailablediagnostics instead of treating GitHub as required. This is the primary workstation path for refreshing recommendations because normal confirmed curation applies the generated recommendation model against the post-curation backlog state; curation-only apply intentionally discards generated recommendations.refresh-recommendationsexample input:{}; starts or reuses a daemon-owned recommendation-only planning task for the current open backlog and roadmap-context fingerprint. This action remains available as a lower-level/API compatibility path and is allowed for roadmap refresh flows.promote-selectionexample input:{ "itemIds": ["add-import-preview"], "status": "active" }; also accepts{ "recommendationRef": "next-one" }or{ "epicId": "planning" }selectors.list-draft-unitsexample input:{ "limit": 50, "offset": 0 }; returns compact paginated draft-unit rows (units,total,limit, andoffset) with unit id, title, status, provenance, item ids/count, profile, promotion metadata, and timestamps. Verbose intent/detail reads stay behindget-draft-unit, e.g.{ "unitId": "unit_123" }.prepare-planner-contextexample input:{ "itemIds": ["add-import-preview"], "includeRoadmap": true }; returns JSON-safe selected/open backlog items, epics, recommendations, dependency/blocker context, roadmap context, and relevant lifecycle summaries.apply-planner-resultexample input:{ "recommendations": { "schemaVersion": 1, "activeWork": [], "readyCandidates": [{ "itemId": "add-import-preview" }], "recommendedNextSequence": [{ "itemId": "add-import-preview", "rationale": "Ready and high priority." }], "safeParallelizableGroups": [], "blockedChains": [], "rationaleAndAssumptions": ["Import preview is unblocked."] } }or{ "handoffDraft": { "selection": { "itemIds": ["add-import-preview"], "status": "active" } } }; applies only structured recommendation models and promotion selections.start-planning-agent-taskexample input:{ "userGoal": "Find the safest next import-preview work", "itemIds": ["add-import-preview"], "includeRoadmap": true }; prepares bounded planner context, then starts a daemon-ownedeforge-plan.planning-drafttask.userGoalis optional: when omitted, the AI-first flow derives the goal from the selection (itemIds,epicId, orrecommendationRef), e.g.{ "itemIds": ["add-import-preview"] },{ "epicId": "planning" }, or{ "recommendationRef": "next-one" }. Callers that plan an explicit ready subset from a recommendation lane may send{ "itemIds": ["add-import-preview"], "sourceRecommendationRef": "lane-one" }to keep provenance without usingrecommendationRefas the selector. Direct starts fail closed before daemon task creation when any selected item is already covered by an editable/submitted session plan, an active planning task, queued/building/build-session evidence, or open PR evidence; the invalid-input/user-action details include the same reason codes and associated links asget-recommendations.get-planning-agent-taskexample input:{ "taskId": "task_123" }; returns the daemon task record for polling status and result data.cancel-planning-agent-taskexample input:{ "taskId": "task_123" }; requests cancellation through the daemon-owned task API.list-planning-agent-tasksexample input:{ "limit": 50, "offset": 0 }; returns paginated compact workflow rows (tasks,total,returned,limit,offset, and continuation metadata) joined to daemon task status. Rows include compact entry/task summaries; Console callers include workflow entries and compact daemon task records by default, while agent callers can opt in withincludeEntry: trueandincludeTask: true. Boundedmetadata.activityLogentries remain available in compact task metadata for recent progress context. Heavy generated result payloads such as backlog curation drafts and recommendations are omitted from list rows withresultOmitted: true; callget-planning-agent-taskfor full task detail before rendering or applying a selected row.metadata.activityLogentries are{ "timestamp": "<ISO UTC>", "message": "<bounded text>" }, ordered oldest-to-newest with the newest entry last; timestamps are canonical ISO UTC with millisecond precision, messages are bounded, and only the newest 50 entries are retained.
retry-planning-agent-taskexample input:{ "taskId": "task_123" }; starts a new planning task reusing the preserved request context (selection, requested output sections, planning settings) of a prior task.redraft-planning-agent-taskexample input:{ "taskId": "task_123", "answers": ["Target the import-preview milestone."], "steering": "Keep the scope to the preview rail only." }; starts a linked redraft of a completed needs-input task, carrying the prior summary and clarification questions plus the user's answers or steering.apply-planning-agent-task-resultexample input:{ "taskId": "task_123", "applyRecommendations": true, "applySessionPlanDrafts": [{ "session": "2026-06-05-add-import-preview", "sections": ["scope", "acceptance-criteria"] }] }; fetches a completed planning-draft task and writes only the selected recommendation, handoff, or session-plan draft portions through the same safe mutation paths used by the non-agent planner actions. To apply a ready session-plan creation draft instead, passapplySessionPlanCreationDraft, e.g.{ "taskId": "task_123", "applySessionPlanCreationDraft": {} }, which writes the generated session plan throughapplySessionPlanCreationDraftand persists the tasksummaryas a leading## Executive Summarysection before readiness dimensions. The workstation automatically sends exactly{ "taskId": "task_123", "applySessionPlanCreationDraft": {} }once for eligible completed, available, unapplied, single-outputsessionPlanCreationDraftresults whose decision isready; failed, cancelled, unavailable, needs-input, recommendation refresh, backlog curation, handoff, recommendation, patch, revision, and ambiguous multi-output tasks remain visible for manual review. Automatic creation failures, including collision errors from the authoritative apply validation, are shown in Planning activity without retry loops, and the manual Create session plan action remains available. To apply a backlog curation draft, passapplyBacklogCurationDraftwith both literal confirmation flags, e.g.{ "taskId": "task_123", "applyBacklogCurationDraft": { "previewAcknowledged": true, "confirmApply": true } }; this selection cannot be combined with unrelated apply selections. Preview and apply use the same prospectiverecommendationProjection: draft status changes are applied in memory, closed targets are removed, draft-active/planned targets may be repositioned, and unknown, closed, empty, orwrong-lanereferences block normal curation apply. Users may explicitly apply curation only while discarding generated recommendations by adding"applyCurationOnly": true, e.g.{ "taskId": "task_123", "applyBacklogCurationDraft": { "previewAcknowledged": true, "confirmApply": true, "applyCurationOnly": true } }. Raw generated task output remains preserved as provenance. Normal curation apply writes onlyrecommendationProjection.effectiveRecommendations; curation-only apply omitsbacklogCuration.recommendationsand returnsbacklogCuration.recommendationsSkippedwith reasonapply-curation-onlyplus projection validation details.start-plan-revision-sessionexample input:{ "session": "2026-06-05-add-import-preview" }; creates or resumes a private revision thread for an existing flat session plan and returns plan/readiness details.list-plan-revision-sessionsexample input:{ "includePlan": true, "limit": 50, "offset": 0 }; lists persisted revision threads joined to owner-scoped daemon task records with paginated output. Annotation arrays are included only whenincludePlanis true.get-plan-revision-sessionexample input:{ "session": "2026-06-05-add-import-preview" }; returns one revision thread by session orthreadId, including persisted annotations.create-plan-revision-annotationexample input:{ "session": "2026-06-05-add-import-preview", "body": "Clarify the rollout constraint.", "target": { "kind": "selection", "dimension": "scope", "capturedText": "Existing scope text", "quoteContext": { "exact": "Existing scope text" } } }; persists a bounded semantic/quote-context annotation for a flat session-plan revision session. Durable targets require captured text and quote context; DOM-offset-only targets are rejected.update-plan-revision-annotation,delete-plan-revision-annotation,resolve-plan-revision-annotation, anddismiss-plan-revision-annotationmutate existing revision annotations and return the updated session projection with annotations.start-plan-revision-turnexample input:{ "session": "2026-06-05-add-import-preview", "message": "Tighten the scope section." }; starts one read-onlyeforge-plan.planning-drafttask withrequestedOutputSections: ["planRevisionTurn"]against the current flat plan fingerprint. Annotation-driven turns may also passannotationIds,includeOpenAnnotations, andsteering; selected/open annotations and steering are snapshotted onto the durable turn before the task starts. Selected annotation IDs must still be unresolved, and open-annotation-only requests require at least one unresolved annotation.retry-plan-revision-turnexample input:{ "session": "2026-06-05-add-import-preview", "turnId": "turn_123" }; retries a linked turn, or redrafts a completed needs-input turn whenanswersorsteeringare provided, preserving the parent annotation snapshot when present.cancel-plan-revision-turnexample input:{ "session": "2026-06-05-add-import-preview", "turnId": "turn_123", "reason": "Superseded." }; cancels the linked daemon task.apply-plan-revision-turnexample input:{ "session": "2026-06-05-add-import-preview", "turnId": "turn_123" }; writes all structured section patches from the completed revision turn through adapter-backed section mutations, applies any resolved open questions from the patch metadata to the plan'sopen_questions, resolves referenced open annotations from the turn snapshot, then refreshes readiness. The workstation calls this automatically as soon as a turn produces a patch, so there is no separate section-selection or apply-confirmation step. Apply is idempotent: re-applying an already-applied turn returnskind: "applied"without rewriting the plan or changing annotation resolution timestamps. Answer-only, mismatched, invalid-patch, needs-input, failed, or cancelled turns returnkind: "not-applicable"without writing session-plan sections or resolving annotations.
Integration command IDs are open-planning-entry, render-board, promote-item, and promote-selection. Deep-link IDs are planning-workstation, board, promote, and promote-selection; they dispatch open-planning-entry, render-board-markdown, promote-item, and promote-selection respectively. The planning entry action returns the eforge-plan workstation route /console/workstations/eforge-plan%3Aplanning-workstation. The input-source URI form is:
eforge://input/eforge-plan/<itemId>For example, enqueue eforge://input/eforge-plan/add-import-preview to compile that backlog item into build-source Markdown.
Direct agent backlog workflow
Agents should use direct compact backlog actions instead of browsing broad manifests, full board payloads, or editing Markdown files. Discover candidate work with search-items, inspect details with get-item and get-epic, create new ready backlog records with capture-item, and mutate visible private item metadata or body sections with update-item. Use search-planning-records when a query should cover backlog items, epics, flat session-plan summaries, and recommendation text in one bounded response. capture-item and update-item are compact writes without projection inputs. includeBody applies only to get-item and get-epic; search-items supports searchBody to widen the FTS match scope but does not return body text. Projection flags on reads let agents omit optional epics, sections, lifecycle rows, dependencies, dependents, and dependency id arrays when a smaller payload is enough: search-items can add includeEpics: true or set includeDependencies: false; search-planning-records can use fields to request only optional all-domain fields such as snippets or refs; get-item can set includeEpic, includeSections, includeLifecycleRows, includeDependencies, or includeDependents to false; get-epic can set includeItems, includeSections, or includeItemDependencies to false. If board summaries are used, list-board-compact supports includeEpics, includeLaneCounts, and includeDependencies projection flags.
For title or body-section edits, first call get-item and treat the returned bodySha256 as the optimistic lock token. Send that value back as expectedBodySha256 on update-item whenever changing title, sections, or sectionOperations; expectedBodySha256 is the primary lock token for those edits. Metadata-only updates such as status, priority, tags, dependsOn, or epic preserve body content and do not require expectedBodySha256; priority is a free-form non-empty single-line string rather than a fixed enum. If expectedBodySha256 has a stale lock mismatch, the action fails without mutating the item; retry only after a fresh get-item read and reapplying the intended change to the latest sections.
Canonical backlog body sections are Claim, Evidence, Acceptance Criteria, Recheck, and Notes. Use sections for canonical section replacement and sectionOperations for selected additional/unknown section edits. Example lock read and canonical section update:
{ "action": "get-item", "input": { "id": "add-import-preview", "includeSections": true } }{
"action": "update-item",
"input": {
"id": "add-import-preview",
"expectedBodySha256": "<bodySha256 from get-item>",
"sections": {
"Claim": "Add a preview step so users can inspect imports before enqueue."
}
}
}Example unknown-section append through sectionOperations:
{
"action": "update-item",
"input": {
"id": "add-import-preview",
"expectedBodySha256": "<bodySha256 from get-item>",
"sectionOperations": [
{ "action": "append", "heading": "Rollout Notes", "content": "Enable for internal import projects first." }
]
}
}Successful update-item responses include itemId, title, status, updatedAt, bodySha256, recordSha256, path, storage, changedFields, and changedSections. Successful body updates write canonical SQLite, recompute section rows, update Markdown mirrors, mark search documents dirty, and mark recommendation metadata stale. Direct Markdown edits to .backlog/items/<id>.md or .eforge/storage/extensions/eforge-plan/backlog/items/<id>.md are limited to explicit manual recovery/import scenarios; the normal mutation path is get-item followed by update-item.
Storage model
eforge-plan uses project-local storage only:
The private SQLite store lives at .eforge/storage/extensions/eforge-plan/eforge-plan-private.sqlite. It is the extension-owned normalized store for backlog, epic, recommendation, planning-task, session-plan correlation, lifecycle evidence, queue/build/session/landing links, import/maintenance metadata, and search-index records. Runtime eforge-plan mutations write canonical SQLite rows through storage repositories; legacy Markdown and JSON files remain compatibility/import inputs unless explicitly imported. Successful updates through update-item write canonical SQLite; body mutations also recompute section rows, update Markdown mirrors for compatibility, mark search documents dirty, and mark recommendation metadata stale. Callers should use eforge-plan actions instead of reading the SQLite file directly or editing mirror Markdown directly.
Search uses explicit SQLite FTS documents projected from canonical rows into search_documents and search_documents_fts. The index covers backlog item titles, ids, tags, claims/evidence/acceptance criteria, epics, flat session-plan summaries/provenance, and recommendation lane text. Normal search/read paths do not scan legacy Markdown, recommendation JSON sidecars, trace sidecars, planning-task sidecars, or session-plan Markdown bodies. Canonical writes and imports can mark search documents dirty; read actions report indexDirty and indexStatus (dirtyCount, dirty types, reason/timestamp, and last rebuild time when available) instead of silently rebuilding stale indexes.
.eforge/session-plans/<session>.mdstores promoted flat session-plan artifact bodies. SQLite stores queryable metadata, provenance, source refs, item/epic/recommendation joins, readiness summaries, lifecycle timestamps, lifecycle evidence and projection reasons, canonical session-plan status, submitted handoff/resubmit state, and queue/build/session/landing links; it does not store the Markdown body as canonical content..eforge/storage/extensions/eforge-plan/backlog/items/<id>.mdstores legacy/private backlog item Markdown used as compatibility, import input, and a mirror of canonical SQLite body updates; it is not the normal agent mutation target..eforge/storage/extensions/eforge-plan/backlog/epics/<id>.mdstores legacy/private epic Markdown used as compatibility and import input..backlog/items/<id>.mdand.backlog/epics/<id>.mdare legacy read-through and explicit import inputs for manual recovery or migration; they are not normal agent mutation targets..eforge/storage/extensions/eforge-plan/traces/<itemId>.jsonstores legacy lifecycle trace sidecars used as compatibility/import input; runtime lifecycle correlation is recorded in SQLite lifecycle, queue/build, session, and landing rows..eforge/storage/extensions/eforge-plan/recommendations/current.jsonand.eforge/storage/extensions/eforge-plan/recommendations/status.jsonare legacy recommendation compatibility/import files. Runtime recommendation model, freshness, lane/item, and current-run state are stored in SQLite..eforge/storage/extensions/eforge-plan/analysis-baseline/current.jsonstores the schema-versioned accepted-analysis baseline when one has been recorded after a successful accepted backlog-curation apply or preserved recommendation-refresh apply with a source fingerprint. The sidecar recordsacceptedAt,taskId,passKindvalues such asbacklog-curationorrecommendation-refresh,sourceFingerprint,git.headCommit,git.headCommittedAt, coverage (complete,fallback, orunavailable), and diagnostics, and is used by analyze-all source assembly to decide whether git-delta coverage is complete, fallback, or unavailable. Manualput-recommendationswrites update recommendation freshness only and do not create an accepted-analysis git baseline. Missing, invalid, unreachable, shallow, or no-git baseline states are loaded as diagnostics and produce fallback or unavailable coverage labels, not complete git-delta coverage. Baseline metadata is not encoded into backlog item or epic bodies, recommendation model JSON, or legacy.backlog/recommendations.json..eforge/storage/extensions/eforge-plan/backlog-curation-sources/<sourceFingerprint>.jsonstores server-generated backlog curation preview metadata for a curation source fingerprint, such asitemAuditConcurrency,gitDelta, and optionalfullImplementationAuditcoverage, caps, concurrency settings, diagnostics, per-item outcomes, current-source citations, historical navigation hints, and evidence summaries used by the workstation preview..eforge/storage/extensions/eforge-plan/roadmaps/local-focus.mdstores the editable developer-local focus roadmap used as local steering context..eforge/storage/extensions/eforge-plan/roadmaps/config.jsonstores configured shared roadmap source metadata with normalized project-relative paths. Shared project roadmap files remain read-only context; disabled entries remain metadata only and conventional files such asdocs/roadmap.mdmay be discovered as non-canonical shared context when not enabled as configured sources.- SQLite planning-task rows store the extension-owned durable planning workflow index used by the Planning activity task monitor for AI planning task discovery, polling, retry, redraft context, recommendation refresh task discovery, backlog curation task discovery, and applied curation markers across reloads. The legacy
.eforge/storage/extensions/eforge-plan/planning-tasks/index.jsonpath is no longer used by runtime workflows. .eforge/storage/extensions/eforge-plan/plan-revisions/index.jsonstores private revision-session threads for existing flat session plans, including annotations, turn/task links, annotation snapshots, base fingerprints, section hashes, retry/redraft linkage, and applied section metadata.
Retention and compaction
Store maintenance is explicit local extension behavior. compact-planning-store defaults to a dry run, reports bounded candidate counts and samples, and writes no archives, dirty markers, rows, or store_maintenance_runs records unless callers pass dryRun: false. Apply-mode compaction is limited to retention-eligible high-volume data: raw lifecycle event payloads, terminal planning-task raw request/result payloads, and non-current superseded recommendation runs.
Compaction preserves canonical planning rows and explainability. Backlog items, epics, dependencies, session plans, session-plan joins, queue/build/session/landing links, current lifecycle evidence, current recommendation runs, current recommendation lanes/items, recommendation actionability projections, associated links, and duplicate coverage policy are protected. Lifecycle evidence summaries are refreshed into lifecycle_evidence.retained_summary_json before raw lifecycle payloads are cleared. Planning task rows retain task identity, purpose, status snapshot, selection summaries, compact result summaries, parent links, and applied timestamps when raw request/result payloads are cleared.
When archive: true, affected rows or payloads are written as JSONL under .eforge/storage/extensions/eforge-plan/archives/maintenance/<runId>/ before mutation. Archive paths and row counts are included in the report; raw archived payloads are not returned by action output and are not read by normal projections. Maintenance action outputs omit raw payload_json, raw_request_json, raw_result_json, raw_model_json, verbose_report_json, and details_json strings. Superseded recommendation pruning deletes only eligible non-current runs after keep-latest protection and can rebuild recommendation search documents through the shared FTS helpers. FTS maintenance through rebuild/optimize and SQLite VACUUM are separate explicit maintenance actions; search reads continue to report dirty-index state instead of hiding stale data.
The extension never reads or writes legacy .backlog/recommendations.json; recommendation state lives only in private extension storage. Backlog records, lifecycle evidence, recommendation records, backlog curation source preview sidecars, planning task workflow records, and plan revision session records are private extension storage; session plans are public build inputs under .eforge/session-plans/.
Backlog item and epic rows preserve the durable human-authored planning record, explicit backlog_items.user_status, frontmatter-derived metadata, tags, sections, dependencies, and epic refs. Lifecycle/actionability evidence is stored separately from user-authored status so planned, submitted, queued, building, PR-open, merged, shipped, failed, and partial/current-link states can be explained without overwriting the user's visible status. Confirmed merge or auto-merge evidence may still set the item user_status to shipped to preserve existing user-facing behavior. Legacy .backlog item and epic files remain readable compatibility input when no private record has the same ID, and private records take precedence over same-ID legacy records. Runtime capture, update, upsert, promotion, recommendation, planning-task, session-plan, and lifecycle mutations write canonical SQLite rows; legacy item and epic files are not deleted or rewritten by default. The existing safe-id and path-containment checks apply to private storage reads/writes and legacy compatibility/import reads.
Recommendation freshness is derived by comparing stored recommendation/source fingerprint data against the current or prospective source fingerprint of open backlog items, epics, dependency/blocker context, roadmap context, and lifecycle summaries for current open backlog items. Recommendation actionability is a separate read-time projection and is never persisted into the recommendation model: reason codes include planned-session-plan, submitted-session-plan, active-planning-task, queued-build, running-build, active-build-session, open-pr, merged-result, shipped-result, failed-result, and partial-plan; compatibility aliases such as queued-trace map to the SQL-backed vocabulary at action boundaries. Each suppressed, de-actioned, or relocated item includes associated session/task/queue/build/PR links for inspection. Lifecycle summaries preserve historical evidence rows, but their active fields are projected only from current editable/submitted plan evidence, active planning tasks, live queue/run/build evidence, current PR-open/landing evidence, failed/partial durable evidence, or explicit fallback backlog status rather than from durable history alone:
| State | Meaning |
| --- | --- |
| missing | No private current recommendation run exists, and no stale status metadata has been recorded. |
| fresh | A current recommendation run exists and status metadata matches the current recommendation source fingerprint with no stale reasons. |
| stale | Stale metadata exists, or a current recommendation run exists but its status metadata is missing/invalid, records stale reasons, or its last-applied fingerprint differs from the current source fingerprint. |
Deterministic git-delta matching considers item ids, titles, slugs, changed paths, branch hints, PR numbers/titles/bodies/files, merge subjects, and bounded excerpts. Source-first closed-status patches require current-source preview citations and use exact evidence prefixes Shipped evidence: current source — or Superseded evidence: current source — ; git/PR/lifecycle/session evidence is navigation-only. Historical evidence prefixes such as Shipped evidence: lifecycle trace — , Shipped evidence: inferred from git/PR history — , Superseded evidence: lifecycle trace — , and Superseded evidence: inferred from git/PR history — may appear as navigation hints but are not closed-status authority. Ambiguous closure evidence is not enough for a closed-status patch; source-first curation should resolve it into open backlog updates, recommendations, or true needs-input where possible, with exact needs-input prefixes Ambiguous shipped candidate: needs input — and Ambiguous superseded candidate: needs input — when a product decision remains required.
The freshness metadata and action outputs expose freshAt, staleSince, lastRefreshedBy, and structured reasons entries. Lifecycle stale reasons include eventType, affected itemIds, correlationKind (single, multi, or bootstrapped), timestamp, and a bounded summary; compatibility fields such as code, message, refs, sourceFingerprint, lastAppliedSourceFingerprint, state, and staleReasons remain available for existing consumers. Persisted reason history is deduplicated for exact repeats and trimmed to the latest 20 entries. A correlated lifecycle event can therefore make recommendations stale before a current recommendation model exists; in that case get-recommendations returns stale freshness with recommendations: null instead of creating or backfilling a model.
Lifecycle hooks are invalidators only. After a lifecycle event has been correlated to one or more backlog items and SQLite lifecycle/status rows have been updated, the hook records structured stale metadata and invalidates recommendation freshness. Uncorrelated or ambiguous lifecycle events do not dirty recommendation freshness, and lifecycle hooks never start daemon-owned agent tasks or host-specific planning commands. Freshness is restored only through explicit recommendation apply or refresh paths: confirmed applyBacklogCurationDraft output from the primary analyze-all-backlog flow when it includes generated recommendations, refresh-recommendations as a lower-level recommendation-only path, apply-planner-result, apply-planning-agent-task-result, or put-recommendations.
Recommendation model writes validate references before changing storage: put-recommendations, apply-planner-result, apply-planning-agent-task-result, and confirmed applyBacklogCurationDraft output reject unknown itemId/epicIds references, closed item/epic recommendation references, and empty safe-parallelizable group itemIds. Generated recommendations from a backlog curation draft are projected against the prospective post-curation backlog state before preview validation and apply validation: proposed item/epic status changes are applied in memory, closed targets are removed, draft-active targets are moved to activeWork, draft-planned targets can move from activeWork to readyCandidates, and curation-specific placement validation reports wrong-lane issues. Backlog curation task list entries can include preview-time generated recommendation validation and recommendationProjection metadata so the workstation can show effectiveRecommendations, removed/repositioned targets, and invalid generated recommendation references before apply; backend apply repeats validation and remains authoritative. Raw generated task output remains preserved as provenance; the effective prospective projection is what preview displays and normal apply writes. Validation, reference, and curation precondition failures leave the existing recommendation run, freshness metadata, and accepted-analysis baseline unchanged; canonical writes are transactional and do not partially update related rows. Successful writes update the current SQLite recommendation run, then derive freshness from the applied source fingerprint. When curation output includes generated recommendations, confirmed applyBacklogCurationDraft writes private backlog rows first, writes only the effective projected recommendation model after validation succeeds, records freshness against the post-apply/post-curation backlog fingerprint with lastRefreshedBy: "apply-backlog-curation-draft", and records an accepted-analysis baseline when the draft has a source fingerprint. Curation-only apply writes backlog changes, skips recommendation writes, returns projection metadata, records the accepted backlog-curation baseline when the draft has a source fingerprint, and leaves discarded generated recommendations unfresh rather than labeling them fresh. A preserved recommendation-refresh workflow entry applied through apply-planning-agent-task-result records an accepted-analysis baseline when the entry has a source fingerprint; direct apply-planner-result and put-recommendations do not. If the recommendation fingerprint has drifted by the time the model is applied, apply-planning-agent-task-result can return stale status with a source-fingerprint-drift reason instead of fresh. Fresh status records lastRefreshedBy as put-recommendations, apply-planner-result, apply-planning-agent-task-result, or apply-backlog-curation-draft, depending on the action that applied the model.
Kanban semantics
The board is derived from backlog status, dependency state, and lifecycle evidence. Lanes are not separate storage locations.
| Lane | Meaning |
| --- | --- |
| inbox | True candidate items with no dependency, plan, task, queue, build, PR, landing, lifecycle, failed, partial, or shipped evidence. |
| ready | Planned items or editable nonterminal session-plan items without unresolved blockers and without higher-priority active/terminal evidence. |
| blocked | Items with unresolved dependencies, failed terminal evidence with no later nonfailed superseding evidence, or partial aggregate evidence that requires intervention. |
| in-progress | Active items or items with nonterminal submitted, queued, running/building, active build-session, or PR-open evidence. |
| done | Items with shipped/landed/merged evidence or explicit shipped status. |
| archive | Stale or superseded items when no higher-priority current evidence supersedes the explicit status. |
Statuses are candidate, planned, active, shipped, stale, and superseded. Promotion never marks an item shipped; it marks the item active by default, or leaves it planned when requested by the action input.
Actions
The extension registers backlog, board, search, recommendation, roadmap, planner-orchestration, plan-revision, store-maintenance, agent runtime profile-option, and planning-workstation actions. Agent-facing compact and paginated actions declare output profiles (get-item, get-store-status, compact-planning-store, rebuild-search-index, optimize-search-index, and vacuum-planning-store as agent-compact; get-epic, search-items, search-planning-records, list-board-compact, list-draft-units, list-planning-artifacts, list-planning-agent-tasks, and list-plan-revision-sessions as agent-paginated), list-agent-runtime-profiles declares ui-rich, direct backlog writes (capture-item and update-item) declare agent-compact, render-board-markdown declares markdown, and the compatibility full-board payload declares debug-rich.
| Action | Purpose | Side effects |
| --- | --- | --- |
| list-board | Compatibility/debug read that returns SQL-derived epics, items, lanes, blocked reasons, recommendation status (including missing/fresh/stale), optional recommendation summary, lifecycle summaries, and lifecycle projections as JSON-safe data. Kanban cards include canonical linkRows, failureEvidence, and lifecycleState; the board also exposes aggregate lifecycleLinks and epicProgress. The workstation does not use this rich action on its hot path. | local-read |
| list-board-compact | Return bounded SQL-derived compact item summaries, lane counts, total/open/closed counts, pagination metadata, effective lifecycle, user status, reason codes, backend planEligible/eligibility reason fields, compact evidence links, and epic counts. It is open-first by default: closed done/archive cards are omitted from items until callers explicitly request a closed lane with includeClosed (and includeArchive for archive reads). Projection flags can omit epics, lane/count aggregates, and dependency id arrays. | local-read |
| get-item | Return one backlog item detail with explicit user status, SQL-derived lifecycle/reason codes, backend planEligible/eligibility reason fields, associated plan/build links, Markdown sections, lifecycle rows, compact dependency/dependent summaries, and bodySha256/recordSha256 lock fields for body-safe update-item calls. Raw body output is opt-in through includeBody; projection flags can omit the epic, sections, lifecycle rows, dependencies, or dependents. | local-read |
| get-epic | Return one backlog epic detail with Markdown sections, SQLite item/open-item counts, and paginated compact item summaries. Raw body output is opt-in through includeBody; projection flags can omit sections, items, or item dependency ids. | local-read |
| search-items | Search compact item summaries through the SQL/FTS index by text, epic, status, effective lane, or tags with default limit: 20, max limit: 100, and offset pagination. Body-summary search is opt-in through searchBody; projection flags can add compact epics for matches or omit dependency id arrays. Text-query responses may add rank, snippets, matched fields, counts, pagination metadata, and dirty-index status while omitting raw backlog body text. Blank queries behave as filtered compact listings. | local-read |
| search-planning-records | Search the all-domain SQL/FTS index across backlog items, epics, flat session-plan summaries, and recommendation lanes. Returns compact records with counts by type, offset pagination, optional selected fields (rank, snippet, refs, updatedAt), and dirty-index status; it does not return raw recommendation JSON, session-plan Markdown bodies, lifecycle event payloads, or backlog bodies. | local-read |
| get-store-status | Report private SQLite store initialization, expected path, DB/WAL/SHM byte sizes, schema version, table counts, retention eligibility counts, search-index status, and recent maintenance runs. Missing stores return initialized: false without creating storage directories. | local-read |
| compact-planning-store | Dry-run by default; in apply mode, explicitly compacts only retention-eligible raw lifecycle payloads, terminal planning-task raw payloads, and superseded non-current recommendation runs while preserving protected canonical rows and bounded action output. Optional JSONL archives are written under the maintenance archive directory before mutation. | local-write |
| rebuild-search-index | Rebuild selected all-domain FTS document types through the shared search-index helpers, clear matching dirty markers, and record observable maintenance metadata. | local-write |
| optimize-search-index | Run the explicit FTS optimize helper and record a maintenance run. | local-write |
| vacuum-planning-store | Optionally checkpoint WAL, run SQLite VACUUM as a separate explicit maintenance operation, and report before/after byte counts. | local-write |
| render-board-markdown | Return { markdown } for host or Console display, including visible recommendation freshness notes when recommendations are fresh or stale. | local-read |
| list-agent-runtime-profiles | Return kernel-owned agent runtime profile options through ctx.profiles.list, preserving the shared client profile-list response fields such as name, scope, harness, active source, shadowing, path, and metadata. It is a read-only adapter and does not scan profile directories or own profile-list semantics. | local-read |
| capture-item | Create a visible, session-plan-ready backlog item in private eforge-plan storage from title, claim, evidence, tags, priority, epic, dependencies, and required acceptance criteria. Rejects exploration/revisit/research-style captures. | local-write |
| upsert-epic | Create or update a visible backlog epic in private eforge-plan storage without duplicating item membership lists. | local-write |
| update-item | Update visible item title, canonical sections (Claim, Evidence, Acceptance Criteria, Recheck, Notes), selected additional sections, status, free-form priority, tags, evidence/recheck notes, dependencies, and epic link in private storage. Metadata-only updates preserve body content without a lock; title/section updates require expectedBodySha256 from get-item. | local-write |
| promote-item | Reject duplicate nonterminal coverage, write a session plan, record planned lifecycle evidence, and set item status to active or planned through canonical SQLite writes. | local-write |
| promote-selection | Promote selected visible item IDs, a recommendation ref, or an epic into one session plan using the same build-source synthesis path, duplicate coverage guard, and canonical SQLite writes. | local-write |
| get-recommendations | Read the current SQLite recommendation run, derive the server freshness view from SQLite status metadata, and return summary, compatibility status, freshness view data, additive read-time recommendationActionability, plus any active refresh task. Actionability includes per-entry compatibility state, disposition, reason/message, lifecycle state, associated links, and safe-parallel actionableItemIds/suppressedItemIds; it is not written into recommendation storage. | local-read |
| put-recommendations | Validate recommendation item/epic references and write the current private recommendation model, then update freshness metadata for the current source fingerprint with lastRefreshedBy: "put-recommendations"; it does not create an accepted-analysis git baseline. | local-write |
| get-roadmap-state | Read private local-focus roadmap state, configured shared-source metadata, discovered conventional context, conflicts, assumptions, truncation metadata, and storage paths. | local-read |
| update-roadmap-state | Update private local-focus roadmap content and/or configured shared-source metadata. It validates configured paths stay within the project, stores normalized project-relative paths, ignores disabled sources during projection, and never writes the configured shared project files themselves. | local-read, local-write |
| analyze-all-backlog | Start or reuse an active daemon-owned backlog curation planning task for input {}. It audits open items against current source, treats current source as the closure authority for shipped/superseded status, treats git/PR/lifecycle/session history as navigation hints, resolves ambiguous evidence into actionable backlog updates, recommendations, or true needs-input rather than routine skips, and requires current-source citations for closure. It records a durable workflow entry with purpose backlog-curation, requests backlogCurationDraft plus recommendations, and defers all-open-backlog source assembly to the background task so the workstation action returns quickly. Normal confirmed apply writes curation changes first, then writes the effective prospective recommendation projection and refreshes recommendations from the post-curation backlog state; curation-only apply discards generated recommendations when explicitly requested. Successful accepted curation apply records the private analysis baseline when a source fingerprint is available. | local-read, local-write, daemon-state, network |
| refresh-recommendations | Start or reuse a daemon-owned recommendation-only planning task for the current source fingerprint. It records a durable workflow entry with purpose recommendation-refresh and does not apply generated output automatically. This lower-level action remains registered and is allowed for roadmap refresh flows. | local-read, local-write, daemon-state |
| prepare-planner-context | Prepare JSON-safe backlog, epic, recommendation, dependency/blocker, roadmap context, and relevant lifecycle summaries for external AI planning orchestration. | local-read |
| apply-planner-result | Apply validated structured planner recommendation updates and/or handoff drafts through private recommendation storage and promote-selection. | local-write |
| start-planning-agent-task | Prepare planner context, reject duplicate selected work using the same server actionability evidence as get-recommendations, then ask the daemon-owned agent task service to run one eforge-plan.planning-draft task for an explicit user goal or a goal derived from the backlog selection (itemIds, epicId, or recommendationRef). Duplicate planned/in-process selections return invalid input before agentTasks.start() and include evidence links in the user-action details. | local-read, local-write, daemon-state |
| get-planning-agent-task | Return the daemon task record for one planning task id. | local-read |
| cancel-planning-agent-task | Delegate cancellation of one planning task to the daemon-owned task service. | local-write |
| list-planning-agent-tasks | Project the durable planning task workflow index as compact agent-paginated rows with limit/offset, compact entry/task summaries, bounded recent activity metadata, and owner-scoped daemon task status for discovery, polling, retry, and redraft across reloads. Console callers include workflow entries and compact task records by default; other agents can opt in with includeEntry/includeTask. Heavy generated result payloads are omitted from list rows with resultOmitted: true; fetch full detail through get-planning-agent-task. Backlog curation previews are fetched separately through preview-backlog-curation-task. | local-read |
| retry-planning-agent-task | Start a new planning task reusing the preserved request context of a prior task. | local-read, local-write, daemon-state |
| redraft-planning-agent-task | Start a linked redraft of a completed needs-input task, carrying prior summary/questions plus the user's clarification answers or steering. | local-read, local-write, daemon-state |
| apply-planning-agent-task-result | Apply selected output from a completed planning-draft task through validated recommendation storage, handoff promotion helpers, session-plan section adapters, applySessionPlanCreationDraft for ready creation drafts (persisting the task summary as ## Executive Summary), or applyBacklogCurationDraft for confirmed backlog curation drafts; applyBacklogCurationDraft.applyCurationOnly applies valid curation while discarding generated recommendations. | local-write |
| start-plan-revision-session | Create or resume a private revision thread for an existing flat session plan and return its plan/readiness projection. | local-read, local-write |
| list-plan-revision-sessions | List private revision threads as agent-paginated rows joined to owner-scoped daemon task records, optionally including current flat plan detail. | local-read |
| get-plan-revision-session | Return one private revision thread by target session or thread id, joined to daemon task records and including annotations. | local-read |
| create-plan-revision-annotation | Persist a bounded semantic/quote-context annotation for an existing flat session-plan revision session. | local-read, local-write |
| update-plan-revision-annotation | Update an annotation body and/or semantic target for an existing flat session-plan revision session. | local-read, local-write |
| delete-plan-revision-annotation | Delete one persisted plan revision annotation. | local-read, local-write |
| resolve-plan-revision-annotation | Manually mark one plan revision annotation resolved. | local-read, local-write |
| dismiss-plan-revision-annotation | Mark one plan revision annotation dismissed so it is no longer treated as open context. | local-read, local-write |
| start-plan-revision-turn | Start one read-only eforge-plan.planning-draft task for a user revision message or annotation-driven request, requesting only planRevisionTurn output and recording the base plan fingerprint plus any annotation snapshot. | local-read, local-write, daemon-state |
| retry-plan-revision-turn | Re
