@papi-ai/adapter-md 0.1.0-alpha → 0.2.0
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/LICENSE +98 -0
- package/dist/index.d.ts +1127 -194
- package/dist/index.js +577 -457
- package/package.json +9 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
|
-
import { TaskStatus as TaskStatus$1, TaskPriority as TaskPriority$1, EffortSize as EffortSize$1,
|
|
1
|
+
import { TaskStatus as TaskStatus$1, TaskPriority as TaskPriority$1, EffortSize as EffortSize$1, TaskComplexity as TaskComplexity$1, TaskType as TaskType$1, ReviewStage as ReviewStage$1, ReviewVerdict as ReviewVerdict$1, isValidStatus as isValidStatus$1, isValidTransition as isValidTransition$1, validateTransition as validateTransition$1 } from '@papi-ai/shared';
|
|
2
2
|
|
|
3
3
|
/** Valid phase statuses in the product brief. */
|
|
4
4
|
type PhaseStatus = 'Not Started' | 'In Progress' | 'Done' | 'Deferred';
|
|
5
|
-
/** Feature lifecycle status. */
|
|
6
|
-
type FeatureStatus = 'Not Started' | 'In Progress' | 'Done' | 'Deferred';
|
|
7
|
-
/** A workstream or capability being built. Replaces Phase as the primary planning construct (AD-23). */
|
|
8
|
-
interface Feature {
|
|
9
|
-
id: string;
|
|
10
|
-
displayId: string;
|
|
11
|
-
slug: string;
|
|
12
|
-
name: string;
|
|
13
|
-
description: string;
|
|
14
|
-
status: FeatureStatus;
|
|
15
|
-
roadmapPosition: number;
|
|
16
|
-
createdAt: string;
|
|
17
|
-
completedAt?: string;
|
|
18
|
-
commitDate?: string;
|
|
19
|
-
createdSprint: number;
|
|
20
|
-
completedSprint?: number;
|
|
21
|
-
}
|
|
22
5
|
/** A development phase defined in the product brief. */
|
|
23
6
|
interface Phase {
|
|
24
7
|
id: string;
|
|
@@ -27,27 +10,71 @@ interface Phase {
|
|
|
27
10
|
description: string;
|
|
28
11
|
status: PhaseStatus;
|
|
29
12
|
order: number;
|
|
13
|
+
/** The stage this phase belongs to (AD-14 hierarchy). */
|
|
14
|
+
stageId?: string;
|
|
30
15
|
}
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Horizon status in the project hierarchy (AD-14). Shares the PhaseStatus
|
|
18
|
+
* vocabulary — the DB constraint + all live rows use 'Not Started'/'In Progress'/
|
|
19
|
+
* 'Done'/'Deferred', NOT the legacy 'active'/'completed'/'deferred' (task-2136).
|
|
20
|
+
*/
|
|
21
|
+
type HorizonStatus = PhaseStatus;
|
|
22
|
+
/** A horizon — the highest level of the project hierarchy (AD-14: Horizon → Stage → Phase → Task). */
|
|
23
|
+
interface Horizon {
|
|
24
|
+
id: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
label: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
status: HorizonStatus;
|
|
29
|
+
sortOrder: number;
|
|
30
|
+
projectId: string;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
updatedAt: string;
|
|
33
|
+
}
|
|
34
|
+
/** Stage status in the project hierarchy (AD-14). Shares the PhaseStatus vocabulary (task-2136 — see HorizonStatus). */
|
|
35
|
+
type StageStatus = PhaseStatus;
|
|
36
|
+
/** A stage — sits between Horizon and Phase in the hierarchy (AD-14: Horizon → Stage → Phase → Task). */
|
|
37
|
+
interface Stage {
|
|
38
|
+
id: string;
|
|
39
|
+
slug: string;
|
|
40
|
+
label: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
status: StageStatus;
|
|
43
|
+
sortOrder: number;
|
|
44
|
+
horizonId: string;
|
|
45
|
+
projectId: string;
|
|
46
|
+
exitCriteria?: string[];
|
|
47
|
+
createdAt: string;
|
|
48
|
+
updatedAt: string;
|
|
49
|
+
}
|
|
50
|
+
/** Cycle lifecycle status (renamed from CycleStatus per AD-14). */
|
|
51
|
+
type CycleStatus = 'planning' | 'active' | 'complete';
|
|
52
|
+
/** Per-section SHA-256 hashes for context diff optimisation between cycles. */
|
|
35
53
|
interface ContextHashes {
|
|
36
54
|
productBrief?: string;
|
|
37
55
|
activeDecisions?: string;
|
|
38
56
|
reviews?: string;
|
|
39
57
|
[key: string]: string | undefined;
|
|
40
58
|
}
|
|
41
|
-
|
|
59
|
+
/** A cycle entity — the methodology loop (renamed from Cycle per AD-14). */
|
|
60
|
+
interface Cycle {
|
|
42
61
|
id: string;
|
|
43
62
|
number: number;
|
|
44
|
-
status:
|
|
63
|
+
status: CycleStatus;
|
|
45
64
|
startDate: string;
|
|
46
65
|
endDate?: string;
|
|
47
66
|
goals: string[];
|
|
48
67
|
boardHealth: string;
|
|
49
68
|
taskIds: string[];
|
|
50
69
|
contextHashes?: ContextHashes;
|
|
70
|
+
/**
|
|
71
|
+
* task-2071 (C293, MU-3): the member who owns this cycle. Each member runs
|
|
72
|
+
* their own cycle into the shared repo; the DB enforces one active cycle per
|
|
73
|
+
* (project_id, user_id). createCycle stamps this from the calling identity;
|
|
74
|
+
* the C293 migration backfilled existing active cycles to the project owner so
|
|
75
|
+
* solo/owner-operated projects are unchanged. NULL = legacy/unowned.
|
|
76
|
+
*/
|
|
77
|
+
userId?: string;
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
type TaskStatus = TaskStatus$1;
|
|
@@ -63,7 +90,7 @@ declare const validateTransition: typeof validateTransition$1;
|
|
|
63
90
|
declare const isValidStatus: typeof isValidStatus$1;
|
|
64
91
|
/**
|
|
65
92
|
* Context tiers control which tasks the planner sees:
|
|
66
|
-
* Tier 1 (
|
|
93
|
+
* Tier 1 (Cycle-eligible): Bug, Task — fed to planner for scheduling
|
|
67
94
|
* Tier 2 (Plannable): Research — scheduled but output is knowledge not code
|
|
68
95
|
* Tier 3 (Pre-triage): Idea, Feedback — invisible to planner until promoted
|
|
69
96
|
*/
|
|
@@ -78,22 +105,41 @@ type Confidence = 'HIGH' | 'MEDIUM' | 'LOW';
|
|
|
78
105
|
type DecisionEventType = 'created' | 'confidence_changed' | 'modified' | 'superseded' | 'validated' | 'invalidated' | 'scored';
|
|
79
106
|
/** Source of a decision event. */
|
|
80
107
|
type DecisionEventSource = 'strategy_review' | 'build_complete' | 'strategy_change' | 'manual';
|
|
108
|
+
/**
|
|
109
|
+
* Structured before->after movement of a single metric, captured on a
|
|
110
|
+
* deliberate decision event (task-2168). Consumes cycle_metrics_snapshots.
|
|
111
|
+
*/
|
|
112
|
+
interface MetricDelta {
|
|
113
|
+
/** Metric name — ideally a real metric from cycle_metrics_snapshots. */
|
|
114
|
+
metric: string;
|
|
115
|
+
before?: number;
|
|
116
|
+
after?: number;
|
|
117
|
+
delta?: number;
|
|
118
|
+
}
|
|
81
119
|
/** An append-only event in a decision's lifecycle. */
|
|
82
120
|
interface DecisionEvent {
|
|
83
121
|
id: string;
|
|
84
122
|
decisionId: string;
|
|
85
123
|
eventType: DecisionEventType;
|
|
86
|
-
|
|
124
|
+
cycle: number;
|
|
87
125
|
source: DecisionEventSource;
|
|
88
126
|
sourceRef?: string;
|
|
89
127
|
detail?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Pointer to supporting evidence (doc path / build-report id / metric name).
|
|
130
|
+
* Captured on deliberate events (validated / invalidated / modified) at
|
|
131
|
+
* strategy_review / strategy_change. Optional — writer fails open (task-2168).
|
|
132
|
+
*/
|
|
133
|
+
evidenceRef?: string;
|
|
134
|
+
/** Which metric moved + before->after for this decision (task-2168). */
|
|
135
|
+
metricDelta?: MetricDelta | null;
|
|
90
136
|
createdAt: string;
|
|
91
137
|
}
|
|
92
138
|
/** Dimensional scores for an Active Decision at a point in time. */
|
|
93
139
|
interface DecisionScore {
|
|
94
140
|
id: string;
|
|
95
141
|
decisionId: string;
|
|
96
|
-
|
|
142
|
+
cycle: number;
|
|
97
143
|
effort: number;
|
|
98
144
|
risk: number;
|
|
99
145
|
reversibility: number;
|
|
@@ -103,15 +149,17 @@ interface DecisionScore {
|
|
|
103
149
|
rationale?: string;
|
|
104
150
|
createdAt: string;
|
|
105
151
|
}
|
|
106
|
-
/**
|
|
107
|
-
interface
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
152
|
+
/** Cycle health metadata from PLANNING_LOG.md header. */
|
|
153
|
+
interface CycleHealth {
|
|
154
|
+
totalCycles: number;
|
|
155
|
+
latestCycleStatus?: string;
|
|
156
|
+
cyclesSinceLastStrategyReview: number;
|
|
111
157
|
strategyReviewDue: string;
|
|
112
158
|
boardHealth: string;
|
|
113
159
|
strategicDirection: string;
|
|
114
160
|
lastFullMode: number;
|
|
161
|
+
/** Number of auth.users rows with no matching user_profiles row. Non-zero = trigger gap. pg adapter only. */
|
|
162
|
+
orphanAuthUsers?: number;
|
|
115
163
|
}
|
|
116
164
|
/** An Active Decision (AD) tracked in the planning log. */
|
|
117
165
|
interface ActiveDecision {
|
|
@@ -122,46 +170,128 @@ interface ActiveDecision {
|
|
|
122
170
|
confidence: Confidence;
|
|
123
171
|
superseded: boolean;
|
|
124
172
|
supersededBy?: string;
|
|
125
|
-
|
|
126
|
-
|
|
173
|
+
createdCycle?: number;
|
|
174
|
+
modifiedCycle?: number;
|
|
127
175
|
body: string;
|
|
176
|
+
outcome?: 'pending' | 'confirmed' | 'validated' | 'revised' | 'resolved' | 'abandoned' | 'superseded';
|
|
177
|
+
revisionCount?: number;
|
|
128
178
|
}
|
|
129
|
-
/** A single
|
|
130
|
-
interface
|
|
179
|
+
/** A single cycle entry in the planning log. */
|
|
180
|
+
interface CycleLogEntry {
|
|
131
181
|
uuid: string;
|
|
132
|
-
|
|
182
|
+
cycleNumber: number;
|
|
133
183
|
title: string;
|
|
134
184
|
content: string;
|
|
135
185
|
carryForward?: string;
|
|
136
186
|
notes?: string;
|
|
187
|
+
/** Number of tasks in this cycle (structured — no prose parsing needed). */
|
|
188
|
+
taskCount?: number;
|
|
189
|
+
/** Total effort points for this cycle (XS=1, S=2, M=3, L=5, XL=8). */
|
|
190
|
+
effortPoints?: number;
|
|
191
|
+
/**
|
|
192
|
+
* ISO timestamp for when this cycle log entry was last written (plan or
|
|
193
|
+
* release). Optional — historical entries may not have it. Surfaced from
|
|
194
|
+
* planning_log_entries.updated_at in the pg adapter.
|
|
195
|
+
*/
|
|
196
|
+
date?: string;
|
|
137
197
|
}
|
|
138
198
|
/** A strategy review entry stored in its own table (not planning_log_entries). */
|
|
139
199
|
interface StrategyReviewEntry {
|
|
140
|
-
|
|
141
|
-
|
|
200
|
+
cycleNumber: number;
|
|
201
|
+
cycleRange?: string;
|
|
142
202
|
title: string;
|
|
143
203
|
content: string;
|
|
144
204
|
notes?: string;
|
|
145
205
|
boardHealth?: string;
|
|
146
206
|
strategicDirection?: string;
|
|
147
207
|
recommendations?: unknown;
|
|
208
|
+
fullAnalysis?: string;
|
|
209
|
+
velocityAssessment?: string;
|
|
210
|
+
/** Full ReviewStructuredOutput from the strategy review LLM, stored as JSONB for dashboard querying */
|
|
211
|
+
structuredData?: Record<string, unknown>;
|
|
212
|
+
createdAt?: string;
|
|
213
|
+
/** Sequential review number per project (1, 2, 3...) */
|
|
214
|
+
reviewNumber?: number;
|
|
215
|
+
/** Review type: 'scheduled' (every 5 cycles), 'ad-hoc' (user-triggered), 'triggered' (by event) */
|
|
216
|
+
reviewType?: string;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* A single entry in a project's harness inventory (task-1896).
|
|
220
|
+
* Captures what skills / sub-agents / hooks / MCP tools a project is running,
|
|
221
|
+
* scanned from the local filesystem by the MCP server and persisted so the
|
|
222
|
+
* dashboard (which has no filesystem access) can surface it per project.
|
|
223
|
+
*/
|
|
224
|
+
interface HarnessInventoryEntry {
|
|
225
|
+
id?: string;
|
|
226
|
+
projectId?: string;
|
|
227
|
+
/** What kind of harness artifact this row describes. */
|
|
228
|
+
kind: 'skill' | 'agent' | 'hook' | 'mcp_tool';
|
|
229
|
+
/** Human-readable name (skill/agent/hook filename stem, or MCP tool name). */
|
|
230
|
+
name: string;
|
|
231
|
+
/** One-line description where available (frontmatter / tool description). */
|
|
232
|
+
description?: string;
|
|
233
|
+
/** Version of the artifact, where known (skills, from the @papi-ai/skills manifest). */
|
|
234
|
+
version?: string;
|
|
235
|
+
/** Content checksum, where known (skills — used to detect stale forks). */
|
|
236
|
+
checksum?: string;
|
|
237
|
+
/**
|
|
238
|
+
* Status signal surfaced in the dashboard:
|
|
239
|
+
* - 'ok': present and current
|
|
240
|
+
* - 'stale_fork': a local skill that has drifted from the pinned registry version
|
|
241
|
+
* - 'missing': a recommended hook that is not installed in the project
|
|
242
|
+
*/
|
|
243
|
+
status: 'ok' | 'stale_fork' | 'missing';
|
|
244
|
+
/** Project-relative path, where applicable (never absolute, never file contents). */
|
|
245
|
+
path?: string;
|
|
246
|
+
syncedAt?: string;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Change-detection marker for the harness inventory (task-1896).
|
|
250
|
+
* A cheap fingerprint of the project's harness layout; the sync writer only
|
|
251
|
+
* does the full scan + DB write when this fingerprint changes.
|
|
252
|
+
*/
|
|
253
|
+
interface HarnessState {
|
|
254
|
+
fingerprint: string;
|
|
255
|
+
syncedAt?: string;
|
|
256
|
+
}
|
|
257
|
+
/** A dogfood observation captured during strategy reviews or releases. */
|
|
258
|
+
interface DogfoodEntry {
|
|
259
|
+
id?: string;
|
|
260
|
+
projectId?: string;
|
|
261
|
+
cycleNumber: number;
|
|
262
|
+
category: 'friction' | 'methodology' | 'signal' | 'commercial';
|
|
263
|
+
content: string;
|
|
264
|
+
sourceTool?: string;
|
|
265
|
+
sourceRef?: string;
|
|
266
|
+
status?: 'observed' | 'backlog-created' | 'resolved' | 'actioned' | 'dismissed';
|
|
267
|
+
linkedTaskId?: string;
|
|
148
268
|
createdAt?: string;
|
|
149
269
|
}
|
|
150
270
|
/** Full parsed contents of PLANNING_LOG.md. */
|
|
151
271
|
interface PlanningLog {
|
|
152
|
-
|
|
272
|
+
cycleHealth: CycleHealth;
|
|
153
273
|
northStar: string;
|
|
154
274
|
activeDecisions: ActiveDecision[];
|
|
155
275
|
deferred: string[];
|
|
156
|
-
|
|
276
|
+
cycleLog: CycleLogEntry[];
|
|
157
277
|
}
|
|
158
278
|
/** A single state transition entry recording when a task changed status. */
|
|
159
279
|
interface StateTransition {
|
|
160
280
|
status: TaskStatus;
|
|
161
281
|
timestamp: string;
|
|
162
282
|
}
|
|
163
|
-
/**
|
|
164
|
-
|
|
283
|
+
/** AD-29: scope_class distinguishes directly-buildable tasks from brief-class items needing decomposition. */
|
|
284
|
+
type ScopeClass = 'task' | 'brief';
|
|
285
|
+
/** A task on the board (parsed from CYCLE_BOARD.md YAML). */
|
|
286
|
+
/** A sibling project's in-flight task, surfaced for the plan duplicate-risk check (task-2139). */
|
|
287
|
+
interface SiblingRepoTask {
|
|
288
|
+
displayId: string;
|
|
289
|
+
title: string;
|
|
290
|
+
epic?: string;
|
|
291
|
+
status: string;
|
|
292
|
+
sourceProjectName: string;
|
|
293
|
+
}
|
|
294
|
+
interface CycleTask {
|
|
165
295
|
uuid: string;
|
|
166
296
|
id: string;
|
|
167
297
|
displayId: string;
|
|
@@ -170,12 +300,15 @@ interface SprintTask {
|
|
|
170
300
|
priority: TaskPriority;
|
|
171
301
|
complexity: TaskComplexity;
|
|
172
302
|
module: string;
|
|
173
|
-
|
|
303
|
+
/** @deprecated (AD-14): Use phase + stageId instead. Will be removed after taxonomy migration. */
|
|
304
|
+
epic?: string;
|
|
174
305
|
phase: string;
|
|
306
|
+
/** Stage FK for AD-14 hierarchy (Horizon → Stage → Phase → Task). */
|
|
307
|
+
stageId?: string;
|
|
175
308
|
owner: string;
|
|
176
309
|
reviewed: boolean;
|
|
177
|
-
|
|
178
|
-
|
|
310
|
+
cycle?: number;
|
|
311
|
+
createdCycle?: number;
|
|
179
312
|
createdAt?: string;
|
|
180
313
|
why?: string;
|
|
181
314
|
dependsOn?: string;
|
|
@@ -186,6 +319,63 @@ interface SprintTask {
|
|
|
186
319
|
buildReport?: string;
|
|
187
320
|
taskType?: TaskType;
|
|
188
321
|
maturity?: TaskMaturity;
|
|
322
|
+
/** Path to a reference document (e.g. docs/research/foo.md). */
|
|
323
|
+
docRef?: string;
|
|
324
|
+
/** Provenance: where this task originated (owner, llm, strategy_review, etc.). */
|
|
325
|
+
source?: string;
|
|
326
|
+
/** What user problem does this solve? Used by planner for opportunity-based clustering. */
|
|
327
|
+
opportunity?: string;
|
|
328
|
+
/** AD-29: 'task' = directly buildable; 'brief' = needs scope_brief decomposition first. Default 'task'. */
|
|
329
|
+
scopeClass?: ScopeClass;
|
|
330
|
+
/** task-1699 (C255): audit who initiated a cancellation. Set when status transitions to 'Cancelled'.
|
|
331
|
+
* 'planner' = planner proposed + user confirmed; 'user' = direct user action; 'system' = automated. */
|
|
332
|
+
cancelledBy?: 'planner' | 'user' | 'system';
|
|
333
|
+
/**
|
|
334
|
+
* Visibility tier (task-2013). Inherited from the source doc when a task is born
|
|
335
|
+
* from `idea`/`plan` with a doc_ref; defaults to 'public'. Read-only after creation —
|
|
336
|
+
* build_execute/review_submit must NOT mutate it.
|
|
337
|
+
*/
|
|
338
|
+
visibility?: DocVisibility;
|
|
339
|
+
/** Owner lock (task-2013) — set on private/contributors rows so a project_id reassignment cannot expose them. */
|
|
340
|
+
ownerUserId?: string;
|
|
341
|
+
/**
|
|
342
|
+
* task-1763 (C293): claim assignee — the user who has claimed this task from the
|
|
343
|
+
* shared pool. NULL/undefined = unclaimed. Set only via the atomic claimTask CAS
|
|
344
|
+
* (bearer-derived identity, never client input). Consumed by MU-3 (task-2071).
|
|
345
|
+
*/
|
|
346
|
+
assigneeId?: string;
|
|
347
|
+
/**
|
|
348
|
+
* task-2071 (C293, MU-3): how this task entered a personal backlog. 'pool' =
|
|
349
|
+
* claimed from the shared org pool via task_claim; 'self_generated' = created
|
|
350
|
+
* already attributed to a user. NULL/undefined = legacy/unattributed. The
|
|
351
|
+
* pooled-task invariant is `assigneeId == null && cycle == null`.
|
|
352
|
+
*/
|
|
353
|
+
claimSource?: 'pool' | 'self_generated';
|
|
354
|
+
/**
|
|
355
|
+
* task-2071 (C293): reviewer slot for MU-4/5 (cross-user review, task-2072).
|
|
356
|
+
* Schema-only this task — no code reads it yet.
|
|
357
|
+
*/
|
|
358
|
+
reviewerId?: string;
|
|
359
|
+
/**
|
|
360
|
+
* task-2180 (C295): ISO timestamp the task's branch was successfully merged to the
|
|
361
|
+
* base branch (review_submit accept or release). NULL/undefined = not yet merged.
|
|
362
|
+
* Write-only audit tie between Done status and git reality — set on a successful
|
|
363
|
+
* merge so a Done task is provably backed by a real merge; no reader yet.
|
|
364
|
+
*/
|
|
365
|
+
mergedAt?: string;
|
|
366
|
+
}
|
|
367
|
+
/** Structured handoff accuracy — replaces coarse scope_accuracy text. */
|
|
368
|
+
interface HandoffAccuracy {
|
|
369
|
+
scopeMatch: boolean;
|
|
370
|
+
filesMatch: 'exact' | 'partial' | 'missed';
|
|
371
|
+
effortMatch: boolean;
|
|
372
|
+
notes?: string;
|
|
373
|
+
}
|
|
374
|
+
/** Brief implications from a build — discovery learnings that feed back into planning. */
|
|
375
|
+
interface BriefImplication {
|
|
376
|
+
canvasSection: 'landscape' | 'journeys' | 'mvpBoundary' | 'assumptions' | 'successSignals';
|
|
377
|
+
type: 'confirm' | 'contradict' | 'new';
|
|
378
|
+
detail: string;
|
|
189
379
|
}
|
|
190
380
|
/** A build report entry from BUILD_REPORTS.md. */
|
|
191
381
|
interface BuildReport {
|
|
@@ -195,7 +385,7 @@ interface BuildReport {
|
|
|
195
385
|
taskId: string;
|
|
196
386
|
taskName: string;
|
|
197
387
|
date: string;
|
|
198
|
-
|
|
388
|
+
cycle: number;
|
|
199
389
|
completed: 'Yes' | 'No' | 'Partial';
|
|
200
390
|
actualEffort: EffortSize;
|
|
201
391
|
estimatedEffort: EffortSize;
|
|
@@ -205,7 +395,139 @@ interface BuildReport {
|
|
|
205
395
|
scopeAccuracy: 'accurate' | 'over-scoped' | 'under-scoped' | 'missed-context';
|
|
206
396
|
commitSha?: string;
|
|
207
397
|
filesChanged?: string[];
|
|
398
|
+
/**
|
|
399
|
+
* task-1523 (C242): scope drift signal.
|
|
400
|
+
* Populated when filesChanged diverges materially from the handoff's filesLikelyTouched
|
|
401
|
+
* (e.g. >50% of changed files unpredicted, or >5 unexpected files). Format is a single
|
|
402
|
+
* human-readable line surfaced under "Scope drift signal" in the build report. Does NOT block.
|
|
403
|
+
*/
|
|
404
|
+
scopeDriftSignal?: string;
|
|
208
405
|
relatedDecisions?: string[];
|
|
406
|
+
handoffAccuracy?: HandoffAccuracy;
|
|
407
|
+
correctionsCount?: number;
|
|
408
|
+
briefImplications?: BriefImplication[];
|
|
409
|
+
deadEnds?: string;
|
|
410
|
+
/** Number of build iterations for this task (1 = first attempt, 2+ = rework after pushback). */
|
|
411
|
+
iterationCount?: number;
|
|
412
|
+
/** ISO 8601 timestamp when build_execute (start) was called. */
|
|
413
|
+
startedAt?: string;
|
|
414
|
+
/** ISO 8601 timestamp when build_execute (complete) was called. */
|
|
415
|
+
completedAt?: string;
|
|
416
|
+
/** Number of tool calls recorded during this build session. */
|
|
417
|
+
toolCallCount?: number;
|
|
418
|
+
/**
|
|
419
|
+
* task-1853 deploy-verification record. Populated when the task's diff hit a
|
|
420
|
+
* trigger surface (TRIGGER_SURFACE_GLOBS) and the builder verified the live deploy.
|
|
421
|
+
* Required by `completeBuild` for trigger-surface tasks; gates `review_submit` accept.
|
|
422
|
+
*/
|
|
423
|
+
productionVerification?: {
|
|
424
|
+
urls: string[];
|
|
425
|
+
curl_command: string;
|
|
426
|
+
http_status: number;
|
|
427
|
+
response_excerpt: string;
|
|
428
|
+
verified_at: string;
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
/** A registered document in the doc registry. */
|
|
432
|
+
/**
|
|
433
|
+
* Doc visibility tier (task-1977, C283).
|
|
434
|
+
* - public: shipped with PAPI, readable cross-project by any user.
|
|
435
|
+
* - contributors: "team member" tier — readable by the project's contributor cohort.
|
|
436
|
+
* - private: owner-only (default — safety bias).
|
|
437
|
+
* User-facing label for `contributors` is "team member".
|
|
438
|
+
*/
|
|
439
|
+
type DocVisibility = 'public' | 'contributors' | 'private';
|
|
440
|
+
interface DocRegistryEntry {
|
|
441
|
+
id: string;
|
|
442
|
+
title: string;
|
|
443
|
+
type: string;
|
|
444
|
+
path: string;
|
|
445
|
+
status: string;
|
|
446
|
+
summary: string;
|
|
447
|
+
tags: string[];
|
|
448
|
+
cycleCreated: number;
|
|
449
|
+
cycleUpdated?: number;
|
|
450
|
+
supersededBy?: string;
|
|
451
|
+
actions?: Array<{
|
|
452
|
+
description: string;
|
|
453
|
+
status: string;
|
|
454
|
+
linkedTaskId?: string;
|
|
455
|
+
}>;
|
|
456
|
+
/** Visibility tier (task-1977). Defaults to 'private' at write time when omitted. */
|
|
457
|
+
visibility?: DocVisibility;
|
|
458
|
+
/** Owner lock — the user_id that owns this doc; set on register so a project_id reassignment cannot expose private rows. */
|
|
459
|
+
ownerUserId?: string;
|
|
460
|
+
createdAt?: string;
|
|
461
|
+
updatedAt?: string;
|
|
462
|
+
}
|
|
463
|
+
/** A structured learning entry from a build report. */
|
|
464
|
+
interface CycleLearning {
|
|
465
|
+
id?: string;
|
|
466
|
+
projectId?: string;
|
|
467
|
+
taskId: string;
|
|
468
|
+
cycleNumber: number;
|
|
469
|
+
category: 'surprise' | 'issue' | 'dead_end' | 'architecture' | 'estimation_miss' | 'doc_closure' | 'observability';
|
|
470
|
+
severity?: 'P0' | 'P1' | 'P2' | 'P3';
|
|
471
|
+
summary: string;
|
|
472
|
+
detail?: string;
|
|
473
|
+
tags: string[];
|
|
474
|
+
relatedDecision?: string;
|
|
475
|
+
actionTaken?: 'idea_submitted' | 'task_created' | 'ad_updated' | 'none';
|
|
476
|
+
actionRef?: string;
|
|
477
|
+
createdAt?: string;
|
|
478
|
+
/** When the underlying issue was marked resolved. null/undefined = still open. (task-1541) */
|
|
479
|
+
resolvedAt?: string;
|
|
480
|
+
/** Identifier of the agent/user that resolved the issue (task-1541). */
|
|
481
|
+
resolvedBy?: string;
|
|
482
|
+
}
|
|
483
|
+
/** A cross-cycle pattern detected from learning tags. */
|
|
484
|
+
interface CycleLearningPattern {
|
|
485
|
+
tag: string;
|
|
486
|
+
cycles: number[];
|
|
487
|
+
frequency: number;
|
|
488
|
+
}
|
|
489
|
+
/** Input for doc_search queries. */
|
|
490
|
+
interface DocSearchInput {
|
|
491
|
+
type?: string;
|
|
492
|
+
status?: string;
|
|
493
|
+
tags?: string[];
|
|
494
|
+
keyword?: string;
|
|
495
|
+
hasPendingActions?: boolean;
|
|
496
|
+
sinceCycle?: number;
|
|
497
|
+
limit?: number;
|
|
498
|
+
/**
|
|
499
|
+
* Visibility scoping (task-1977). The user_id of the requester. When set and the
|
|
500
|
+
* requester is NOT the project owner, results are filtered to public docs plus
|
|
501
|
+
* contributors-tier docs the requester is a cohort member of (private excluded —
|
|
502
|
+
* fail-closed). When omitted (local owner/CLI context), all rows are returned.
|
|
503
|
+
*/
|
|
504
|
+
requesterUserId?: string;
|
|
505
|
+
}
|
|
506
|
+
/** Aggregated recommendation effectiveness row from v_recommendation_effectiveness. */
|
|
507
|
+
interface RecommendationEffectivenessRow {
|
|
508
|
+
type: string;
|
|
509
|
+
total: number;
|
|
510
|
+
actioned: number;
|
|
511
|
+
dismissed: number;
|
|
512
|
+
pending: number;
|
|
513
|
+
acceptanceRate: string;
|
|
514
|
+
avgCyclesToAction: string | null;
|
|
515
|
+
}
|
|
516
|
+
/** Aggregated estimation calibration row from v_estimation_accuracy. */
|
|
517
|
+
interface EstimationCalibrationRow {
|
|
518
|
+
estimatedEffort: string;
|
|
519
|
+
actualEffort: string;
|
|
520
|
+
accuracyLabel: string;
|
|
521
|
+
count: number;
|
|
522
|
+
}
|
|
523
|
+
/** Per-module estimation stats — builds joined with task module via cycle_tasks. */
|
|
524
|
+
interface ModuleEstimationRow {
|
|
525
|
+
module: string;
|
|
526
|
+
total: number;
|
|
527
|
+
/** % of tasks where estimated effort matched actual effort. */
|
|
528
|
+
accuracyPct: number;
|
|
529
|
+
/** % of tasks where scope_accuracy was 'accurate'. */
|
|
530
|
+
scopeAccuratePct: number;
|
|
209
531
|
}
|
|
210
532
|
/** A single tool call metric entry from METRICS.md. */
|
|
211
533
|
interface ToolCallMetric {
|
|
@@ -216,12 +538,21 @@ interface ToolCallMetric {
|
|
|
216
538
|
outputTokens?: number;
|
|
217
539
|
estimatedCostUsd?: number;
|
|
218
540
|
model?: string;
|
|
219
|
-
/**
|
|
220
|
-
|
|
541
|
+
/** Cycle number when this metric was recorded. Absent on legacy rows. */
|
|
542
|
+
cycleNumber?: number;
|
|
221
543
|
/** Context size in bytes for plan tool calls. Absent on non-plan tools. */
|
|
222
544
|
contextBytes?: number;
|
|
223
545
|
/** Context utilisation ratio (0.0–1.0). Fraction of input entities referenced in output. */
|
|
224
546
|
contextUtilisation?: number;
|
|
547
|
+
/** Whether the tool call succeeded (no error prefix in response). */
|
|
548
|
+
success?: boolean;
|
|
549
|
+
/**
|
|
550
|
+
* MCP client `Implementation.name` advertised at initialize time.
|
|
551
|
+
* Captured verbatim (Claude Code = "claude-code"; Codex advertises a
|
|
552
|
+
* different string). Used to split activation/feature funnels by CLI.
|
|
553
|
+
* Absent on legacy rows + non-MCP code paths. (task-1680)
|
|
554
|
+
*/
|
|
555
|
+
clientName?: string;
|
|
225
556
|
}
|
|
226
557
|
/** Per-command cost aggregation. */
|
|
227
558
|
interface CommandCost {
|
|
@@ -241,8 +572,32 @@ interface CostSummary {
|
|
|
241
572
|
avgCostPerCall: number;
|
|
242
573
|
}
|
|
243
574
|
/** A cost snapshot persisted in the Cost Summary section of METRICS.md. */
|
|
575
|
+
/** Discovery canvas — progressive discovery sections on product brief. */
|
|
576
|
+
interface DiscoveryCanvas {
|
|
577
|
+
landscapeReferences?: {
|
|
578
|
+
name: string;
|
|
579
|
+
url?: string;
|
|
580
|
+
notes?: string;
|
|
581
|
+
}[];
|
|
582
|
+
userJourneys?: {
|
|
583
|
+
persona: string;
|
|
584
|
+
journey: string;
|
|
585
|
+
priority?: string;
|
|
586
|
+
}[];
|
|
587
|
+
mvpBoundary?: string;
|
|
588
|
+
assumptionsOpenQuestions?: {
|
|
589
|
+
text: string;
|
|
590
|
+
status: string;
|
|
591
|
+
evidence?: string;
|
|
592
|
+
}[];
|
|
593
|
+
successSignals?: {
|
|
594
|
+
signal: string;
|
|
595
|
+
metric?: string;
|
|
596
|
+
target?: string;
|
|
597
|
+
}[];
|
|
598
|
+
}
|
|
244
599
|
interface CostSnapshot {
|
|
245
|
-
|
|
600
|
+
cycle: number;
|
|
246
601
|
date: string;
|
|
247
602
|
totalCostUsd: number;
|
|
248
603
|
totalInputTokens: number;
|
|
@@ -268,7 +623,7 @@ type TextClusterer = (entries: ClusterEntry[]) => Promise<ClusterResult[]>;
|
|
|
268
623
|
interface RecurringSurprise {
|
|
269
624
|
text: string;
|
|
270
625
|
count: number;
|
|
271
|
-
|
|
626
|
+
cycles: number[];
|
|
272
627
|
}
|
|
273
628
|
/** Build pattern detection results from analyzing recent build reports. */
|
|
274
629
|
interface BuildPatterns {
|
|
@@ -278,28 +633,28 @@ interface BuildPatterns {
|
|
|
278
633
|
scopeAccuracyBreakdown: Record<string, number>;
|
|
279
634
|
untriagedIssues: string[];
|
|
280
635
|
}
|
|
281
|
-
/** Per-
|
|
282
|
-
interface
|
|
283
|
-
|
|
636
|
+
/** Per-cycle estimation accuracy stats. */
|
|
637
|
+
interface CycleEstimationAccuracy {
|
|
638
|
+
cycle: number;
|
|
284
639
|
reports: number;
|
|
285
640
|
matchRate: number;
|
|
286
641
|
mae: number;
|
|
287
642
|
bias: number;
|
|
288
643
|
}
|
|
289
|
-
/** Per-
|
|
290
|
-
interface
|
|
291
|
-
|
|
644
|
+
/** Per-cycle velocity stats. */
|
|
645
|
+
interface CycleVelocity {
|
|
646
|
+
cycle: number;
|
|
292
647
|
completed: number;
|
|
293
648
|
partial: number;
|
|
294
649
|
failed: number;
|
|
295
650
|
effortPoints: number;
|
|
296
651
|
}
|
|
297
|
-
/** A
|
|
298
|
-
interface
|
|
299
|
-
|
|
652
|
+
/** A cycle methodology metrics snapshot stored in CYCLE_METRICS.md. */
|
|
653
|
+
interface CycleMetricsSnapshot {
|
|
654
|
+
cycle: number;
|
|
300
655
|
date: string;
|
|
301
|
-
accuracy:
|
|
302
|
-
velocity:
|
|
656
|
+
accuracy: CycleEstimationAccuracy[];
|
|
657
|
+
velocity: CycleVelocity[];
|
|
303
658
|
}
|
|
304
659
|
/** A recurring feedback theme detected across human reviews. */
|
|
305
660
|
interface RecurringFeedback {
|
|
@@ -313,6 +668,21 @@ interface ReviewPatterns {
|
|
|
313
668
|
verdictBreakdown: Record<string, number>;
|
|
314
669
|
requestChangesRate: number;
|
|
315
670
|
}
|
|
671
|
+
/** Auto-review verdict from automated code review. */
|
|
672
|
+
type AutoReviewVerdict = 'pass' | 'warn' | 'fail';
|
|
673
|
+
/** A single finding from an automated code review. */
|
|
674
|
+
interface AutoReviewFinding {
|
|
675
|
+
severity: 'error' | 'warning' | 'info';
|
|
676
|
+
file?: string;
|
|
677
|
+
line?: number;
|
|
678
|
+
message: string;
|
|
679
|
+
}
|
|
680
|
+
/** Automated code review results — supplements human review. */
|
|
681
|
+
interface AutoReview {
|
|
682
|
+
verdict: AutoReviewVerdict;
|
|
683
|
+
findings: AutoReviewFinding[];
|
|
684
|
+
summary: string;
|
|
685
|
+
}
|
|
316
686
|
/** A human review entry stored in REVIEWS.md. */
|
|
317
687
|
interface HumanReview {
|
|
318
688
|
uuid: string;
|
|
@@ -321,11 +691,13 @@ interface HumanReview {
|
|
|
321
691
|
stage: ReviewStage;
|
|
322
692
|
reviewer: string;
|
|
323
693
|
verdict: ReviewVerdict;
|
|
324
|
-
|
|
694
|
+
cycle: number;
|
|
325
695
|
date: string;
|
|
326
696
|
comments: string;
|
|
327
697
|
handoffRevision?: number;
|
|
328
698
|
buildCommitSha?: string;
|
|
699
|
+
/** Optional automated code review results attached to this review. */
|
|
700
|
+
autoReview?: AutoReview;
|
|
329
701
|
}
|
|
330
702
|
/** A structured BUILD HANDOFF parsed from the markdown handoff block. */
|
|
331
703
|
interface BuildHandoff {
|
|
@@ -334,7 +706,7 @@ interface BuildHandoff {
|
|
|
334
706
|
createdAt?: string;
|
|
335
707
|
taskId: string;
|
|
336
708
|
taskTitle: string;
|
|
337
|
-
|
|
709
|
+
cycle: number;
|
|
338
710
|
whyNow: string;
|
|
339
711
|
scope: string[];
|
|
340
712
|
scopeBoundary: string[];
|
|
@@ -342,12 +714,27 @@ interface BuildHandoff {
|
|
|
342
714
|
securityConsiderations: string;
|
|
343
715
|
filesLikelyTouched: string[];
|
|
344
716
|
effort: EffortSize;
|
|
717
|
+
/** Files the builder should check before implementing to verify the feature doesn't already exist. */
|
|
718
|
+
verificationFiles?: string[];
|
|
345
719
|
}
|
|
346
720
|
/** Module and epic registries loaded from REGISTRIES.md. */
|
|
347
721
|
interface Registries {
|
|
348
722
|
modules: string[];
|
|
349
723
|
epics: string[];
|
|
350
724
|
}
|
|
725
|
+
/** Lifecycle status for a queued strategy review agenda topic. */
|
|
726
|
+
type AgendaTopicStatus = 'pending' | 'addressed' | 'dismissed';
|
|
727
|
+
/** A topic queued for the next strategy review. */
|
|
728
|
+
interface AgendaTopic {
|
|
729
|
+
id: string;
|
|
730
|
+
topic: string;
|
|
731
|
+
source: string;
|
|
732
|
+
sourceCycle?: number;
|
|
733
|
+
status: AgendaTopicStatus;
|
|
734
|
+
createdAt: string;
|
|
735
|
+
addressedAt?: string;
|
|
736
|
+
addressedInReview?: number;
|
|
737
|
+
}
|
|
351
738
|
/** Recommendation types written by strategy_review, consumed by plan. */
|
|
352
739
|
type RecommendationType = 'priority_change' | 'new_task' | 'ad_update' | 'phase_transition' | 'process_improvement' | 'infrastructure' | 'velocity_observation';
|
|
353
740
|
/** Recommendation lifecycle status. */
|
|
@@ -358,8 +745,25 @@ interface StrategyRecommendation {
|
|
|
358
745
|
type: RecommendationType;
|
|
359
746
|
status: RecommendationStatus;
|
|
360
747
|
content: string;
|
|
361
|
-
|
|
362
|
-
|
|
748
|
+
createdCycle: number;
|
|
749
|
+
actionedCycle?: number;
|
|
750
|
+
target?: string;
|
|
751
|
+
}
|
|
752
|
+
/** Upstream submission (bug or idea) sent to PAPI for cross-project visibility. */
|
|
753
|
+
interface BugReport {
|
|
754
|
+
id: string;
|
|
755
|
+
projectId: string;
|
|
756
|
+
userId?: string;
|
|
757
|
+
/** Kind of submission. Defaults to 'bug' for back-compat with the legacy `bug report=true` flow (task-2174, C296). */
|
|
758
|
+
type?: 'bug' | 'idea';
|
|
759
|
+
description: string;
|
|
760
|
+
diagnostics: Record<string, unknown>;
|
|
761
|
+
status: 'open' | 'resolved' | 'dismissed';
|
|
762
|
+
/** Submitter opted in to be notified when this is resolved (friction-moment opt-in). */
|
|
763
|
+
notifyRequested?: boolean;
|
|
764
|
+
/** Submitter consented to the PAPI team reaching out about this submission. */
|
|
765
|
+
contactOk?: boolean;
|
|
766
|
+
createdAt: string;
|
|
363
767
|
}
|
|
364
768
|
/** Entity reference — tracks which decisions/entities are used in tool calls. */
|
|
365
769
|
interface EntityReference {
|
|
@@ -368,22 +772,30 @@ interface EntityReference {
|
|
|
368
772
|
entityId: string;
|
|
369
773
|
referenceContext: 'plan_input' | 'plan_output' | 'strategy_input' | 'strategy_output';
|
|
370
774
|
toolName: string;
|
|
371
|
-
|
|
775
|
+
cycleNumber: number;
|
|
372
776
|
createdAt: string;
|
|
373
777
|
}
|
|
778
|
+
/** Per-tool context utilisation summary from v_context_utilisation. */
|
|
779
|
+
interface ContextUtilisationSummary {
|
|
780
|
+
tool: string;
|
|
781
|
+
cycleNumber: number;
|
|
782
|
+
callCount: number;
|
|
783
|
+
avgUtilisation: number;
|
|
784
|
+
avgContextBytes: number;
|
|
785
|
+
}
|
|
374
786
|
/** Per-AD usage summary returned by getDecisionUsage. */
|
|
375
787
|
interface DecisionUsageSummary {
|
|
376
788
|
decisionId: string;
|
|
377
789
|
referenceCount: number;
|
|
378
|
-
|
|
379
|
-
|
|
790
|
+
lastReferencedCycle: number;
|
|
791
|
+
cyclesSinceLastReference: number;
|
|
380
792
|
}
|
|
381
793
|
/** Options for updateTask to control validation behaviour. */
|
|
382
794
|
interface UpdateTaskOptions {
|
|
383
795
|
/** Skip state-machine transition validation when true. */
|
|
384
796
|
force?: boolean;
|
|
385
797
|
}
|
|
386
|
-
/** Filter options for querying the
|
|
798
|
+
/** Filter options for querying the cycle board. */
|
|
387
799
|
interface BoardQueryOptions {
|
|
388
800
|
status?: TaskStatus[];
|
|
389
801
|
priority?: TaskPriority[];
|
|
@@ -391,31 +803,183 @@ interface BoardQueryOptions {
|
|
|
391
803
|
reviewed?: boolean;
|
|
392
804
|
module?: string;
|
|
393
805
|
epic?: string;
|
|
394
|
-
/** Filter by context tier (1=
|
|
806
|
+
/** Filter by context tier (1=cycle-eligible, 2=plannable, 3=pre-triage). */
|
|
395
807
|
contextTier?: ContextTier;
|
|
808
|
+
/** Filter to tasks assigned to this cycle or later (cycle >= N). */
|
|
809
|
+
cycleSince?: number;
|
|
810
|
+
/** Exclude heavy JSONB columns (build_handoff, build_report, state_history) to reduce DB transfer. */
|
|
811
|
+
compact?: boolean;
|
|
812
|
+
/**
|
|
813
|
+
* Visibility scoping (task-2013). The user_id of the requester. When set and the
|
|
814
|
+
* requester is NOT the project owner, results are filtered to public tasks plus
|
|
815
|
+
* contributors-tier tasks the requester is a cohort member of (private excluded —
|
|
816
|
+
* fail-closed). When omitted (local owner/CLI context), all rows are returned.
|
|
817
|
+
* Mirrors DocSearchInput.requesterUserId exactly.
|
|
818
|
+
*/
|
|
819
|
+
requesterUserId?: string;
|
|
820
|
+
/**
|
|
821
|
+
* task-2071 (C293, MU-3): filter to tasks claimed by this user (assignee_id =
|
|
822
|
+
* value). Used by plan's per-user "draw from my personal backlog" path. Does
|
|
823
|
+
* NOT widen visibility — it narrows an already-authorised result set.
|
|
824
|
+
*/
|
|
825
|
+
assigneeId?: string;
|
|
826
|
+
}
|
|
827
|
+
interface OwnerActionInput {
|
|
828
|
+
name: string;
|
|
829
|
+
project_ids?: string[];
|
|
830
|
+
category?: string | null;
|
|
831
|
+
status?: 'todo' | 'waiting' | 'done';
|
|
832
|
+
dependency?: string | null;
|
|
833
|
+
docs_link?: string | null;
|
|
834
|
+
unlocks_task_id?: string | null;
|
|
835
|
+
}
|
|
836
|
+
interface OwnerActionRow extends OwnerActionInput {
|
|
837
|
+
id: string;
|
|
838
|
+
user_id: string;
|
|
839
|
+
project_ids: string[];
|
|
840
|
+
status: 'todo' | 'waiting' | 'done';
|
|
841
|
+
completed_at: string | null;
|
|
842
|
+
created_at: string;
|
|
843
|
+
updated_at: string;
|
|
396
844
|
}
|
|
397
845
|
/** Core adapter interface for reading/writing .papi/ markdown files. */
|
|
398
846
|
interface PapiAdapter {
|
|
399
847
|
readPlanningLog(): Promise<PlanningLog>;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
848
|
+
getCycleHealth(): Promise<CycleHealth>;
|
|
849
|
+
/**
|
|
850
|
+
* Read Active Decisions for this project.
|
|
851
|
+
*
|
|
852
|
+
* Default behaviour (no options or `{ includeRetired: false }`) excludes ADs that
|
|
853
|
+
* are no longer steering the project: outcome ∈ ('abandoned', 'superseded', 'resolved')
|
|
854
|
+
* OR superseded = true. This is the correct signal for context-injection surfaces
|
|
855
|
+
* (orient, build_execute handoffs, plan context, strategy housekeeping displays).
|
|
856
|
+
*
|
|
857
|
+
* Pass `{ includeRetired: true }` for management/triage surfaces that need to see
|
|
858
|
+
* retired ADs explicitly — e.g. strategy_review (so retired ADs can be re-validated
|
|
859
|
+
* or restored), and any code that needs the full ID space (next-AD-number computation,
|
|
860
|
+
* dedupe against existing IDs, lifecycle counts).
|
|
861
|
+
*
|
|
862
|
+
* task-1546 (C242 hot-fix): closes the bug where retired ADs (e.g. AD-26, abandoned
|
|
863
|
+
* in C241) continued to appear in build/plan/orient context as "active" because
|
|
864
|
+
* consumers only filtered the `superseded` boolean and ignored the `outcome` lifecycle.
|
|
865
|
+
*/
|
|
866
|
+
getActiveDecisions(options?: {
|
|
867
|
+
includeRetired?: boolean;
|
|
868
|
+
}): Promise<ActiveDecision[]>;
|
|
869
|
+
/** Query ADs from sibling project IDs in the same Supabase instance. pg adapter only. */
|
|
870
|
+
getSiblingAds?(projectIds: string[]): Promise<Array<ActiveDecision & {
|
|
871
|
+
sourceProjectId: string;
|
|
872
|
+
}>>;
|
|
873
|
+
/**
|
|
874
|
+
* task-2139: in-flight tasks from OTHER projects that share THIS project's
|
|
875
|
+
* repo_url. Surfaced in plan prepare context so the planner does not
|
|
876
|
+
* re-schedule work already underway on the shared repo (the C292 duplicate
|
|
877
|
+
* incident). Scoped to repo_url siblings (never the whole DB); returns only
|
|
878
|
+
* the fields the dup-check needs. pg adapter only — md/proxy omit it and the
|
|
879
|
+
* caller feature-checks.
|
|
880
|
+
*/
|
|
881
|
+
getSiblingRepoTasks?(): Promise<SiblingRepoTask[]>;
|
|
882
|
+
getCycleLog(limit?: number): Promise<CycleLogEntry[]>;
|
|
883
|
+
getCycleLogSince(cycleNumber: number): Promise<CycleLogEntry[]>;
|
|
884
|
+
setCycleHealth(updates: Partial<CycleHealth>): Promise<void>;
|
|
885
|
+
writeCycleLogEntry(entry: CycleLogEntry): Promise<void>;
|
|
886
|
+
updateActiveDecision(id: string, body: string, cycleNumber?: number, action?: 'confidence_change' | 'modify' | 'resolve' | 'supersede' | 'new' | 'delete'): Promise<void>;
|
|
887
|
+
/** Upsert an AD — creates if display_id doesn't exist, updates if it does. */
|
|
888
|
+
upsertActiveDecision?(id: string, body: string, title: string, confidence: string, cycleNumber: number): Promise<void>;
|
|
889
|
+
/** Delete an AD permanently by display_id. */
|
|
890
|
+
deleteActiveDecision?(id: string): Promise<void>;
|
|
891
|
+
/** After a strategy review, mark all still-pending ADs as confirmed (reviewed, no changes). */
|
|
892
|
+
confirmPendingActiveDecisions?(cycleNumber: number): Promise<void>;
|
|
893
|
+
queryBoard(options?: BoardQueryOptions): Promise<CycleTask[]>;
|
|
894
|
+
getTask(id: string): Promise<CycleTask | null>;
|
|
895
|
+
getTasks(ids: string[]): Promise<CycleTask[]>;
|
|
896
|
+
createTask(task: Omit<CycleTask, 'id'>): Promise<CycleTask>;
|
|
897
|
+
/**
|
|
898
|
+
* task-1917 (C280): Owner Action Queue support.
|
|
899
|
+
* Optional — only adapters backed by a database that has the owner_actions
|
|
900
|
+
* table need to implement these. Callers must feature-check before use:
|
|
901
|
+
* if (adapter.createOwnerAction) { ... }
|
|
902
|
+
*/
|
|
903
|
+
createOwnerAction?(userId: string, input: OwnerActionInput): Promise<OwnerActionRow>;
|
|
904
|
+
/**
|
|
905
|
+
* Count rows in owner_actions for the given user that are not yet
|
|
906
|
+
* completed. Used by orient to surface "N actions waiting on you".
|
|
907
|
+
* task-2041 (C284): optional projectId scopes to one project (untagged actions
|
|
908
|
+
* count as global). Omit it for the cross-project /hub aggregate.
|
|
909
|
+
*/
|
|
910
|
+
countOpenOwnerActions?(userId: string, projectId?: string): Promise<number>;
|
|
911
|
+
/**
|
|
912
|
+
* Count open owner_actions a delegate has nudged the owner about (task-2018).
|
|
913
|
+
* Surfaced by orient separately from the open-count. Optional — md adapter and
|
|
914
|
+
* pre-v2 deployments simply skip the line. task-2041: optional projectId scope.
|
|
915
|
+
*/
|
|
916
|
+
countNudgedOwnerActions?(userId: string, projectId?: string): Promise<number>;
|
|
917
|
+
/** task-2041 (C284): the project this adapter is scoped to (pg adapter only). */
|
|
918
|
+
getProjectId?(): string;
|
|
919
|
+
/**
|
|
920
|
+
* task-2051 (C284): count the user's OPEN owner actions whose unlocks_task_id
|
|
921
|
+
* points at a build task currently 'Blocked'. Surfaced by orient as a
|
|
922
|
+
* "complete these to unblock build work" nudge. Optional — md adapter and
|
|
923
|
+
* pre-status deployments skip the line.
|
|
924
|
+
*/
|
|
925
|
+
countOwnerActionsBlockingTasks?(userId: string): Promise<number>;
|
|
926
|
+
/**
|
|
927
|
+
* Team Ops v4: count the user's OPEN owner actions by due date — dueToday
|
|
928
|
+
* (due_date = today) and overdue (due_date < today). Folded into orient's
|
|
929
|
+
* "N actions waiting on you" line. Optional — md adapter and pre-v4
|
|
930
|
+
* deployments skip the suffix. Optional projectId scope as countOpenOwnerActions.
|
|
931
|
+
*/
|
|
932
|
+
countDueOwnerActions?(userId: string, projectId?: string): Promise<{
|
|
933
|
+
dueToday: number;
|
|
934
|
+
overdue: number;
|
|
935
|
+
}>;
|
|
936
|
+
updateTask(id: string, updates: Partial<Omit<CycleTask, 'id'>>, options?: UpdateTaskOptions): Promise<void>;
|
|
412
937
|
updateTaskStatus(id: string, status: TaskStatus): Promise<void>;
|
|
938
|
+
/**
|
|
939
|
+
* task-2182: correct a mis-recorded estimate/actual on the LATEST build report
|
|
940
|
+
* for a task. pg-only (project_id-scoped UPDATE on the MAX(created_at) row); md
|
|
941
|
+
* is legacy and omits it. Carried by board_edit's estimated_effort/actual_effort.
|
|
942
|
+
*/
|
|
943
|
+
correctLatestBuildReportEffort?(taskId: string, fields: {
|
|
944
|
+
estimatedEffort?: string;
|
|
945
|
+
actualEffort?: string;
|
|
946
|
+
}): Promise<void>;
|
|
947
|
+
/**
|
|
948
|
+
* task-1763 (C293): atomic compare-and-swap task claim. Sets assignee_id ONLY if
|
|
949
|
+
* the task is currently unclaimed (assignee_id IS NULL) — first-claim-wins, no
|
|
950
|
+
* queueing. Returns the claimed task on success, or null if it was already claimed
|
|
951
|
+
* (or does not exist). assigneeId must be the bearer-derived identity, never client
|
|
952
|
+
* input; the implementation scopes by project_id so a claim can never cross tenant.
|
|
953
|
+
* Optional: the primitive layer for MU-3 (task-2071); proxy/edge wiring lands with
|
|
954
|
+
* the task_claim tool in task-2071.
|
|
955
|
+
*/
|
|
956
|
+
claimTask?(taskId: string, assigneeId: string): Promise<CycleTask | null>;
|
|
957
|
+
/**
|
|
958
|
+
* task-2071 (C293, MU-3): atomic claimer-only release. Clears assignee_id (and
|
|
959
|
+
* claim_source) ONLY if the task is currently assigned to `assigneeId` AND has
|
|
960
|
+
* not yet entered review (status NOT IN 'In Review','Done'). Returns the
|
|
961
|
+
* unclaimed task on success, or null if the caller is not the claimer, the task
|
|
962
|
+
* has progressed past claim, or it does not exist. Scoped by project_id.
|
|
963
|
+
*/
|
|
964
|
+
unclaimTask?(taskId: string, assigneeId: string): Promise<CycleTask | null>;
|
|
965
|
+
/**
|
|
966
|
+
* task-2072 (C293, MU-4): atomic compare-and-swap REVIEW claim — the cross-user
|
|
967
|
+
* review queue primitive. Sets reviewer_id ONLY if the task is currently In
|
|
968
|
+
* Review and unclaimed-for-review (reviewer_id IS NULL). Returns the claimed
|
|
969
|
+
* task on success, or null if another reviewer already claimed it, it is not In
|
|
970
|
+
* Review, or it does not exist. reviewerId is bearer-derived, never client
|
|
971
|
+
* input; scoped by project_id. First-claim-wins (no double-review race).
|
|
972
|
+
*/
|
|
973
|
+
claimReview?(taskId: string, reviewerId: string): Promise<CycleTask | null>;
|
|
974
|
+
/** Record a task status transition for audit trail. */
|
|
975
|
+
recordTransition(taskId: string, fromStatus: string, toStatus: string, changedBy?: string): Promise<void>;
|
|
413
976
|
appendBuildReport(report: BuildReport): Promise<void>;
|
|
414
977
|
getRecentBuildReports(count: number): Promise<BuildReport[]>;
|
|
415
|
-
|
|
978
|
+
getBuildReportCountForTask(taskId: string): Promise<number>;
|
|
979
|
+
getBuildReportsSince(cycleNumber: number): Promise<BuildReport[]>;
|
|
416
980
|
getRecentReviews(count?: number): Promise<HumanReview[]>;
|
|
417
981
|
writeReview(review: HumanReview): Promise<void>;
|
|
418
|
-
|
|
982
|
+
compressCycleLog(threshold: number, summary: string): Promise<void>;
|
|
419
983
|
compressBuildReports(threshold: number, summary: string): Promise<void>;
|
|
420
984
|
archiveTasks(phases: string[], statuses?: string[]): Promise<{
|
|
421
985
|
archivedCount: number;
|
|
@@ -423,38 +987,210 @@ interface PapiAdapter {
|
|
|
423
987
|
}>;
|
|
424
988
|
readProductBrief(): Promise<string>;
|
|
425
989
|
updateProductBrief(content: string): Promise<void>;
|
|
990
|
+
/** Read discovery canvas sections from product brief. */
|
|
991
|
+
readDiscoveryCanvas(): Promise<DiscoveryCanvas>;
|
|
992
|
+
/** Update discovery canvas sections on product brief. */
|
|
993
|
+
updateDiscoveryCanvas(canvas: Partial<DiscoveryCanvas>): Promise<void>;
|
|
426
994
|
readPhases(): Promise<Phase[]>;
|
|
427
995
|
writePhases(phases: Phase[]): Promise<void>;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
996
|
+
/** Read all horizons for the project (AD-14 hierarchy). */
|
|
997
|
+
readHorizons?(): Promise<Horizon[]>;
|
|
998
|
+
/** Read all stages for the project, optionally filtered by horizon (AD-14 hierarchy). */
|
|
999
|
+
readStages?(horizonId?: string): Promise<Stage[]>;
|
|
1000
|
+
/** Update a stage's status (e.g. 'Active' → 'Complete'). */
|
|
1001
|
+
updateStageStatus?(stageId: string, status: string): Promise<void>;
|
|
1002
|
+
updateStageExitCriteria?(stageId: string, exitCriteria: string[]): Promise<void>;
|
|
1003
|
+
/** Update a horizon's status (e.g. 'Active' → 'Complete'). */
|
|
1004
|
+
updateHorizonStatus?(horizonId: string, status: string): Promise<void>;
|
|
1005
|
+
/** Update a phase's status (e.g. 'Active' → 'Complete'). */
|
|
1006
|
+
updatePhaseStatus?(phaseId: string, status: string): Promise<void>;
|
|
1007
|
+
/** Get the currently active stage for the project. */
|
|
1008
|
+
getActiveStage?(): Promise<Stage | undefined>;
|
|
1009
|
+
/** Create a new horizon (AD-14 hierarchy). Returns the created horizon's ID. */
|
|
1010
|
+
createHorizon?(horizon: {
|
|
1011
|
+
slug: string;
|
|
1012
|
+
label: string;
|
|
1013
|
+
description?: string;
|
|
1014
|
+
status: HorizonStatus;
|
|
1015
|
+
sortOrder: number;
|
|
1016
|
+
}): Promise<string>;
|
|
1017
|
+
/** Create a new stage (AD-14 hierarchy). Returns the created stage's ID. */
|
|
1018
|
+
createStage?(stage: {
|
|
1019
|
+
slug: string;
|
|
1020
|
+
label: string;
|
|
1021
|
+
description?: string;
|
|
1022
|
+
status: StageStatus;
|
|
1023
|
+
sortOrder: number;
|
|
1024
|
+
horizonId: string;
|
|
1025
|
+
}): Promise<string>;
|
|
1026
|
+
/** Link phases to a stage by setting their stage_id. */
|
|
1027
|
+
linkPhasesToStage?(stageId: string): Promise<void>;
|
|
432
1028
|
appendToolMetric(metric: ToolCallMetric): Promise<void>;
|
|
433
1029
|
readToolMetrics(): Promise<ToolCallMetric[]>;
|
|
434
|
-
|
|
435
|
-
|
|
1030
|
+
/** Count tool calls recorded between two ISO timestamps. Optional — pg only. */
|
|
1031
|
+
getToolCallCount?(startedAt: string, completedAt: string): Promise<number>;
|
|
1032
|
+
/**
|
|
1033
|
+
* Cheap existence check for a single milestone tool name. Returns true when
|
|
1034
|
+
* any tool_call_metrics row matches `tool = name`. Replaces full-table reads
|
|
1035
|
+
* for one-shot orient checks (skill scan, TTFV) which previously pulled up
|
|
1036
|
+
* to 5000 rows just to test for one milestone.
|
|
1037
|
+
*/
|
|
1038
|
+
hasToolMilestone?(name: string): Promise<boolean>;
|
|
1039
|
+
getCostSummary(cycleNumber?: number): Promise<CostSummary>;
|
|
436
1040
|
getCostSnapshots(): Promise<CostSnapshot[]>;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
getContextHashes?(
|
|
1041
|
+
appendCycleMetrics(snapshot: CycleMetricsSnapshot): Promise<void>;
|
|
1042
|
+
readCycleMetrics(): Promise<CycleMetricsSnapshot[]>;
|
|
1043
|
+
readCycles(): Promise<Cycle[]>;
|
|
1044
|
+
createCycle(cycle: Cycle): Promise<void>;
|
|
1045
|
+
getContextHashes?(cycleNumber: number): Promise<Record<string, string> | null>;
|
|
442
1046
|
readRegistries(): Promise<Registries>;
|
|
443
1047
|
updateRegistries(registries: Registries): Promise<void>;
|
|
444
1048
|
writeRecommendation(rec: Omit<StrategyRecommendation, 'id'>): Promise<StrategyRecommendation>;
|
|
445
1049
|
getPendingRecommendations(): Promise<StrategyRecommendation[]>;
|
|
446
|
-
actionRecommendation(id: string,
|
|
1050
|
+
actionRecommendation(id: string, cycleNumber: number): Promise<void>;
|
|
1051
|
+
dismissRecommendation?(id: string, reason: string): Promise<void>;
|
|
1052
|
+
/**
|
|
1053
|
+
* Append a topic to the strategy review agenda queue.
|
|
1054
|
+
* Topics surface at the next strategy_review prepare phase and are marked addressed after apply.
|
|
1055
|
+
*/
|
|
1056
|
+
addAgendaTopic?(topic: {
|
|
1057
|
+
topic: string;
|
|
1058
|
+
source: string;
|
|
1059
|
+
sourceCycle?: number;
|
|
1060
|
+
}): Promise<AgendaTopic>;
|
|
1061
|
+
/** List pending (unaddressed) agenda topics for the current project. */
|
|
1062
|
+
getPendingAgendaTopics?(): Promise<AgendaTopic[]>;
|
|
1063
|
+
/** Mark a set of agenda topics as addressed in the given review cycle. */
|
|
1064
|
+
markAgendaTopicsAddressed?(ids: string[], cycleNumber: number): Promise<void>;
|
|
447
1065
|
appendDecisionEvent(event: Omit<DecisionEvent, 'id' | 'createdAt'>): Promise<DecisionEvent>;
|
|
448
1066
|
getDecisionEvents(decisionId: string, limit?: number): Promise<DecisionEvent[]>;
|
|
449
|
-
getDecisionEventsSince(
|
|
1067
|
+
getDecisionEventsSince(cycle: number): Promise<DecisionEvent[]>;
|
|
450
1068
|
writeDecisionScore(score: Omit<DecisionScore, 'id' | 'createdAt' | 'totalScore'>): Promise<DecisionScore>;
|
|
451
1069
|
getDecisionScores(decisionId: string): Promise<DecisionScore[]>;
|
|
452
1070
|
getLatestDecisionScores(): Promise<DecisionScore[]>;
|
|
453
1071
|
logEntityReferences(refs: Omit<EntityReference, 'id' | 'createdAt'>[]): Promise<void>;
|
|
454
|
-
getDecisionUsage(
|
|
1072
|
+
getDecisionUsage(currentCycle: number): Promise<DecisionUsageSummary[]>;
|
|
1073
|
+
/** Get context utilisation summary from v_context_utilisation view. Optional — pg adapter only. */
|
|
1074
|
+
getContextUtilisation?(): Promise<ContextUtilisationSummary[]>;
|
|
455
1075
|
writeStrategyReview(review: StrategyReviewEntry): Promise<void>;
|
|
456
|
-
|
|
457
|
-
getStrategyReviews(limit?: number): Promise<StrategyReviewEntry[]>;
|
|
1076
|
+
getLastStrategyReviewCycle(): Promise<number>;
|
|
1077
|
+
getStrategyReviews(limit?: number, includeFullAnalysis?: boolean): Promise<StrategyReviewEntry[]>;
|
|
1078
|
+
/** Save a strategy review LLM response that failed write-back, for retry next session. */
|
|
1079
|
+
savePendingReviewResponse?(cycleNumber: number, rawResponse: string): Promise<void>;
|
|
1080
|
+
/** Get the pending review response, if any. Returns null if none. */
|
|
1081
|
+
getPendingReviewResponse?(): Promise<{
|
|
1082
|
+
cycleNumber: number;
|
|
1083
|
+
rawResponse: string;
|
|
1084
|
+
} | null>;
|
|
1085
|
+
/** Clear the pending review response after successful retry. */
|
|
1086
|
+
clearPendingReviewResponse?(): Promise<void>;
|
|
1087
|
+
/** Register a document in the doc registry. */
|
|
1088
|
+
registerDoc?(entry: Omit<DocRegistryEntry, 'id' | 'createdAt' | 'updatedAt'>): Promise<DocRegistryEntry>;
|
|
1089
|
+
/** Search documents by filters. */
|
|
1090
|
+
searchDocs?(input: DocSearchInput): Promise<DocRegistryEntry[]>;
|
|
1091
|
+
/** Get a single doc by ID or path. */
|
|
1092
|
+
getDoc?(idOrPath: string): Promise<DocRegistryEntry | null>;
|
|
1093
|
+
/** Update a doc's status (e.g. supersede, archive). */
|
|
1094
|
+
updateDocStatus?(id: string, status: string, supersededBy?: string): Promise<void>;
|
|
1095
|
+
/**
|
|
1096
|
+
* Update a single action on a doc — used by `doc_action_promote` to mark an action
|
|
1097
|
+
* as resolved and link it to the Backlog task that now owns the work.
|
|
1098
|
+
* `actionIndex` is the 0-based index in the doc's `actions` array.
|
|
1099
|
+
*/
|
|
1100
|
+
updateDocAction?(docId: string, actionIndex: number, update: {
|
|
1101
|
+
status?: 'pending' | 'resolved';
|
|
1102
|
+
linkedTaskId?: string;
|
|
1103
|
+
}): Promise<void>;
|
|
1104
|
+
/**
|
|
1105
|
+
* Find every (doc, action) pair whose action references the given task and is still pending.
|
|
1106
|
+
* Used by `submitReview` accept-path to auto-resolve doc actions when their owning task ships
|
|
1107
|
+
* (task-1719). Bounded to 50 results per task — anything beyond is bug-shaped.
|
|
1108
|
+
*/
|
|
1109
|
+
findPendingDocActionsForTask?(taskDisplayId: string): Promise<Array<{
|
|
1110
|
+
docId: string;
|
|
1111
|
+
actionIndex: number;
|
|
1112
|
+
description: string;
|
|
1113
|
+
}>>;
|
|
1114
|
+
writeDogfoodEntries?(entries: DogfoodEntry[]): Promise<void>;
|
|
1115
|
+
getDogfoodLog?(limit?: number): Promise<DogfoodEntry[]>;
|
|
1116
|
+
getUnactionedDogfoodEntries?(limit?: number): Promise<DogfoodEntry[]>;
|
|
1117
|
+
updateDogfoodEntryStatus?(id: string, status: DogfoodEntry['status'], linkedTaskId?: string): Promise<void>;
|
|
1118
|
+
/**
|
|
1119
|
+
* Harness inventory (task-1896). Persists per-project skills/agents/hooks/MCP
|
|
1120
|
+
* tools so the dashboard can surface them. All scoped to the adapter's project.
|
|
1121
|
+
* Optional — the md adapter does not implement these; the sync writer is a
|
|
1122
|
+
* no-op when they are absent.
|
|
1123
|
+
*/
|
|
1124
|
+
getHarnessInventory?(): Promise<HarnessInventoryEntry[]>;
|
|
1125
|
+
/** Replace the entire inventory for this project in one atomic operation. */
|
|
1126
|
+
replaceHarnessInventory?(entries: HarnessInventoryEntry[]): Promise<void>;
|
|
1127
|
+
/** Read the stored change-detection fingerprint, or null if never synced. */
|
|
1128
|
+
getHarnessState?(): Promise<HarnessState | null>;
|
|
1129
|
+
/** Persist the change-detection fingerprint after a successful sync. */
|
|
1130
|
+
setHarnessState?(fingerprint: string): Promise<void>;
|
|
1131
|
+
/** Append structured cycle learning entries. */
|
|
1132
|
+
appendCycleLearnings?(learnings: CycleLearning[]): Promise<void>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Get cycle learnings, optionally filtered by cycle and/or category.
|
|
1135
|
+
* `includeResolved` defaults to false — resolved discovered-issues (resolved_at IS NOT NULL)
|
|
1136
|
+
* are excluded by default so planner / orient reads stay focused on still-open work (task-1541).
|
|
1137
|
+
*/
|
|
1138
|
+
getCycleLearnings?(opts?: {
|
|
1139
|
+
cycleNumber?: number;
|
|
1140
|
+
category?: string;
|
|
1141
|
+
limit?: number;
|
|
1142
|
+
includeResolved?: boolean;
|
|
1143
|
+
}): Promise<CycleLearning[]>;
|
|
1144
|
+
/** Get cross-cycle patterns from learning tags (tags appearing in 2+ cycles). */
|
|
1145
|
+
getCycleLearningPatterns?(): Promise<CycleLearningPattern[]>;
|
|
1146
|
+
/** Set action_ref on a cycle learning to link it to the task that acted on it. */
|
|
1147
|
+
updateCycleLearningActionRef?(learningId: string, taskDisplayId: string): Promise<void>;
|
|
1148
|
+
/**
|
|
1149
|
+
* Mark a cycle learning resolved. Sets resolved_at = NOW() and (optionally) resolved_by.
|
|
1150
|
+
* Pg-only — md / proxy adapters can leave this unimplemented. (task-1541)
|
|
1151
|
+
*/
|
|
1152
|
+
markCycleLearningResolved?(learningId: string, resolvedBy?: string): Promise<void>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Auto-resolve discovered-issues (category='issue') whose linked task is Done/Cancelled,
|
|
1155
|
+
* draining the stale-issue clog so orient/planner reads stay clean (task-2079, C291).
|
|
1156
|
+
* Pass a task display_id to resolve only that task's issues (task→Done transition path);
|
|
1157
|
+
* omit for a full sweep. Restricted to category='issue'. Pg-only; returns rows resolved.
|
|
1158
|
+
*/
|
|
1159
|
+
resolveLearningsForDoneTasks?(taskDisplayId?: string): Promise<number>;
|
|
1160
|
+
/**
|
|
1161
|
+
* Optional: return the current (unsuperseded) North Star statement.
|
|
1162
|
+
* When implemented, plan and strategy_review use this instead of relying
|
|
1163
|
+
* on the North Star embedded in PLANNING_LOG.md (which may be stale).
|
|
1164
|
+
*/
|
|
1165
|
+
getCurrentNorthStar?(): Promise<string | null>;
|
|
1166
|
+
/**
|
|
1167
|
+
* Optional: return the cycle number when the current North Star was set.
|
|
1168
|
+
* Used for drift detection — flags when North Star hasn't been validated in 10+ cycles.
|
|
1169
|
+
*/
|
|
1170
|
+
getNorthStarSetCycle?(): Promise<number | null>;
|
|
1171
|
+
/**
|
|
1172
|
+
* Optional: return both cycle number and set_at date for the current North Star.
|
|
1173
|
+
* Used for hybrid drift detection — warns only when both cycle gap AND time gap exceed thresholds.
|
|
1174
|
+
*/
|
|
1175
|
+
getNorthStarStaleness?(): Promise<{
|
|
1176
|
+
setCycle: number;
|
|
1177
|
+
setAt: string;
|
|
1178
|
+
} | null>;
|
|
1179
|
+
/**
|
|
1180
|
+
* Optional: persist a new North Star statement, superseding the previous active one.
|
|
1181
|
+
* Called by strategy_review apply and strategy_change apply when the LLM outputs a northStar field.
|
|
1182
|
+
*/
|
|
1183
|
+
upsertNorthStar?(statement: string, cycleNumber: number): Promise<void>;
|
|
1184
|
+
/**
|
|
1185
|
+
* Optional: return aggregated estimation calibration data from v_estimation_accuracy.
|
|
1186
|
+
* Used by the planner to adjust effort estimates based on historical patterns.
|
|
1187
|
+
*/
|
|
1188
|
+
getEstimationCalibration?(): Promise<EstimationCalibrationRow[]>;
|
|
1189
|
+
/**
|
|
1190
|
+
* Optional: return per-module estimation accuracy stats from the last 20 cycles.
|
|
1191
|
+
* Joins build_reports with cycle_tasks on task_id. pg adapter only.
|
|
1192
|
+
*/
|
|
1193
|
+
getModuleEstimationStats?(): Promise<ModuleEstimationRow[]>;
|
|
458
1194
|
/**
|
|
459
1195
|
* Optional: return recent task comments for plan context.
|
|
460
1196
|
* Returns up to `limit` comments across all active tasks, newest first.
|
|
@@ -465,6 +1201,11 @@ interface PapiAdapter {
|
|
|
465
1201
|
content: string;
|
|
466
1202
|
createdAt: string;
|
|
467
1203
|
}[]>;
|
|
1204
|
+
/**
|
|
1205
|
+
* Optional: return recommendation effectiveness data from v_recommendation_effectiveness.
|
|
1206
|
+
* Used by strategy review to assess whether past recommendations were followed.
|
|
1207
|
+
*/
|
|
1208
|
+
getRecommendationEffectiveness?(): Promise<RecommendationEffectivenessRow[]>;
|
|
468
1209
|
/**
|
|
469
1210
|
* Optional: return a lean pre-formatted plan context summary.
|
|
470
1211
|
* When implemented (e.g. by pg adapter with SQL aggregates), assembleContext
|
|
@@ -472,6 +1213,163 @@ interface PapiAdapter {
|
|
|
472
1213
|
* Return undefined to fall back to the default assembly path.
|
|
473
1214
|
*/
|
|
474
1215
|
getPlanContextSummary?(): Promise<PlanContextSummary | undefined>;
|
|
1216
|
+
/**
|
|
1217
|
+
* Optional: check if the project exists in the data store.
|
|
1218
|
+
* Returns true if the project is found, false otherwise.
|
|
1219
|
+
* When not implemented, defaults to true (assumes project exists).
|
|
1220
|
+
*/
|
|
1221
|
+
projectExists?(): Promise<boolean>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Optional: fetch the project name, slug, papi_dir, and repo_url for connection + path-identity verification.
|
|
1224
|
+
* `papi_dir` is the absolute path of the project's `.papi/` directory as stored in the database.
|
|
1225
|
+
* Used by the path-identity guardrail to detect cwd↔stored-path mismatches.
|
|
1226
|
+
* `repo_url` (task-1979, C279) is the GitHub URL the project is associated with, used by the
|
|
1227
|
+
* release tool's remote-project guard. Optional in the result so adapters that don't expose it
|
|
1228
|
+
* can return null without breaking legacy callers.
|
|
1229
|
+
*/
|
|
1230
|
+
getProjectInfo?(): Promise<{
|
|
1231
|
+
name: string;
|
|
1232
|
+
slug: string;
|
|
1233
|
+
papi_dir?: string | null;
|
|
1234
|
+
repo_url?: string | null;
|
|
1235
|
+
} | null>;
|
|
1236
|
+
/**
|
|
1237
|
+
* Optional: persist a new value for the project's papi_dir column. Used by the path-identity
|
|
1238
|
+
* guardrail when backfilling legacy null values or applying PAPI_ALLOW_PATH_MIGRATE updates.
|
|
1239
|
+
*/
|
|
1240
|
+
setProjectPapiDir?(papiDir: string): Promise<void>;
|
|
1241
|
+
/**
|
|
1242
|
+
* Optional: resolve the user_id that owns the currently-bound project.
|
|
1243
|
+
* Returns null for legacy pre-multi-user projects whose row was created before the
|
|
1244
|
+
* user_id column existed. Used by verifyProject's detect-only legacy-project probe
|
|
1245
|
+
* (task-1621). pg-only — md/proxy adapters can leave it unimplemented.
|
|
1246
|
+
*/
|
|
1247
|
+
getProjectOwnerUserId?(): Promise<string | null>;
|
|
1248
|
+
/**
|
|
1249
|
+
* Optional (task-2052, C288): resolve BOTH sides of the owner-gate identity in
|
|
1250
|
+
* one call — who is calling, and who owns the project. On the proxy adapter the
|
|
1251
|
+
* edge function derives callerUserId from the bearer token server-side, so a
|
|
1252
|
+
* hosted/proxy owner is recognised without needing PAPI_USER_ID configured
|
|
1253
|
+
* locally (and a non-owner cannot claim ownership by setting it). Adapters that
|
|
1254
|
+
* cannot resolve the caller (pg/md, where identity comes from local config)
|
|
1255
|
+
* leave this unimplemented and the gate falls back to
|
|
1256
|
+
* getProjectOwnerUserId + config.userId. Consumed by resolveOwnerGate in
|
|
1257
|
+
* packages/server/src/lib/owner-identity.ts.
|
|
1258
|
+
*/
|
|
1259
|
+
getOwnerIdentity?(): Promise<OwnerIdentity>;
|
|
1260
|
+
/**
|
|
1261
|
+
* task-2029 (C288): contributor cohort management on the project_contributors
|
|
1262
|
+
* table (MVP slice — current schema, no roles/invites; that's MU-2/task-2070).
|
|
1263
|
+
* Email resolution happens adapter-side (pg: user_profiles join; proxy: edge
|
|
1264
|
+
* function) so the tool layer never touches identity tables directly. The
|
|
1265
|
+
* OWNER-ONLY rule is enforced in the tool layer via resolveOwnerGate AND
|
|
1266
|
+
* (proxy) server-side in the edge function — defence in depth, because the
|
|
1267
|
+
* npm server runs on the user's machine. pg/proxy only; md leaves these
|
|
1268
|
+
* unimplemented (no cohort concept in local single-user mode).
|
|
1269
|
+
*/
|
|
1270
|
+
listContributors?(): Promise<ContributorEntry[]>;
|
|
1271
|
+
addContributorByEmail?(email: string): Promise<ContributorEntry>;
|
|
1272
|
+
removeContributorByEmail?(email: string): Promise<boolean>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Optional (task-1888 / 1885-C): list all projects the authenticated user owns.
|
|
1275
|
+
* Scopes to the auth user (proxy: bearer; pg: the bound project's user_id). Used by the
|
|
1276
|
+
* project_list MCP tool so a user on one API key across many folders can see and select
|
|
1277
|
+
* the right project from the LLM.
|
|
1278
|
+
*/
|
|
1279
|
+
listUserProjects?(): Promise<ProjectSummary[]>;
|
|
1280
|
+
/**
|
|
1281
|
+
* Optional (task-1888 / 1885-C): create a project for the authenticated user, idempotent on
|
|
1282
|
+
* papi_dir then name — re-running in the same workspace (or with the same name) returns the
|
|
1283
|
+
* EXISTING project instead of creating a duplicate (fixes the SUP-2026-013 duplicate-project
|
|
1284
|
+
* bug). NO auto-plan / NO seeded backlog — an empty project only. `papiDir` is omitted on the
|
|
1285
|
+
* stateless remote transport (no real workspace there).
|
|
1286
|
+
*/
|
|
1287
|
+
createUserProject?(input: {
|
|
1288
|
+
name: string;
|
|
1289
|
+
papiDir?: string;
|
|
1290
|
+
repoUrl?: string;
|
|
1291
|
+
}): Promise<ProjectLifecycleResult>;
|
|
1292
|
+
/**
|
|
1293
|
+
* Optional (task-1888 / 1885-C): resolve a project the user owns by id or slug and (when a
|
|
1294
|
+
* workspace signal is available) stamp it as the papi_dir for the current folder. Callable from
|
|
1295
|
+
* the LLM ("switch to golf"). Fails closed if the identifier does not resolve to a project the
|
|
1296
|
+
* auth user owns.
|
|
1297
|
+
*/
|
|
1298
|
+
switchUserProject?(identifier: string, papiDir?: string): Promise<ProjectLifecycleResult>;
|
|
1299
|
+
/**
|
|
1300
|
+
* Optional (task-2119): return a view of this adapter scoped to a DIFFERENT
|
|
1301
|
+
* project for a single call, without rebinding the session adapter (unlike
|
|
1302
|
+
* switchUserProject) and without persisting anything. Callers MUST validate
|
|
1303
|
+
* the target project belongs to the auth user first (listUserProjects) —
|
|
1304
|
+
* this method does not gate ownership itself.
|
|
1305
|
+
*/
|
|
1306
|
+
withProject?(projectId: string): PapiAdapter;
|
|
1307
|
+
/** Optional: insert a plan run record for telemetry. Non-blocking — callers should catch errors. */
|
|
1308
|
+
insertPlanRun?(entry: PlanRunEntry): Promise<void>;
|
|
1309
|
+
/** Submit a bug report with diagnostics for cross-project visibility. */
|
|
1310
|
+
submitBugReport?(report: Omit<BugReport, 'id' | 'createdAt'>): Promise<BugReport>;
|
|
1311
|
+
/**
|
|
1312
|
+
* Optional (task-2061): the authenticated user's tier + metered tool-call
|
|
1313
|
+
* count for the current month. Only the proxy adapter implements this —
|
|
1314
|
+
* its identity is server-derived from the bearer. Local adapters (pg/md)
|
|
1315
|
+
* deliberately omit it, so local sessions are never metered or blocked.
|
|
1316
|
+
*/
|
|
1317
|
+
getMeteredUsage?(): Promise<{
|
|
1318
|
+
tier: string;
|
|
1319
|
+
monthlyToolCalls: number;
|
|
1320
|
+
}>;
|
|
1321
|
+
}
|
|
1322
|
+
/** A project the auth user owns — returned by listUserProjects (task-1888 / 1885-C). */
|
|
1323
|
+
/**
|
|
1324
|
+
* task-2052 (C288): both sides of the owner-gate identity. callerUserId is the
|
|
1325
|
+
* authenticated caller (proxy: bearer-derived server-side; null when the
|
|
1326
|
+
* transport cannot resolve a caller); ownerUserId is the project's owner row.
|
|
1327
|
+
*/
|
|
1328
|
+
interface OwnerIdentity {
|
|
1329
|
+
callerUserId: string | null;
|
|
1330
|
+
ownerUserId: string | null;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* task-2029 (C288): one row of a project's contributor cohort
|
|
1334
|
+
* (project_contributors joined to user_profiles for the human-readable bits).
|
|
1335
|
+
*/
|
|
1336
|
+
interface ContributorEntry {
|
|
1337
|
+
userId: string;
|
|
1338
|
+
email: string | null;
|
|
1339
|
+
displayName: string | null;
|
|
1340
|
+
role: string;
|
|
1341
|
+
createdAt: string;
|
|
1342
|
+
}
|
|
1343
|
+
interface ProjectSummary {
|
|
1344
|
+
id: string;
|
|
1345
|
+
name: string;
|
|
1346
|
+
slug: string;
|
|
1347
|
+
papi_dir?: string | null;
|
|
1348
|
+
}
|
|
1349
|
+
/** Result of project_create / project_switch (task-1888 / 1885-C). */
|
|
1350
|
+
interface ProjectLifecycleResult {
|
|
1351
|
+
projectId: string;
|
|
1352
|
+
name: string;
|
|
1353
|
+
slug: string;
|
|
1354
|
+
papiDir?: string | null;
|
|
1355
|
+
/** True when a new project row was created; false when an existing one was returned (idempotent). */
|
|
1356
|
+
created: boolean;
|
|
1357
|
+
}
|
|
1358
|
+
/** Plan quality telemetry — one row per plan apply. */
|
|
1359
|
+
interface PlanRunEntry {
|
|
1360
|
+
cycleNumber: number;
|
|
1361
|
+
contextBytes?: number;
|
|
1362
|
+
durationMs?: number;
|
|
1363
|
+
taskCountIn?: number;
|
|
1364
|
+
taskCountOut?: number;
|
|
1365
|
+
backlogDepth?: number;
|
|
1366
|
+
notes?: string;
|
|
1367
|
+
/** Context utilisation ratio (0-1) and other token metrics captured at apply time. */
|
|
1368
|
+
tokenUsage?: {
|
|
1369
|
+
utilisation?: number;
|
|
1370
|
+
};
|
|
1371
|
+
/** Origin of this plan run: "mcp-server" (default) or "dashboard". */
|
|
1372
|
+
source?: string;
|
|
475
1373
|
}
|
|
476
1374
|
/** Lean plan context returned by adapters that support SQL aggregation. */
|
|
477
1375
|
interface PlanContextSummary {
|
|
@@ -479,25 +1377,25 @@ interface PlanContextSummary {
|
|
|
479
1377
|
board: string;
|
|
480
1378
|
/** Pre-computed build intelligence: accuracy %, velocity trend, top surprises. */
|
|
481
1379
|
buildIntelligence: string;
|
|
482
|
-
/** Last 3
|
|
483
|
-
|
|
1380
|
+
/** Last 3 cycle entries with carry-forward. */
|
|
1381
|
+
cycleLog: string;
|
|
484
1382
|
/** One-liner per active decision: id, title, confidence. */
|
|
485
1383
|
activeDecisions: string;
|
|
486
1384
|
}
|
|
487
1385
|
/** Everything the plan write-back needs to persist in a single transaction. */
|
|
488
1386
|
interface PlanWriteBackPayload {
|
|
489
|
-
/** The NEW
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
|
|
1387
|
+
/** The NEW cycle number (current + 1). */
|
|
1388
|
+
cycleNumber: number;
|
|
1389
|
+
/** Cycle log entry to upsert. */
|
|
1390
|
+
cycleLog: CycleLogEntry;
|
|
493
1391
|
/** Health updates: boardHealth, strategicDirection, etc. */
|
|
494
|
-
healthUpdates: Partial<
|
|
1392
|
+
healthUpdates: Partial<CycleHealth>;
|
|
495
1393
|
/** New tasks to create (already deduplicated by plan service). */
|
|
496
|
-
newTasks: Array<Omit<
|
|
1394
|
+
newTasks: Array<Omit<CycleTask, 'id' | 'uuid' | 'displayId'>>;
|
|
497
1395
|
/** Board corrections: taskId + partial updates. */
|
|
498
1396
|
boardCorrections: Array<{
|
|
499
1397
|
taskId: string;
|
|
500
|
-
updates: Partial<Omit<
|
|
1398
|
+
updates: Partial<Omit<CycleTask, 'id'>>;
|
|
501
1399
|
}>;
|
|
502
1400
|
/** Phases parsed from product brief update. Empty array = no phase changes. */
|
|
503
1401
|
phases: Phase[];
|
|
@@ -513,10 +1411,8 @@ interface PlanWriteBackPayload {
|
|
|
513
1411
|
taskId: string;
|
|
514
1412
|
handoff: BuildHandoff;
|
|
515
1413
|
}>;
|
|
516
|
-
/**
|
|
517
|
-
|
|
518
|
-
/** Whether to run feature sync from phases. */
|
|
519
|
-
featureSync: boolean;
|
|
1414
|
+
/** Cycle entity to create. */
|
|
1415
|
+
cycle: Cycle;
|
|
520
1416
|
/** IDs of tasks whose reviewed status should be checked before allowing priority changes. */
|
|
521
1417
|
reviewedTaskIds: string[];
|
|
522
1418
|
}
|
|
@@ -540,33 +1436,40 @@ declare class MdFileAdapter implements PapiAdapter {
|
|
|
540
1436
|
private read;
|
|
541
1437
|
/** Write UTF-8 text to a .papi/ file. */
|
|
542
1438
|
private write;
|
|
543
|
-
/** Parse the full planning context into structured sections (reads from PLANNING_LOG.md + ACTIVE_DECISIONS.md +
|
|
1439
|
+
/** Parse the full planning context into structured sections (reads from PLANNING_LOG.md + ACTIVE_DECISIONS.md + CYCLE_LOG.md). */
|
|
544
1440
|
readPlanningLog(): Promise<PlanningLog>;
|
|
545
|
-
/** Read the
|
|
546
|
-
|
|
547
|
-
/**
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
/**
|
|
1441
|
+
/** Read the Cycle Health table from PLANNING_LOG.md. */
|
|
1442
|
+
getCycleHealth(): Promise<CycleHealth>;
|
|
1443
|
+
/**
|
|
1444
|
+
* Read Active Decisions from ACTIVE_DECISIONS.md.
|
|
1445
|
+
*
|
|
1446
|
+
* Default filters out retired ADs (outcome ∈ abandoned/superseded/resolved or superseded=true).
|
|
1447
|
+
* Pass { includeRetired: true } for management/triage surfaces. See PapiAdapter docstring.
|
|
1448
|
+
*/
|
|
1449
|
+
getActiveDecisions(options?: {
|
|
1450
|
+
includeRetired?: boolean;
|
|
1451
|
+
}): Promise<ActiveDecision[]>;
|
|
1452
|
+
/** Read cycle log entries (newest first), optionally limited to {@link limit} entries. */
|
|
1453
|
+
getCycleLog(limit?: number): Promise<CycleLogEntry[]>;
|
|
1454
|
+
getCycleLogSince(cycleNumber: number): Promise<CycleLogEntry[]>;
|
|
1455
|
+
/** Merge partial updates into the Cycle Health table and write back. */
|
|
1456
|
+
setCycleHealth(updates: Partial<CycleHealth>): Promise<void>;
|
|
1457
|
+
/** Prepend a new cycle log entry at the top of the Cycle Log section. */
|
|
1458
|
+
writeCycleLogEntry(entry: CycleLogEntry): Promise<void>;
|
|
1459
|
+
/** Write a strategy review — for md adapter, delegates to cycle log. */
|
|
557
1460
|
writeStrategyReview(review: StrategyReviewEntry): Promise<void>;
|
|
558
|
-
/** Get the
|
|
559
|
-
|
|
560
|
-
/** Get strategy reviews — md adapter returns empty (reviews live in
|
|
561
|
-
getStrategyReviews(_limit?: number): Promise<StrategyReviewEntry[]>;
|
|
1461
|
+
/** Get the cycle number of the last strategy review. */
|
|
1462
|
+
getLastStrategyReviewCycle(): Promise<number>;
|
|
1463
|
+
/** Get strategy reviews — md adapter returns empty (reviews live in cycle log). */
|
|
1464
|
+
getStrategyReviews(_limit?: number, _includeFullAnalysis?: boolean): Promise<StrategyReviewEntry[]>;
|
|
562
1465
|
/** Update or insert an Active Decision block by ID. */
|
|
563
|
-
updateActiveDecision(id: string, body: string,
|
|
564
|
-
/** Query the
|
|
565
|
-
queryBoard(options?: BoardQueryOptions): Promise<
|
|
1466
|
+
updateActiveDecision(id: string, body: string, cycleNumber?: number, _action?: string): Promise<void>;
|
|
1467
|
+
/** Query the cycle board, optionally filtering by status/priority/phase/etc. */
|
|
1468
|
+
queryBoard(options?: BoardQueryOptions): Promise<CycleTask[]>;
|
|
566
1469
|
/** Look up a single task by ID, returning null if not found. */
|
|
567
|
-
getTask(id: string): Promise<
|
|
1470
|
+
getTask(id: string): Promise<CycleTask | null>;
|
|
568
1471
|
/** Look up multiple tasks by ID in a single board read. */
|
|
569
|
-
getTasks(ids: string[]): Promise<
|
|
1472
|
+
getTasks(ids: string[]): Promise<CycleTask[]>;
|
|
570
1473
|
/** Warn if a phase name doesn't match any known phase label from PRODUCT_BRIEF.md. */
|
|
571
1474
|
private warnInvalidPhase;
|
|
572
1475
|
/** Warn if a module name doesn't match any registered module in REGISTRIES.md. */
|
|
@@ -574,32 +1477,61 @@ declare class MdFileAdapter implements PapiAdapter {
|
|
|
574
1477
|
/** Warn if an epic name doesn't match any registered epic in REGISTRIES.md. */
|
|
575
1478
|
private warnInvalidEpic;
|
|
576
1479
|
/** Create a new task on the board with an auto-generated sequential ID. */
|
|
577
|
-
createTask(task: Omit<
|
|
1480
|
+
createTask(task: Omit<CycleTask, 'id'>): Promise<CycleTask>;
|
|
578
1481
|
/** Update one or more fields on an existing task. Throws if the task ID is not found. */
|
|
579
|
-
updateTask(id: string, updates: Partial<Omit<
|
|
1482
|
+
updateTask(id: string, updates: Partial<Omit<CycleTask, 'id'>>, options?: UpdateTaskOptions): Promise<void>;
|
|
580
1483
|
/** Shorthand to update only the status field of a task. */
|
|
581
1484
|
updateTaskStatus(id: string, status: TaskStatus): Promise<void>;
|
|
1485
|
+
/**
|
|
1486
|
+
* task-1763 (C293): atomic compare-and-swap task claim. First-claim-wins —
|
|
1487
|
+
* sets assigneeId only if the task is currently unclaimed. The markdown adapter
|
|
1488
|
+
* is single-process, so the read-check-write is trivially atomic here; the real
|
|
1489
|
+
* concurrency guarantee lives in the pg adapter's RETURNING CAS. Returns the
|
|
1490
|
+
* claimed task, or null if it was already claimed or does not exist.
|
|
1491
|
+
*
|
|
1492
|
+
* task-2071 (MU-3): the pooled-task invariant is `assigneeId == null && cycle
|
|
1493
|
+
* == null` — a task already pulled into someone's cycle is NOT in the pool and
|
|
1494
|
+
* cannot be claimed. Sets claimSource='pool' on success.
|
|
1495
|
+
*/
|
|
1496
|
+
claimTask(taskId: string, assigneeId: string): Promise<CycleTask | null>;
|
|
1497
|
+
/**
|
|
1498
|
+
* task-2071 (C293, MU-3): claimer-only release. Clears assigneeId + claimSource
|
|
1499
|
+
* only if the task is currently assigned to `assigneeId` and has not entered
|
|
1500
|
+
* review. Returns the unclaimed task, or null if the caller is not the claimer,
|
|
1501
|
+
* the task has progressed, or it does not exist.
|
|
1502
|
+
*/
|
|
1503
|
+
unclaimTask(taskId: string, assigneeId: string): Promise<CycleTask | null>;
|
|
1504
|
+
/**
|
|
1505
|
+
* task-2072 (C293, MU-4): atomic review claim. Sets reviewerId only if the task
|
|
1506
|
+
* is In Review and not yet claimed for review (reviewerId == null). First-claim-
|
|
1507
|
+
* wins. Returns the claimed task, or null if already review-claimed / not In
|
|
1508
|
+
* Review / missing.
|
|
1509
|
+
*/
|
|
1510
|
+
claimReview(taskId: string, reviewerId: string): Promise<CycleTask | null>;
|
|
1511
|
+
recordTransition(_taskId: string, _fromStatus: string, _toStatus: string, _changedBy?: string): Promise<void>;
|
|
582
1512
|
/** Insert a new build report at the top of BUILD_REPORTS.md. */
|
|
583
1513
|
appendBuildReport(report: BuildReport): Promise<void>;
|
|
584
1514
|
/** Return the most recent {@link count} build reports. */
|
|
585
1515
|
getRecentBuildReports(count: number): Promise<BuildReport[]>;
|
|
586
|
-
/** Return
|
|
587
|
-
|
|
1516
|
+
/** Return the number of build reports for a specific task. */
|
|
1517
|
+
getBuildReportCountForTask(taskId: string): Promise<number>;
|
|
1518
|
+
/** Return all build reports from cycles >= {@link cycleNumber}. */
|
|
1519
|
+
getBuildReportsSince(cycleNumber: number): Promise<BuildReport[]>;
|
|
588
1520
|
/** Return recent human reviews from REVIEWS.md (newest first), optionally limited to {@link count}. */
|
|
589
1521
|
getRecentReviews(count?: number): Promise<HumanReview[]>;
|
|
590
1522
|
/** Write a new human review to REVIEWS.md. */
|
|
591
1523
|
writeReview(review: HumanReview): Promise<void>;
|
|
592
|
-
/** Compress old
|
|
593
|
-
|
|
1524
|
+
/** Compress old cycle log entries below {@link threshold} into a summary block. */
|
|
1525
|
+
compressCycleLog(threshold: number, summary: string): Promise<void>;
|
|
594
1526
|
/** Compress old build reports below {@link threshold} into a summary block. */
|
|
595
1527
|
compressBuildReports(threshold: number, summary: string): Promise<void>;
|
|
596
1528
|
/** Read a .papi/ file, returning empty string if it doesn't exist. */
|
|
597
1529
|
private readOptional;
|
|
598
1530
|
/** Strip build_handoff and build_report from a task before archiving — these are already in BUILD_REPORTS.md. */
|
|
599
1531
|
private stripHeavyFields;
|
|
600
|
-
/** Append tasks to
|
|
1532
|
+
/** Append tasks to ARCHIVE_CYCLE_BOARD.md, stripping heavy fields and deduplicating by ID. */
|
|
601
1533
|
private appendToArchive;
|
|
602
|
-
/** Archive tasks matching phases and/or statuses to
|
|
1534
|
+
/** Archive tasks matching phases and/or statuses to ARCHIVE_CYCLE_BOARD.md and remove them from active board. */
|
|
603
1535
|
archiveTasks(phases: string[], statuses?: string[]): Promise<{
|
|
604
1536
|
archivedCount: number;
|
|
605
1537
|
taskIds: string[];
|
|
@@ -608,38 +1540,29 @@ declare class MdFileAdapter implements PapiAdapter {
|
|
|
608
1540
|
readProductBrief(): Promise<string>;
|
|
609
1541
|
/** Overwrite PRODUCT_BRIEF.md with new content. */
|
|
610
1542
|
updateProductBrief(content: string): Promise<void>;
|
|
1543
|
+
readDiscoveryCanvas(): Promise<DiscoveryCanvas>;
|
|
1544
|
+
updateDiscoveryCanvas(_canvas: Partial<DiscoveryCanvas>): Promise<void>;
|
|
611
1545
|
/** Read all phases from PHASES.md (falls back to PRODUCT_BRIEF.md for migration). */
|
|
612
1546
|
readPhases(): Promise<Phase[]>;
|
|
613
1547
|
/** Write phases to PHASES.md. */
|
|
614
1548
|
writePhases(phases: Phase[]): Promise<void>;
|
|
615
|
-
/** Read all features from FEATURES.md. */
|
|
616
|
-
readFeatures(): Promise<Feature[]>;
|
|
617
|
-
/** Get a single feature by UUID. */
|
|
618
|
-
getFeature(id: string): Promise<Feature | null>;
|
|
619
|
-
/** Create a new feature and append it to FEATURES.md. */
|
|
620
|
-
createFeature(feature: Omit<Feature, 'id'>): Promise<Feature>;
|
|
621
|
-
/** Update an existing feature by UUID. */
|
|
622
|
-
updateFeature(id: string, updates: Partial<Omit<Feature, 'id'>>): Promise<void>;
|
|
623
|
-
/** Write all features to FEATURES.md. */
|
|
624
|
-
private writeFeatures;
|
|
625
1549
|
/** Append a tool call metric entry to METRICS.md. */
|
|
626
1550
|
appendToolMetric(metric: ToolCallMetric): Promise<void>;
|
|
627
1551
|
/** Read all tool call metrics from METRICS.md. */
|
|
628
1552
|
readToolMetrics(): Promise<ToolCallMetric[]>;
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
writeCostSnapshot(snapshot: CostSnapshot): Promise<void>;
|
|
1553
|
+
hasToolMilestone(name: string): Promise<boolean>;
|
|
1554
|
+
/** Aggregate tool call metrics into a cost summary, optionally filtered by cycle. */
|
|
1555
|
+
getCostSummary(cycleNumber?: number): Promise<CostSummary>;
|
|
633
1556
|
/** Read all cost snapshots from the Cost Summary section of METRICS.md. */
|
|
634
1557
|
getCostSnapshots(): Promise<CostSnapshot[]>;
|
|
635
|
-
/** Append a
|
|
636
|
-
|
|
637
|
-
/** Read all
|
|
638
|
-
|
|
639
|
-
/** Read all
|
|
640
|
-
|
|
641
|
-
/** Write a new
|
|
642
|
-
|
|
1558
|
+
/** Append a cycle metrics snapshot to CYCLE_METRICS.md. */
|
|
1559
|
+
appendCycleMetrics(snapshot: CycleMetricsSnapshot): Promise<void>;
|
|
1560
|
+
/** Read all cycle metrics snapshots from CYCLE_METRICS.md. */
|
|
1561
|
+
readCycleMetrics(): Promise<CycleMetricsSnapshot[]>;
|
|
1562
|
+
/** Read all Cycle entities from CYCLES.md (newest first). */
|
|
1563
|
+
readCycles(): Promise<Cycle[]>;
|
|
1564
|
+
/** Write a new Cycle entity to CYCLES.md. */
|
|
1565
|
+
createCycle(cycle: Cycle): Promise<void>;
|
|
643
1566
|
/** Read module and epic registries from REGISTRIES.md. */
|
|
644
1567
|
readRegistries(): Promise<Registries>;
|
|
645
1568
|
/** Overwrite REGISTRIES.md with updated registries. */
|
|
@@ -652,17 +1575,31 @@ declare class MdFileAdapter implements PapiAdapter {
|
|
|
652
1575
|
/** Read all pending (unactioned) strategy recommendations. */
|
|
653
1576
|
getPendingRecommendations(): Promise<StrategyRecommendation[]>;
|
|
654
1577
|
/** Mark a recommendation as actioned. */
|
|
655
|
-
actionRecommendation(id: string,
|
|
1578
|
+
actionRecommendation(id: string, cycleNumber: number): Promise<void>;
|
|
1579
|
+
addAgendaTopic(input: {
|
|
1580
|
+
topic: string;
|
|
1581
|
+
source: string;
|
|
1582
|
+
sourceCycle?: number;
|
|
1583
|
+
}): Promise<AgendaTopic>;
|
|
1584
|
+
getPendingAgendaTopics(): Promise<AgendaTopic[]>;
|
|
1585
|
+
markAgendaTopicsAddressed(ids: string[], cycleNumber: number): Promise<void>;
|
|
656
1586
|
appendDecisionEvent(event: Omit<DecisionEvent, 'id' | 'createdAt'>): Promise<DecisionEvent>;
|
|
657
1587
|
getDecisionEvents(decisionId: string, limit?: number): Promise<DecisionEvent[]>;
|
|
658
|
-
getDecisionEventsSince(
|
|
1588
|
+
getDecisionEventsSince(cycle: number): Promise<DecisionEvent[]>;
|
|
659
1589
|
private parseDecisionEvents;
|
|
660
1590
|
writeDecisionScore(score: Omit<DecisionScore, 'id' | 'createdAt' | 'totalScore'>): Promise<DecisionScore>;
|
|
661
1591
|
getDecisionScores(decisionId: string): Promise<DecisionScore[]>;
|
|
662
1592
|
getLatestDecisionScores(): Promise<DecisionScore[]>;
|
|
663
1593
|
private parseDecisionScores;
|
|
664
1594
|
logEntityReferences(_refs: Omit<EntityReference, 'id' | 'createdAt'>[]): Promise<void>;
|
|
665
|
-
getDecisionUsage(
|
|
1595
|
+
getDecisionUsage(_currentCycle: number): Promise<DecisionUsageSummary[]>;
|
|
1596
|
+
getCurrentNorthStar(): Promise<string | null>;
|
|
1597
|
+
getNorthStarSetCycle(): Promise<number | null>;
|
|
1598
|
+
getNorthStarStaleness(): Promise<{
|
|
1599
|
+
setCycle: number;
|
|
1600
|
+
setAt: string;
|
|
1601
|
+
} | null>;
|
|
1602
|
+
upsertNorthStar(statement: string, _cycleNumber: number): Promise<void>;
|
|
666
1603
|
}
|
|
667
1604
|
|
|
668
1605
|
/** Validate and normalise an effort string to EffortSize. Returns the value or undefined if invalid. */
|
|
@@ -674,12 +1611,12 @@ declare function parseEffortSize(value: string): EffortSize | undefined;
|
|
|
674
1611
|
*/
|
|
675
1612
|
declare function parseBuildHandoff(markdown: string): BuildHandoff | null;
|
|
676
1613
|
/** Serialize a BuildHandoff object back into the standard markdown format. */
|
|
677
|
-
declare function serializeBuildHandoff(
|
|
1614
|
+
declare function serializeBuildHandoff(raw: BuildHandoff | string): string;
|
|
678
1615
|
|
|
679
|
-
/** Calculate Tier 1
|
|
680
|
-
declare function
|
|
681
|
-
accuracy:
|
|
682
|
-
velocity:
|
|
1616
|
+
/** Calculate Tier 1 cycle metrics from build reports. */
|
|
1617
|
+
declare function calculateCycleMetrics(reports: BuildReport[], currentCycle: number, window?: number): {
|
|
1618
|
+
accuracy: CycleEstimationAccuracy[];
|
|
1619
|
+
velocity: CycleVelocity[];
|
|
683
1620
|
};
|
|
684
1621
|
/**
|
|
685
1622
|
* Detect recurring patterns across build reports.
|
|
@@ -687,7 +1624,7 @@ declare function calculateSprintMetrics(reports: BuildReport[], currentSprint: n
|
|
|
687
1624
|
* When a TextClusterer is provided, uses LLM-based semantic clustering for surprises
|
|
688
1625
|
* instead of normalised string matching.
|
|
689
1626
|
*/
|
|
690
|
-
declare function detectBuildPatterns(reports: BuildReport[],
|
|
1627
|
+
declare function detectBuildPatterns(reports: BuildReport[], currentCycle: number, window?: number, clusterer?: TextClusterer): Promise<BuildPatterns>;
|
|
691
1628
|
/** Returns true if the patterns contain any actionable findings. */
|
|
692
1629
|
declare function hasBuildPatterns(patterns: BuildPatterns): boolean;
|
|
693
1630
|
|
|
@@ -704,7 +1641,7 @@ declare function prependReview(review: HumanReview, content: string): string;
|
|
|
704
1641
|
* When a TextClusterer is provided, uses LLM-based semantic clustering for feedback
|
|
705
1642
|
* instead of normalised string matching.
|
|
706
1643
|
*/
|
|
707
|
-
declare function detectReviewPatterns(reviews: HumanReview[],
|
|
1644
|
+
declare function detectReviewPatterns(reviews: HumanReview[], currentCycle: number, window?: number, clusterer?: TextClusterer): Promise<ReviewPatterns>;
|
|
708
1645
|
/** Returns true if the patterns contain any actionable findings. */
|
|
709
1646
|
declare function hasReviewPatterns(patterns: ReviewPatterns): boolean;
|
|
710
1647
|
|
|
@@ -714,8 +1651,8 @@ declare function parseToolMetrics(content: string): ToolCallMetric[];
|
|
|
714
1651
|
declare function serializeToolMetric(metric: ToolCallMetric): string;
|
|
715
1652
|
/** Append a tool metric row to METRICS.md content. Creates the file template if content is empty. */
|
|
716
1653
|
declare function appendToolMetricToContent(metric: ToolCallMetric, content: string): string;
|
|
717
|
-
/** Aggregate tool call metrics into a cost summary, optionally filtered by
|
|
718
|
-
declare function aggregateCostSummary(metrics: ToolCallMetric[],
|
|
1654
|
+
/** Aggregate tool call metrics into a cost summary, optionally filtered by cycle. */
|
|
1655
|
+
declare function aggregateCostSummary(metrics: ToolCallMetric[], cycleNumber?: number): CostSummary;
|
|
719
1656
|
|
|
720
1657
|
/** Parse the PHASES YAML section from PRODUCT_BRIEF.md content. */
|
|
721
1658
|
declare function parsePhases(content: string): Phase[];
|
|
@@ -724,21 +1661,14 @@ declare function serializePhases(phases: Phase[]): string;
|
|
|
724
1661
|
/** Serialize phases and write them into the PHASES section of PRODUCT_BRIEF.md content. */
|
|
725
1662
|
declare function writePhasesToContent(phases: Phase[], content: string): string;
|
|
726
1663
|
|
|
727
|
-
/** Parse
|
|
728
|
-
declare function
|
|
729
|
-
/** Serialize
|
|
730
|
-
declare function
|
|
731
|
-
/** Serialize
|
|
732
|
-
declare function
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
declare function parseSprints(content: string): Sprint[];
|
|
736
|
-
/** Serialize sprints to a complete SPRINTS.md file content. */
|
|
737
|
-
declare function serializeSprints(sprints: Sprint[], content: string): string;
|
|
738
|
-
/** Serialize a single Sprint to a YAML string (for display/export). */
|
|
739
|
-
declare function serializeSprint(sprint: Sprint): string;
|
|
740
|
-
/** Add a new sprint to SPRINTS.md (prepended to the array so newest is first). */
|
|
741
|
-
declare function prependSprint(sprint: Sprint, content: string): string;
|
|
1664
|
+
/** Parse CYCLES.md content into an array of Cycle objects (newest first). */
|
|
1665
|
+
declare function parseCycles(content: string): Cycle[];
|
|
1666
|
+
/** Serialize cycles to a complete CYCLES.md file content. */
|
|
1667
|
+
declare function serializeCycles(cycles: Cycle[], content: string): string;
|
|
1668
|
+
/** Serialize a single Cycle to a YAML string (for display/export). */
|
|
1669
|
+
declare function serializeCycle(cycle: Cycle): string;
|
|
1670
|
+
/** Add a new cycle to CYCLES.md (prepended to the array so newest is first). */
|
|
1671
|
+
declare function prependCycle(cycle: Cycle, content: string): string;
|
|
742
1672
|
|
|
743
1673
|
/** Parse REGISTRIES.md content into a Registries object. */
|
|
744
1674
|
declare function parseRegistries(content: string): Registries;
|
|
@@ -782,6 +1712,9 @@ interface Project {
|
|
|
782
1712
|
name: string;
|
|
783
1713
|
repo_url?: string;
|
|
784
1714
|
papi_dir?: string;
|
|
1715
|
+
user_id?: string;
|
|
1716
|
+
root_commit_hash?: string;
|
|
1717
|
+
resolution_method?: string;
|
|
785
1718
|
created_at: string;
|
|
786
1719
|
updated_at: string;
|
|
787
1720
|
}
|
|
@@ -901,4 +1834,4 @@ interface ConflictAlert {
|
|
|
901
1834
|
resolved_at?: string;
|
|
902
1835
|
}
|
|
903
1836
|
|
|
904
|
-
export { type Acknowledgement, type AcknowledgementStatus, type ActiveDecision, type BoardQueryOptions, type BuildHandoff, type BuildPatterns, type BuildReport, type ClusterEntry, type ClusterResult, type CommandCost, type Confidence, type ConflictAlert, type ConflictAlertStatus, type ConflictRaisedBy, type ConflictType, type ContextHashes, type ContextTier, type CostSnapshot, type CostSummary, type DecisionEvent, type DecisionEventSource, type DecisionEventType, type DecisionScore, type DecisionUsageSummary, type EffortSize, type EntityReference, type
|
|
1837
|
+
export { type Acknowledgement, type AcknowledgementStatus, type ActiveDecision, type AgendaTopic, type AgendaTopicStatus, type AutoReview, type AutoReviewFinding, type AutoReviewVerdict, type BoardQueryOptions, type BriefImplication, type BugReport, type BuildHandoff, type BuildPatterns, type BuildReport, type ClusterEntry, type ClusterResult, type CommandCost, type Confidence, type ConflictAlert, type ConflictAlertStatus, type ConflictRaisedBy, type ConflictType, type ContextHashes, type ContextTier, type ContextUtilisationSummary, type ContributorEntry, type CostSnapshot, type CostSummary, type Cycle, type CycleEstimationAccuracy, type CycleHealth, type CycleLearning, type CycleLearningPattern, type CycleLogEntry, type CycleMetricsSnapshot, type CycleStatus, type CycleTask, type CycleVelocity, type DecisionEvent, type DecisionEventSource, type DecisionEventType, type DecisionScore, type DecisionUsageSummary, type DiscoveryCanvas, type DocRegistryEntry, type DocSearchInput, type DocVisibility, type DogfoodEntry, type EffortSize, type EntityReference, type EstimationCalibrationRow, type HarnessInventoryEntry, type HarnessState, type Horizon, type HorizonStatus, type HumanReview, MdFileAdapter, type MetricDelta, type MilestoneDependency, type ModuleEstimationRow, type NorthStar, type OwnerActionInput, type OwnerActionRow, type OwnerIdentity, type PapiAdapter, type Phase, type PhaseStatus, type PlanContextSummary, type PlanRunEntry, type PlanWriteBackPayload, type PlanWriteBackResult, type PlanningLog, type Project, type ProjectContribution, type ProjectContributionStatus, type ProjectLifecycleResult, type ProjectSummary, type RecommendationEffectivenessRow, type RecommendationStatus, type RecommendationType, type RecurringFeedback, type RecurringSurprise, type Registries, type ReviewPatterns, type ReviewStage, type ReviewVerdict, type SharedDecision, type SharedDecisionConfidence, type SharedDecisionStatus, type SharedMilestone, type SharedMilestoneStatus, type SiblingRepoTask, type Stage, type StageStatus, type StateTransition, type StrategyRecommendation, type StrategyReviewEntry, TASK_TYPE_TIERS, type TaskComplexity, type TaskMaturity, type TaskPriority, type TaskStatus, type TaskType, type TextClusterer, type ToolCallMetric, type UpdateTaskOptions, VALID_TRANSITIONS, aggregateCostSummary, appendToolMetricToContent, calculateCycleMetrics, detectBuildPatterns, detectReviewPatterns, hasBuildPatterns, hasReviewPatterns, isValidStatus, isValidTransition, parseBuildHandoff, parseCycles, parseEffortSize, parsePhases, parseRegistries, parseReviews, parseToolMetrics, prependCycle, prependReview, serializeBuildHandoff, serializeCycle, serializeCycles, serializePhases, serializeRegistries, serializeReview, serializeToolMetric, validateTransition, writePhasesToContent };
|