projectkeeper 0.0.0-stage → 1.0.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.
Files changed (276) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +283 -2
  4. package/README.zh-CN.md +285 -0
  5. package/THIRD_PARTY_NOTICES.md +53 -0
  6. package/bin/pk.mjs +6 -0
  7. package/bin/postinstall.mjs +5 -0
  8. package/bin/strip-types.mjs +28 -0
  9. package/package.json +68 -4
  10. package/patches/README.md +111 -0
  11. package/patches/pi-ai-0.85.0.ts +122 -0
  12. package/patches/pi-ai-0.87.1.ts +122 -0
  13. package/scripts/apply-pi-streaming-patch.ts +86 -0
  14. package/skills/clerk/coverage/SKILL.md +35 -0
  15. package/skills/clerk/cross-check/SKILL.md +118 -0
  16. package/skills/clerk/deepen-dispatch/SKILL.md +69 -0
  17. package/skills/clerk/lane-follow-up/SKILL.md +94 -0
  18. package/skills/clerk/lane-plan/SKILL.md +107 -0
  19. package/skills/clerk/lane-slot/SKILL.md +113 -0
  20. package/skills/clerk/lane-topic/SKILL.md +116 -0
  21. package/skills/clerk/orientation/SKILL.md +160 -0
  22. package/skills/clerk/reconcile/SKILL.md +77 -0
  23. package/skills/clerk/skeleton-dispatch/SKILL.md +43 -0
  24. package/skills/clerk/spot-check/SKILL.md +52 -0
  25. package/skills/clerk/synthesis/SKILL.md +65 -0
  26. package/skills/table-follow-up/SKILL.md +42 -0
  27. package/src/cli.ts +319 -0
  28. package/src/codemap/README.md +13 -0
  29. package/src/codemap/engines.ts +102 -0
  30. package/src/codemap/facts.ts +504 -0
  31. package/src/context/agent-entry.ts +232 -0
  32. package/src/context/ask.ts +97 -0
  33. package/src/context/assemble.ts +1058 -0
  34. package/src/context/code-source.ts +103 -0
  35. package/src/context/k-briefs.ts +114 -0
  36. package/src/context/lineage.ts +100 -0
  37. package/src/context/object-brief.ts +300 -0
  38. package/src/context/owner-words.ts +191 -0
  39. package/src/context/pack-fixture.ts +342 -0
  40. package/src/context/project-rules.ts +160 -0
  41. package/src/intake/intake.ts +392 -0
  42. package/src/intake/material-rules.ts +166 -0
  43. package/src/intake/removal.ts +316 -0
  44. package/src/intake/skipped.ts +72 -0
  45. package/src/keeper/adjustment.ts +565 -0
  46. package/src/keeper/bounds/boundary.ts +509 -0
  47. package/src/keeper/bounds/command.ts +1665 -0
  48. package/src/keeper/bounds/paths.ts +164 -0
  49. package/src/keeper/bounds/reads.ts +718 -0
  50. package/src/keeper/bounds/shell-write-guard.ts +521 -0
  51. package/src/keeper/capabilities.ts +136 -0
  52. package/src/keeper/clerk-steps.ts +151 -0
  53. package/src/keeper/clerk-tools.ts +1424 -0
  54. package/src/keeper/conversation.ts +253 -0
  55. package/src/keeper/evidence.ts +662 -0
  56. package/src/keeper/fake-provider.ts +132 -0
  57. package/src/keeper/held.ts +15 -0
  58. package/src/keeper/history-tools.ts +163 -0
  59. package/src/keeper/jobs/answering.ts +53 -0
  60. package/src/keeper/key-check.ts +105 -0
  61. package/src/keeper/ledger-tools.ts +295 -0
  62. package/src/keeper/link-check.ts +185 -0
  63. package/src/keeper/merge.ts +260 -0
  64. package/src/keeper/note-origin.ts +56 -0
  65. package/src/keeper/numbers-check.ts +102 -0
  66. package/src/keeper/open-in-pi.ts +57 -0
  67. package/src/keeper/organize/absence.ts +266 -0
  68. package/src/keeper/organize/carried-on.ts +214 -0
  69. package/src/keeper/organize/clerk-coverage.ts +293 -0
  70. package/src/keeper/organize/clerk-prompts.ts +132 -0
  71. package/src/keeper/organize/clerk.ts +1395 -0
  72. package/src/keeper/organize/coverage-gate.ts +19 -0
  73. package/src/keeper/organize/coverage-tools.ts +765 -0
  74. package/src/keeper/organize/entries.ts +153 -0
  75. package/src/keeper/organize/entry-gate.ts +289 -0
  76. package/src/keeper/organize/fill-tools.ts +718 -0
  77. package/src/keeper/organize/follow-up.ts +280 -0
  78. package/src/keeper/organize/generation-check.ts +504 -0
  79. package/src/keeper/organize/graph.ts +230 -0
  80. package/src/keeper/organize/lane-tools.ts +289 -0
  81. package/src/keeper/organize/looked-tools.ts +54 -0
  82. package/src/keeper/organize/materials.ts +243 -0
  83. package/src/keeper/organize/owner-lines.ts +493 -0
  84. package/src/keeper/organize/place-tools.ts +216 -0
  85. package/src/keeper/organize/placement-inference.ts +1045 -0
  86. package/src/keeper/organize/placement-time.ts +320 -0
  87. package/src/keeper/organize/placing.ts +821 -0
  88. package/src/keeper/organize/positioning.ts +33 -0
  89. package/src/keeper/organize/readiness.ts +47 -0
  90. package/src/keeper/organize/reading.ts +401 -0
  91. package/src/keeper/organize/round-blocks.ts +65 -0
  92. package/src/keeper/organize/round-news.ts +164 -0
  93. package/src/keeper/organize/round-open.ts +586 -0
  94. package/src/keeper/organize/schedule-state.ts +39 -0
  95. package/src/keeper/organize/schedule.ts +137 -0
  96. package/src/keeper/organize/service.ts +409 -0
  97. package/src/keeper/organize/skills.ts +116 -0
  98. package/src/keeper/organize/slots.ts +85 -0
  99. package/src/keeper/organize/stage-gate.ts +175 -0
  100. package/src/keeper/organize/stage-tools.ts +471 -0
  101. package/src/keeper/organize/standing-notes.ts +141 -0
  102. package/src/keeper/organize/table-follow-up.ts +330 -0
  103. package/src/keeper/organize/takeover-clerk.ts +832 -0
  104. package/src/keeper/organize/takeover-state.ts +103 -0
  105. package/src/keeper/organize/takeover.ts +216 -0
  106. package/src/keeper/organize/update-pending.ts +535 -0
  107. package/src/keeper/organize/workbench-placement.ts +92 -0
  108. package/src/keeper/own-keys.ts +114 -0
  109. package/src/keeper/owner-text.ts +165 -0
  110. package/src/keeper/project-folder.ts +334 -0
  111. package/src/keeper/prompts.ts +101 -0
  112. package/src/keeper/references.ts +177 -0
  113. package/src/keeper/relook/compose.ts +120 -0
  114. package/src/keeper/relook/prompts.ts +36 -0
  115. package/src/keeper/roles.ts +259 -0
  116. package/src/keeper/round-tools.ts +227 -0
  117. package/src/keeper/route.ts +148 -0
  118. package/src/keeper/rules.ts +97 -0
  119. package/src/keeper/runtime.ts +1858 -0
  120. package/src/keeper/scope-tools.ts +194 -0
  121. package/src/keeper/sendback-text.ts +83 -0
  122. package/src/keeper/step-timing.ts +207 -0
  123. package/src/keeper/testing/clerk-script.ts +212 -0
  124. package/src/keeper/testing/streaming-arguments.ts +57 -0
  125. package/src/keeper/tools.ts +2340 -0
  126. package/src/keeper/utterance-tools.ts +64 -0
  127. package/src/keeper/verbatim.ts +397 -0
  128. package/src/ledger/adapters.ts +186 -0
  129. package/src/ledger/arrangements.ts +257 -0
  130. package/src/ledger/blame.ts +58 -0
  131. package/src/ledger/code-engine-child.ts +69 -0
  132. package/src/ledger/code-engine.ts +548 -0
  133. package/src/ledger/code.ts +607 -0
  134. package/src/ledger/docs.ts +294 -0
  135. package/src/ledger/git-read.ts +321 -0
  136. package/src/ledger/index.ts +1850 -0
  137. package/src/ledger/item-range.ts +16 -0
  138. package/src/ledger/lines.ts +328 -0
  139. package/src/ledger/numbering.ts +269 -0
  140. package/src/ledger/ranges.ts +74 -0
  141. package/src/ledger/rebuild-worker.ts +15 -0
  142. package/src/ledger/rebuild.ts +387 -0
  143. package/src/ledger/repo-scan.ts +181 -0
  144. package/src/ledger/schema.ts +450 -0
  145. package/src/ledger/sessions.ts +134 -0
  146. package/src/ledger/text-scan.ts +466 -0
  147. package/src/ledger/time.ts +185 -0
  148. package/src/ledger/ts-symbols.ts +180 -0
  149. package/src/ledger/views.ts +377 -0
  150. package/src/mcp/server.ts +127 -0
  151. package/src/mcp/tools.ts +187 -0
  152. package/src/model/ids.ts +23 -0
  153. package/src/model/k-types.ts +912 -0
  154. package/src/model/time.ts +85 -0
  155. package/src/model/types.ts +1382 -0
  156. package/src/model/views-k.ts +707 -0
  157. package/src/model/vocab.ts +269 -0
  158. package/src/process/analysis.ts +79 -0
  159. package/src/process/breakpoint-candidates.ts +383 -0
  160. package/src/process/breakpoints.ts +746 -0
  161. package/src/process/claim-check.ts +295 -0
  162. package/src/process/delivery-links.ts +52 -0
  163. package/src/process/facts.ts +487 -0
  164. package/src/process/generations.ts +138 -0
  165. package/src/process/index.ts +243 -0
  166. package/src/process/integration.ts +128 -0
  167. package/src/process/placement.ts +107 -0
  168. package/src/process/plan.ts +276 -0
  169. package/src/process/sendbacks.ts +244 -0
  170. package/src/process/text.ts +185 -0
  171. package/src/process/units.ts +543 -0
  172. package/src/process/unnumbered.ts +431 -0
  173. package/src/process/work.ts +884 -0
  174. package/src/scope/candidates.ts +86 -0
  175. package/src/scope/decisions.ts +229 -0
  176. package/src/scope/discover.ts +741 -0
  177. package/src/scope/ignore.ts +126 -0
  178. package/src/scope/ignored-place.ts +93 -0
  179. package/src/scope/skip.ts +161 -0
  180. package/src/scope/toolchain.ts +180 -0
  181. package/src/scope/worktree.ts +187 -0
  182. package/src/server/api.ts +549 -0
  183. package/src/server/app.ts +595 -0
  184. package/src/server/drafts-api.ts +170 -0
  185. package/src/server/folders-api.ts +243 -0
  186. package/src/server/graph-view.ts +639 -0
  187. package/src/server/http.ts +224 -0
  188. package/src/server/k-agent-api.ts +56 -0
  189. package/src/server/k-rounds-d99.ts +91 -0
  190. package/src/server/k-views.ts +405 -0
  191. package/src/server/keeper-page.ts +446 -0
  192. package/src/server/keys-api.ts +239 -0
  193. package/src/server/project-folder-api.ts +104 -0
  194. package/src/server/vendor.ts +14 -0
  195. package/src/server/workbench-content.ts +561 -0
  196. package/src/sources/anchor.ts +129 -0
  197. package/src/sources/files.ts +267 -0
  198. package/src/sources/gitobs.ts +41 -0
  199. package/src/sources/history.ts +231 -0
  200. package/src/sources/scan-worker.ts +10 -0
  201. package/src/sources/sessions/locate.ts +292 -0
  202. package/src/sources/sessions/read.ts +346 -0
  203. package/src/sources/sessions/scope.ts +42 -0
  204. package/src/sources/sessions/utterances.ts +223 -0
  205. package/src/sources/watch.ts +215 -0
  206. package/src/store/json-file.ts +50 -0
  207. package/src/store/paths.ts +39 -0
  208. package/src/store/project-store.ts +295 -0
  209. package/src/store/versions.ts +172 -0
  210. package/src/store/workspace.ts +216 -0
  211. package/src/table/check.ts +333 -0
  212. package/src/table/follow-up-tools.ts +30 -0
  213. package/src/table/follow-up.ts +344 -0
  214. package/src/table/import.ts +610 -0
  215. package/src/table/project-home.ts +61 -0
  216. package/src/table/sessions.ts +168 -0
  217. package/src/table/takeover.ts +483 -0
  218. package/src/util/git-check.ts +29 -0
  219. package/src/util/git.ts +411 -0
  220. package/src/util/own-ts.ts +15 -0
  221. package/src/util/paths.ts +225 -0
  222. package/template/FILLING-IN.md +148 -0
  223. package/template/examples/papertrail.json +747 -0
  224. package/template/projectkeeper.schema.json +1001 -0
  225. package/ui/app.js +1135 -0
  226. package/ui/failures.js +82 -0
  227. package/ui/flyout.js +120 -0
  228. package/ui/folder-chooser.js +264 -0
  229. package/ui/glossary.js +156 -0
  230. package/ui/graph-fit.js +157 -0
  231. package/ui/graph-material.js +61 -0
  232. package/ui/graph-palette.js +109 -0
  233. package/ui/graph-tools.js +62 -0
  234. package/ui/graph.js +1712 -0
  235. package/ui/index.html +31 -0
  236. package/ui/k/code-view.js +230 -0
  237. package/ui/k/draft-view.js +93 -0
  238. package/ui/k/k-views.css +224 -0
  239. package/ui/k/round-tree.js +450 -0
  240. package/ui/k/scope-k.js +159 -0
  241. package/ui/k-data.js +118 -0
  242. package/ui/k-fold.js +106 -0
  243. package/ui/k-process.css +302 -0
  244. package/ui/k-process.js +934 -0
  245. package/ui/keeper-activity.js +175 -0
  246. package/ui/keeper-view.js +801 -0
  247. package/ui/keeper.css +101 -0
  248. package/ui/key-order.js +62 -0
  249. package/ui/list-fold.js +67 -0
  250. package/ui/markdown.d.ts +21 -0
  251. package/ui/markdown.js +472 -0
  252. package/ui/placement.d.ts +92 -0
  253. package/ui/placement.js +445 -0
  254. package/ui/popover-place.d.ts +16 -0
  255. package/ui/popover-place.js +89 -0
  256. package/ui/popover.js +198 -0
  257. package/ui/project-folder.js +37 -0
  258. package/ui/shell-state.js +40 -0
  259. package/ui/strip-rows.js +171 -0
  260. package/ui/styles.css +492 -0
  261. package/ui/theme-pick.js +36 -0
  262. package/ui/theme.js +74 -0
  263. package/ui/themes/LICENSE.md +13 -0
  264. package/ui/themes/README.md +44 -0
  265. package/ui/themes/TOKENS.md +291 -0
  266. package/ui/themes/a1/board.css +1557 -0
  267. package/ui/themes/a1/pk.css +392 -0
  268. package/ui/themes/b1/board.css +1163 -0
  269. package/ui/themes/b1/pk.css +218 -0
  270. package/ui/themes/d2/board.css +518 -0
  271. package/ui/themes/d2/pk.css +243 -0
  272. package/ui/themes/guard.css +73 -0
  273. package/ui/themes/i1/board.css +776 -0
  274. package/ui/themes/i1/pk.css +223 -0
  275. package/ui/themes/manifest.json +13 -0
  276. package/ui/views.js +2796 -0
@@ -0,0 +1,707 @@
1
+ /**
2
+ * What the workbench receives for increment K (Spec v3.0 §6.3 process view, §6.17 `Code`, §6.4 versions and
3
+ * `How it got here`, §6.9 a round's tree, §6.7 Project scope). The server assembles these from the assets and the
4
+ * ledger; the UI only draws them. Every list is already sorted by when things happened (§2.11), oldest first, unless
5
+ * a field says otherwise; the UI never re-sorts by `updatedAt`.
6
+ *
7
+ * Endpoints (JSON):
8
+ * GET /api/projects/:id/process → ProcessView
9
+ * GET /api/projects/:id/objects/:oid/lineage → LineageView
10
+ * GET /api/projects/:id/objects/:oid/versions → VersionsView
11
+ * GET /api/projects/:id/code → CodeView
12
+ * GET /api/projects/:id/code/territories/:tid → TerritoryDetailView
13
+ * GET /api/projects/:id/k-rounds → RoundView[] (newest first)
14
+ * GET /api/projects/:id/k-rounds/:rid/docs/:docId → RoundDocView
15
+ * GET /api/projects/:id/scope-k → ScopeKView
16
+ * GET /api/projects/:id/patches → { patches: PatchView[] } (oldest first, by when it happened)
17
+ * GET /api/projects/:id/patches/:pid → PatchView with its `text` (a patch's details; also by SP-n)
18
+ * GET /api/projects/:id/code/file?path=&repo= → CodeFileTextView (a file of the current version)
19
+ * GET /api/projects/:id/generations/:gid/plans/:n → GenerationPlanTextView (an earlier generation's plan document)
20
+ * GET /api/projects/:id/drafts[?objectId=] → { drafts: SessionDraftRef[] } (server/drafts-api.ts)
21
+ * GET /api/projects/:id/drafts/:key → SessionDraftView (key: draft id, session source id, host:session, session id)
22
+ * POST /api/projects/:id/breakpoints/:bid/response body { reason } → BreakpointView (`No action needed`)
23
+ * POST /api/projects/:id/sendbacks/:sid/response body { reason } → SendBackView (`No action needed`)
24
+ *
25
+ * Object ids are graph node ids (`/api/projects/:id/graph`), so these views hang on the nodes the graph and the List
26
+ * already draw.
27
+ */
28
+ import type {
29
+ BreakpointKind, ClerkStage, CoverageGroup, CurrentUse, EvidenceRef, LaneKind, LayerKind, MaterialAccount, Occurred, RoundDocKind, RoundKind,
30
+ RoundStepKind, SendBackStage, SixThing, SlotKind, StepKind, StepTiming, TerritoryAnomalyKind,
31
+ } from './k-types.ts';
32
+ import type { Usage } from './types.ts';
33
+
34
+ // ───────────────────────── shared ─────────────────────────
35
+
36
+ export interface NumberView {
37
+ readonly value: string;
38
+ /** The project had no number for it and the Keeper gave one (§1.17): the UI says so. */
39
+ readonly byKeeper: boolean;
40
+ }
41
+
42
+ export interface NoActionView { readonly reason: string; readonly at: string }
43
+
44
+ // ───────────────────────── §6.3 the process view (Graph and List) ─────────────────────────
45
+
46
+ /** One step of a piece of work (§2.12): what was done on the left, what reality gave on the right. */
47
+ export interface ProcessStepView {
48
+ readonly id: string;
49
+ readonly kind: StepKind;
50
+ readonly occurred: Occurred;
51
+ /** Left: what was done, e.g. "AB delivered — no receipt, rebuilt from the diff". */
52
+ readonly did: string;
53
+ /** The project's number of the task that made this step (a fix, a check), when it is a task of its own, e.g. "AD". */
54
+ readonly unit?: string | null;
55
+ /** Right: what reality gave, e.g. "merged 42a86f5 · 12 tests", "Fail · 7 findings". */
56
+ readonly result: string;
57
+ /** The verdict exactly as the report wrote it, for QC / Review / Walkthrough. */
58
+ readonly verdict: string | null;
59
+ /** Agent, window or worktree bound to it, when the arrangement or git says. */
60
+ readonly who: string | null;
61
+ readonly evidence: readonly EvidenceRef[];
62
+ /** `Inferred` when the step was tied to this work by a judged link rather than an id (drawn as such). */
63
+ readonly basis: 'Explicit' | 'Inferred';
64
+ /** This step lies in history (a side branch, a deleted document): shown labelled as history (D82). */
65
+ readonly history: boolean;
66
+ /** The step is a send-back going back to Work or Plan: drawn as an arrow pointing back (§6.3). */
67
+ readonly sendBackId: string | null;
68
+ /** CM: a step from a judged link — confirmed by the cross-check, lane-checked by the program, suspect, or not checked yet. */
69
+ readonly link?: 'confirmed' | 'lane-checked' | 'suspect' | 'unconfirmed';
70
+ }
71
+
72
+ export type ExecutionState = 'Not started' | 'In progress' | 'Merged' | 'Not merged';
73
+
74
+ /** §2.12 the four things every piece of work shows at a glance. */
75
+ export interface FourThingsView {
76
+ /** Null when the ledger does not say (no engine, no ledger yet): execution is never guessed from progress (QC AY B9). */
77
+ readonly execution: ExecutionState | null;
78
+ /** The work item's progress (§2.2 vocabulary). */
79
+ readonly progress: string;
80
+ /** The latest check and who made it; `Not checked` only when the project's rules ask for a check; null when they do not. */
81
+ readonly check: { readonly verdict: string; readonly by: 'Independent QC' | 'Self-reported' | 'Test'; readonly occurred: Occurred } | 'Not checked' | null;
82
+ /** Findings and send-backs still open: they light up even when the work is folded (D75). */
83
+ readonly open: { readonly findings: number; readonly sendBacks: number; readonly breakpoints: number };
84
+ }
85
+
86
+ export interface WorkProcessView {
87
+ /** Graph node id of the work item. */
88
+ readonly workId: string;
89
+ readonly number: NumberView | null;
90
+ readonly steps: readonly ProcessStepView[];
91
+ readonly four: FourThingsView;
92
+ /** One line when folded, e.g. "5 steps · 2 send-backs · all closed". Every work is folded, in the List and on the
93
+ * Graph, until the owner opens it (E152, E153; ui/k-fold.js). */
94
+ readonly folded: string;
95
+ /** The work item this one is a step of — a fix or a check of another piece of work (§2.12) — folded under it in List
96
+ * and Graph, as its steps show it; null for a piece of work of its own. */
97
+ readonly stepOf?: string | null;
98
+ /** The generation it was planned in, when it belongs to an earlier one (`GenerationBandView.id`). */
99
+ readonly generationId: string | null;
100
+ /** Replaced, abandoned or deferred: struck through, with what replaced it or why (§2.12). */
101
+ readonly struck: { readonly validity: string; readonly why: string; readonly byId: string | null } | null;
102
+ readonly breakpointIds: readonly string[];
103
+ readonly sendBackIds: readonly string[];
104
+ readonly sixThings: readonly SixThing[];
105
+ /**
106
+ * The code territories this work changed (§6.17 "从过程视图的工作跳到它改过的领地"): the files its trunk commits and
107
+ * merges changed in each territory, counted as `Built by` counts them, so the jump and the jump back give the same
108
+ * numbers. Most files first. Absent when the build has no code map (no ledger, or no territories drawn yet).
109
+ */
110
+ readonly territories?: readonly WorkTerritoryView[];
111
+ }
112
+
113
+ /** One code territory a piece of work changed (CKC-25 AC-7). */
114
+ export interface WorkTerritoryView {
115
+ readonly territoryId: string;
116
+ readonly name: string;
117
+ /** Files of the territory its commits changed. */
118
+ readonly files: number;
119
+ /** The commits (12 characters), oldest first. */
120
+ readonly commits: readonly string[];
121
+ }
122
+
123
+ /** §6.3 a plan's execution shape (D72): as the orchestrator wrote it and as git shows it; ProjectKeeper schedules nothing. */
124
+ export interface PlanShapeView {
125
+ /** Graph node id of the `Plan`. */
126
+ readonly planId: string;
127
+ /** Execution order as it actually happened, e.g. "1 → 6 → 2 → 3 → 4 → 5 (first half ∥ second half) → 7". */
128
+ readonly actualOrder: string | null;
129
+ readonly plannedOrder: string | null;
130
+ /** Where execution differed from the plan, in one sentence; null when it did not. */
131
+ readonly differs: string | null;
132
+ readonly batches: readonly {
133
+ readonly label: string;
134
+ readonly workIds: readonly string[];
135
+ readonly parallel: boolean;
136
+ readonly running: boolean;
137
+ readonly agent: string | null;
138
+ readonly worktree: string | null;
139
+ readonly mergeCommit: string | null;
140
+ readonly occurred: Occurred | null;
141
+ }[];
142
+ readonly dependsOn: readonly { readonly from: string; readonly to: string }[];
143
+ }
144
+
145
+ /** §6.3 the version of a document-like object that is current, and whether earlier ones can be seen. */
146
+ export interface DocCurrentView {
147
+ /** Graph node id of the Product / Requirement / Design / Decision / Plan object. */
148
+ readonly objectId: string;
149
+ /** The project's version label, or the short commit and date. */
150
+ readonly current: string | null;
151
+ readonly versions: number;
152
+ /** Not under version control before some day (CKC-22 AC-15): earlier versions cannot be shown. */
153
+ readonly historyFrom: string | null;
154
+ }
155
+
156
+ /** §2.12, D85 an earlier generation of plans, rolled up before the current plan. */
157
+ export interface GenerationBandView {
158
+ readonly id: string;
159
+ readonly name: string;
160
+ readonly started: Occurred | null;
161
+ readonly ended: Occurred;
162
+ /** The decision, cleanup or restart that ended it. */
163
+ readonly endedBy: EvidenceRef;
164
+ readonly planned: number;
165
+ readonly done: number;
166
+ readonly struck: number;
167
+ /** Its work items (graph node ids, carried in `works`), shown when the band is unrolled. */
168
+ readonly workIds: readonly string[];
169
+ /** CZ: of those, the ones carried on under the same number — current work in their current plan, listed here with that destination. */
170
+ readonly carriedIds: readonly string[];
171
+ /**
172
+ * Its plan objects (graph node ids): the `Plan` items read from its plan documents, and the plans its work items were
173
+ * planned in that are no longer current. They are drawn in the band like the current plan, with their shape.
174
+ */
175
+ readonly planIds: readonly string[];
176
+ /** The plans behind `planIds`, named, so the band shows them even when the graph does not draw them (a removed one). */
177
+ readonly plans?: readonly { readonly id: string; readonly name: string; readonly validity: string }[];
178
+ /**
179
+ * Its plan documents as the generation names them (`Generation.planRefs`), in that order; each one's text is read, when
180
+ * the band is unrolled, from the version the ledger has — for a document since deleted, from the commit before its
181
+ * deletion (D82): GET /api/projects/:id/generations/:gid/plans/:n.
182
+ */
183
+ readonly planDocs?: readonly GenerationPlanDocView[];
184
+ }
185
+
186
+ /** One plan document of an earlier generation (§2.12, D82). */
187
+ export interface GenerationPlanDocView {
188
+ /** Its position in `Generation.planRefs`: the `:n` of its text's endpoint. */
189
+ readonly index: number;
190
+ readonly label: string;
191
+ readonly path: string | null;
192
+ /** How the generation names it. */
193
+ readonly ref: EvidenceRef;
194
+ }
195
+
196
+ /** An earlier generation's plan document as it stood (§2.12, D82): the text is the ledger's copy, never rewritten. */
197
+ export interface GenerationPlanTextView {
198
+ readonly generationId: string;
199
+ readonly index: number;
200
+ readonly label: string;
201
+ readonly repo: string | null;
202
+ readonly path: string | null;
203
+ /** The version read: its commit and when that version happened. */
204
+ readonly version: { readonly commit: string; readonly occurred: Occurred } | null;
205
+ /** Deleted from the current version: the commit that deleted it and when; the text is the version before it. */
206
+ readonly deleted: { readonly commit: string; readonly occurred: Occurred } | null;
207
+ /** Still in the current version. */
208
+ readonly current: boolean;
209
+ /** The text, whole unless `truncated` (the ledger pages a long document; `lines` is its full length). */
210
+ readonly text: string | null;
211
+ readonly lines: number;
212
+ /** The line the text starts at (1 unless a later page was asked for). */
213
+ readonly fromLine: number;
214
+ /** The next page starts here (`?from=`), when the text is a page of a longer document. */
215
+ readonly nextFromLine: number | null;
216
+ readonly truncated: boolean;
217
+ /** Why no text could be read (no ledger, not in its history), when `text` is null. */
218
+ readonly why: string | null;
219
+ }
220
+
221
+ export interface BreakpointView {
222
+ readonly id: string;
223
+ readonly kind: BreakpointKind;
224
+ readonly targetId: string;
225
+ readonly why: string;
226
+ readonly since: Occurred;
227
+ readonly evidence: readonly EvidenceRef[];
228
+ readonly basis: 'Explicit' | 'Inferred';
229
+ /** Lit: a lane looked and the spot-check confirmed it (D99). A finding; only a lit one shows red. */
230
+ readonly lit: boolean;
231
+ /** D99: `Candidate` — computed, waiting for a lane to look and the spot-check to check; a lead, not a finding. */
232
+ readonly state?: 'Lit' | 'Candidate' | 'Out';
233
+ /** D99: where a lane looked for the missing step and did not find it; when the spot-check confirmed it. */
234
+ readonly looked?: { readonly where: readonly string[]; readonly at: string } | null;
235
+ readonly checked?: { readonly at: string } | null;
236
+ readonly ownerResponse: NoActionView | null;
237
+ readonly sixThing: SixThing | null;
238
+ readonly sendBackId: string | null;
239
+ }
240
+
241
+ export interface SendBackView {
242
+ readonly id: string;
243
+ readonly to: 'Work' | 'Plan';
244
+ readonly stage: SendBackStage;
245
+ readonly targetId: string;
246
+ readonly what: string;
247
+ readonly suggestion: string;
248
+ readonly evidence: readonly EvidenceRef[];
249
+ readonly occurred: Occurred;
250
+ readonly returned: { readonly label: string; readonly occurred: Occurred } | null;
251
+ readonly closed: { readonly label: string; readonly occurred: Occurred } | null;
252
+ readonly ownerResponse: NoActionView | null;
253
+ readonly sixThing: SixThing | null;
254
+ /** The text `Copy for agent` puts on the clipboard (§1.18): where, evidence, where to send it back, the CLI command. */
255
+ readonly copyForAgent: string;
256
+ /** The CLI command inside it, e.g. `pk get sb_… --project …` (§7.10). */
257
+ readonly cliCommand: string;
258
+ /** Still lights up (open and not answered `No action needed`). */
259
+ readonly lit: boolean;
260
+ /** Where it came from: a breakpoint, a verdict, an owner's-judgement position, a code territory's anomaly (§1.18). */
261
+ readonly from?: { readonly kind: 'breakpoint' | 'verdict' | 'owner-judgement' | 'code-anomaly'; readonly id: string };
262
+ /** The object it hangs on is a code territory: it is found in `Code`, not on the graph. */
263
+ readonly onTerritory?: boolean;
264
+ }
265
+
266
+ export interface ProcessView {
267
+ readonly projectId: string;
268
+ /** When the assets and the ledger this was assembled from were last updated. */
269
+ readonly asOf: string;
270
+ readonly ledgerAsOf: string | null;
271
+ /** Keyed by the work item's graph node id. A `Plan` with an execution shape has an entry too — its unit in List and
272
+ * Graph, with no steps of its own and its batches under `plans`. */
273
+ readonly works: Readonly<Record<string, WorkProcessView>>;
274
+ /** Keyed by the plan's graph node id. */
275
+ readonly plans: Readonly<Record<string, PlanShapeView>>;
276
+ /** Keyed by the document-like object's graph node id. */
277
+ readonly docs: Readonly<Record<string, DocCurrentView>>;
278
+ /** Earlier generations, oldest first; empty when the material names none (no bands are invented). */
279
+ readonly generations: readonly GenerationBandView[];
280
+ readonly breakpoints: readonly BreakpointView[];
281
+ readonly sendBacks: readonly SendBackView[];
282
+ /** Which objects carry each of the six things (§2.13), for `Filter`. */
283
+ readonly sixThings: readonly { readonly thing: SixThing; readonly objectIds: readonly string[] }[];
284
+ /** The top bar: breakpoints still lit, by kind; send-backs still open (§6.3, §2.12). */
285
+ readonly counts: { readonly breakpointsLit: number; readonly byKind: Readonly<Partial<Record<BreakpointKind, number>>>; readonly sendBacksOpen: number;
286
+ /** D99: candidates waiting to be read and checked; never counted as lit. */
287
+ readonly breakpointCandidates?: number };
288
+ }
289
+
290
+ // ───────────────────────── §6.4 the popover: versions and `How it got here` ─────────────────────────
291
+
292
+ export type LineageStepKind =
293
+ | 'First appeared' | 'Changed' | 'Replaced' | 'Replaces' | 'Planned' | 'Work' | 'Commit' | 'Merged' | 'Verdict'
294
+ | 'Send-back' | 'Now';
295
+
296
+ /** §2.11 one step of an object's dated path to now; the steps are ledger facts, not the model's words. */
297
+ export interface LineageStepView {
298
+ readonly kind: LineageStepKind;
299
+ readonly occurred: Occurred;
300
+ readonly title: string;
301
+ readonly evidence: readonly EvidenceRef[];
302
+ /** Lies in history: shown labelled as history, with what replaced it (D82). */
303
+ readonly history: boolean;
304
+ /**
305
+ * Whose step it is: the object's own (its number named, a line that replaces it, a patch or send-back aimed at it) or
306
+ * the document it sits in (the document's versions, commits and patches). A decision's popover shows the document's
307
+ * steps as that document's history, never as the decision's own (owner 2026-09-30). Absent: the object's.
308
+ */
309
+ readonly about?: 'object' | 'document';
310
+ }
311
+
312
+ export interface LineageView {
313
+ readonly objectId: string;
314
+ /** Oldest first. The popover shows the last few and expands to all (CKC-24 AC-14). */
315
+ readonly steps: readonly LineageStepView[];
316
+ /** The document the object sits in (repository-relative), whose steps are marked `about: 'document'`; null when none. */
317
+ readonly document?: string | null;
318
+ }
319
+
320
+ export interface VersionView {
321
+ /** The project's version label, or the short commit. */
322
+ readonly label: string;
323
+ readonly commit: string | null;
324
+ readonly occurred: Occurred;
325
+ readonly sections: { readonly added: readonly string[]; readonly removed: readonly string[]; readonly changed: readonly string[] };
326
+ /** The semantic patch that withdrew (part of) this version, when one did. */
327
+ readonly supersededBy: { readonly patchId: string; readonly number: string; readonly title: string; readonly partial: boolean } | null;
328
+ readonly current: boolean;
329
+ readonly history: boolean;
330
+ }
331
+
332
+ export interface VersionsView {
333
+ readonly objectId: string;
334
+ /** Oldest first. */
335
+ readonly versions: readonly VersionView[];
336
+ /** Not under version control before this day (CKC-22 AC-15): "earlier versions cannot be seen". */
337
+ readonly historyFrom: string | null;
338
+ /** The document these are the versions of (repository-relative): the one the object sits in; null when none. */
339
+ readonly document?: string | null;
340
+ }
341
+
342
+ // ───────────────────────── §6.17 `Code` ─────────────────────────
343
+
344
+ export interface TerritoryAnomalyView {
345
+ readonly kind: TerritoryAnomalyKind;
346
+ readonly text: string;
347
+ readonly evidence: readonly EvidenceRef[];
348
+ readonly basis: 'Explicit' | 'Inferred';
349
+ readonly sendBackId: string | null;
350
+ readonly noteIds: readonly string[];
351
+ /** The notes behind `noteIds` as the jump names them: title, what they ask, their state (§6.17 "从异常跳到相关的 note"). */
352
+ readonly notes?: readonly { readonly id: string; readonly title: string; readonly ask: string; readonly status: string }[];
353
+ }
354
+
355
+ export interface TerritoryView {
356
+ readonly id: string;
357
+ readonly name: string;
358
+ readonly summary: string;
359
+ readonly repo: string;
360
+ readonly paths: readonly string[];
361
+ /** A row per product area, one for the shared base, one for what is not product code (§6.17). */
362
+ readonly row: { readonly kind: 'area'; readonly areaId: string; readonly areaName: string; /** The area's one-line summary, as Product intent writes it. */ readonly areaLine?: string | null } | { readonly kind: 'shared' } | { readonly kind: 'non-product' };
363
+ readonly size: { readonly files: number; readonly lines: number; readonly generatedFiles: number; readonly generatedLines: number };
364
+ readonly dependsOn: readonly string[];
365
+ readonly dependedBy: readonly string[];
366
+ /** How many file-level edges each dependency carries, by territory id ("depends on: chat engine (19)"). */
367
+ readonly dependsOnCounts?: Readonly<Record<string, number>>;
368
+ readonly dependedByCounts?: Readonly<Record<string, number>>;
369
+ /** Other areas it also serves: "also serves N", expanded on hover (D74, D54). */
370
+ readonly alsoServes: readonly { readonly areaId: string; readonly areaName: string }[];
371
+ /** Who built it: work item × files changed, by merge commit (§1.19). */
372
+ readonly builtBy: readonly { readonly workId: string | null; readonly label: string; readonly commits: readonly string[]; readonly files: number }[];
373
+ /** Which generation the current lines come from (D85), largest share first. `generationId` is an earlier generation's
374
+ * band (`GenerationBandView.id`); null is the current generation, which has no band. */
375
+ readonly generations: readonly { readonly generationId: string | null; readonly name: string; readonly share: number; /** The work items the lines of this generation came from, by lines (§1.19: which generation's which work). */ readonly works?: readonly { readonly workId: string | null; readonly label: string; readonly lines: number }[] }[];
376
+ readonly currentUse: CurrentUse;
377
+ readonly tests: number;
378
+ readonly lastChange: { readonly commit: string; readonly occurred: Occurred; readonly subject: string } | null;
379
+ readonly anomalies: readonly TerritoryAnomalyView[];
380
+ /**
381
+ * Its paths the current version no longer has (deleted or moved since the territory was drawn): its numbers count only
382
+ * what is left, and it is drawn again at the next round's cross-check (CKC-25 AC-10). Absent or empty when all are there.
383
+ */
384
+ readonly gonePaths?: readonly string[];
385
+ }
386
+
387
+ /**
388
+ * How deep the ledger reads one language of the code (§1.16 "看得见", §6.17 "顶上写明…账本的代码结构做到哪一级"; D98 补),
389
+ * from the coverage it measured (Ledger.coverage): read by the TypeScript compiler, to symbols; read by the code engine,
390
+ * to symbols as far as it resolved them — the imports it resolved to a file of the repository and those it left
391
+ * unresolved though they name one; or not read, its files and sizes only. Where a file is not read or a reference was
392
+ * measured unresolved, a residual call on that code is Inferred (CKC-25 AC-5).
393
+ */
394
+ export interface CodeLanguageView {
395
+ readonly language: string;
396
+ /** Its files of the current version, generated and third-party ones left out (tests counted), and of them the ones its reader read. */
397
+ readonly files: number;
398
+ readonly read: number;
399
+ /** Who reads its references: the TypeScript compiler, the code engine, or nobody. */
400
+ readonly readBy: 'compiler' | 'engine' | null;
401
+ /** The code engine's imports: resolved to a file of the repository, and left unresolved though they name one. Null unless the engine reads it. */
402
+ readonly imports: { readonly resolved: number; readonly unresolvedNamingRepoFiles: number } | null;
403
+ /** Files no counted reference reaches that another file names by its file name: references its reader left unresolved. */
404
+ readonly namedButUnreferenced: number;
405
+ /** Files the engine could not parse in full. */
406
+ readonly parseErrors: number;
407
+ /** Every file read and nothing measured unresolved: a residual call on it can rest on computed references alone. */
408
+ readonly complete: boolean;
409
+ /** What was measured unresolved or missing, in the ledger's words; empty when nothing was. */
410
+ readonly gaps: readonly string[];
411
+ }
412
+
413
+ export interface CodeView {
414
+ readonly projectId: string;
415
+ readonly version: { readonly repo: string; readonly branch: string | null; readonly commit: string; readonly occurred: Occurred };
416
+ /** How deep the ledger reads each language of the code: every language a reader reads, and every one it knows is code but reads nothing of. */
417
+ readonly levels: readonly CodeLanguageView[];
418
+ readonly generatedAt: string;
419
+ readonly territories: readonly TerritoryView[];
420
+ /** The send-backs its anomalies carry, by id, so `Code` shows them without the process view loaded first (QC AY B6). */
421
+ readonly sendBacks?: Readonly<Record<string, SendBackView>>;
422
+ }
423
+
424
+ /** A file of the current version, opened from `Code` (§6.17 "点文件打开原文阅读"): found by the ledger's `fileRefs`. */
425
+ export interface CodeFileTextView {
426
+ readonly repo: string;
427
+ readonly path: string;
428
+ readonly lang: string | null;
429
+ /** The commit whose tree the ledger read it from (the checkout's HEAD when the ledger was built), and when. */
430
+ readonly commit: string | null;
431
+ readonly occurred: Occurred | null;
432
+ readonly lines: number;
433
+ readonly fromLine: number;
434
+ readonly toLine: number;
435
+ /** A long file comes in pages: the next page starts here. */
436
+ readonly nextFromLine: number | null;
437
+ readonly text: string;
438
+ readonly generated: boolean;
439
+ }
440
+
441
+ export interface CodeFileView {
442
+ readonly path: string;
443
+ readonly lines: number;
444
+ readonly generated: boolean;
445
+ readonly importedBy: readonly string[];
446
+ readonly imports: readonly string[];
447
+ readonly lastCommit: { readonly commit: string; readonly occurred: Occurred; readonly subject: string } | null;
448
+ readonly workId: string | null;
449
+ /** The work item's name and number, when it is known; a work id no territory's `builtBy` names still reads. */
450
+ readonly workLabel?: string | null;
451
+ }
452
+
453
+ export interface TerritoryDetailView {
454
+ readonly territoryId: string;
455
+ readonly files: readonly CodeFileView[];
456
+ }
457
+
458
+ // ───────────────────────── §6.9 a round in the Keeper view ─────────────────────────
459
+
460
+ export interface RoundDocRef { readonly id: string; readonly kind: RoundDocKind; readonly title: string; readonly path: string | null; /** When the document was written. */ readonly at?: string }
461
+
462
+ export interface RoundStepView {
463
+ readonly jobId: string;
464
+ readonly kind: RoundStepKind;
465
+ readonly label: string;
466
+ /** The deep sweep's name, for `dig`; the lane's name, for `lane` (D99). */
467
+ readonly path: string | null;
468
+ readonly status: string;
469
+ readonly model: { readonly provider: string; readonly id: string; readonly thinking: string | null } | null;
470
+ readonly startedAt: string | null;
471
+ readonly endedAt: string | null;
472
+ readonly timing: StepTiming | null;
473
+ readonly usage: Usage | null;
474
+ readonly docs: readonly RoundDocRef[];
475
+ readonly children: readonly RoundStepView[];
476
+ /** The session drafts this step wrote (the session-drafts step), each openable (CKC-23 AC-18). */
477
+ readonly drafts?: readonly SessionDraftRef[];
478
+ }
479
+
480
+ export interface RoundView {
481
+ readonly id: string;
482
+ readonly kind: RoundKind;
483
+ readonly number: number;
484
+ /** The record of the round itself: stopping it stops the whole tree (§3.10). Absent on a fixture written before it. */
485
+ readonly rootJobId?: string;
486
+ /** A deepening: the depth it ran at. A Follow up: what started it (the owner, the schedule). */
487
+ readonly depth?: string | null;
488
+ readonly startedBy?: string | null;
489
+ readonly startedAt: string;
490
+ readonly endedAt: string | null;
491
+ readonly status: string;
492
+ /** Wall clock of the round and of its longest path: with paths in parallel the round lasts as long as the longest (§3.10). */
493
+ readonly wallMs: number | null;
494
+ readonly longestPathMs: number | null;
495
+ readonly timing: StepTiming | null;
496
+ readonly usage: Usage | null;
497
+ readonly steps: readonly RoundStepView[];
498
+ /** What the round produced, by workbench position (§3.3 table), and what served a later step or recall. */
499
+ readonly outputs: readonly { readonly position: string; readonly count: number }[];
500
+ readonly groundwork: readonly { readonly kind: string; readonly count: number }[];
501
+ /** Outputs that served nothing: should be near zero, each with its reason (CKC-23 AC-6). */
502
+ readonly unplaced: { readonly count: number; readonly reasons: readonly string[] };
503
+ /**
504
+ * D103: `synthesis` — the synthesis' outputs and the notes, checked in full and counted apart from the sample. CS:
505
+ * `placement` — the reasons that left an item unplaced and the program's placements, counted apart too.
506
+ */
507
+ readonly spotCheck: { readonly sampled: number; readonly wrong: number; readonly byKind: Readonly<Record<string, number>>; readonly corrected: number; readonly synthesis?: { readonly outputs: number; readonly checked: number; readonly wrong: number }; readonly placement?: { readonly reasons: number; readonly reasonsChecked: number; readonly reasonsWrong: number; readonly programPlacementsSampled: number; readonly programPlacementsWrong: number } } | null;
508
+ /** D103: what the round did with the notes standing from earlier rounds (a deepening, a Follow up); counted live while it runs. */
509
+ readonly standingNotes?: { readonly standing: number; readonly confirmed: number; readonly updated: number; readonly withdrawn: number; readonly open: number } | null;
510
+ readonly ledger: { readonly ms: number; readonly commitsAdded: number } | null;
511
+ /** What the round's end did with the project folder, or why it could not. */
512
+ readonly folder?: string | null;
513
+ /**
514
+ * The sweeps the program added to a takeover's deepening for kinds of question orientation set no sweep for, each with
515
+ * why and the brief it composed (a document of this round, written by no step's job, so no step lists it; CKC-23 AC-4).
516
+ * Absent when the program added none.
517
+ */
518
+ readonly sweepsAdded?: readonly { readonly path: string; readonly why: string; readonly doc: RoundDocRef | null }[];
519
+ /**
520
+ * D99 (Spec §3.3, §3.10, §6.9): the main agent — the stage it is in and the stages it went through, each with its time.
521
+ * Present exactly on rounds run by the main agent; a round from before D99 has none and reads as its steps.
522
+ */
523
+ readonly main?: RoundMainView;
524
+ /** D99: the lanes the main agent sent, in the order sent, each with its question, slots, status and what it read. */
525
+ readonly lanes?: readonly RoundLaneView[];
526
+ /** D99: the coverage check — what it listed as untouched and each account; null until the main agent enters it. */
527
+ readonly coverage?: RoundCoverageView | null;
528
+ /** D99: the missing steps this round's lanes looked for (breakpoint candidates, §2.12), and those its spot-check confirmed. */
529
+ readonly missing?: { readonly looked: number; readonly checked: number };
530
+ }
531
+
532
+ /**
533
+ * D99: the main agent of a round: its job, the stage it is in, and its stages in order (§3.10 the time of each). D103:
534
+ * `handover` once it handed the round over to the synthesis — when, and its Handover document, which opens from the tree.
535
+ */
536
+ export interface RoundMainView {
537
+ readonly jobId: string | null;
538
+ readonly stage: ClerkStage | null;
539
+ readonly handover?: { readonly at: string; readonly doc: RoundDocRef | null } | null;
540
+ readonly stages: readonly { readonly stage: ClerkStage; readonly startedAt: string; readonly endedAt: string | null; readonly timing: StepTiming | null; readonly current: boolean }[];
541
+ }
542
+
543
+ /**
544
+ * D99: a lane as the round tree shows it: what it answers (the first lines of its brief), the slots it writes, the stage it
545
+ * was sent in, its job's status, time and usage (with the jobs it sent), its brief and report, and what it read — counted
546
+ * by the program from its steps' recorded reads, each material once.
547
+ */
548
+ export interface RoundLaneView {
549
+ readonly name: string;
550
+ readonly kind: LaneKind;
551
+ readonly slots: readonly SlotKind[];
552
+ readonly stage: ClerkStage | null;
553
+ readonly sentAt: string | null;
554
+ readonly question: string | null;
555
+ readonly jobId: string | null;
556
+ readonly status: string;
557
+ readonly model: { readonly provider: string; readonly id: string; readonly thinking: string | null } | null;
558
+ readonly startedAt: string | null;
559
+ readonly endedAt: string | null;
560
+ readonly timing: StepTiming | null;
561
+ readonly usage: Usage | null;
562
+ readonly brief: RoundDocRef | null;
563
+ readonly report: RoundDocRef | null;
564
+ readonly read: { readonly files: number; readonly versions: number; readonly commits: number; readonly sessions: number };
565
+ }
566
+
567
+ /** D99: the coverage check of a round: when, whether settled, what the last check listed as untouched, and each account. */
568
+ export interface RoundCoverageView {
569
+ readonly at: string;
570
+ readonly settled: boolean;
571
+ /** Null when the check did not record its listing. */
572
+ readonly untouched: readonly CoverageGroup[] | null;
573
+ readonly accounted: readonly MaterialAccount[];
574
+ }
575
+
576
+ export interface RoundDocView {
577
+ readonly id: string;
578
+ readonly roundId: string;
579
+ readonly kind: RoundDocKind;
580
+ readonly title: string;
581
+ readonly path: string | null;
582
+ readonly markdown: string;
583
+ readonly at: string;
584
+ }
585
+
586
+ // ───────────────────────── §3.11 session drafts ─────────────────────────
587
+
588
+ /** A session as a round step or an object lists it, with the draft of it when there is one (CKC-23 AC-18). */
589
+ export interface SessionDraftRef {
590
+ /** The draft's id; null when the session has not been drafted yet (it is listed, and says so). */
591
+ readonly id: string | null;
592
+ readonly host: string;
593
+ readonly sessionId: string;
594
+ readonly startedAt: string | null;
595
+ readonly endedAt: string | null;
596
+ /** The owner's lines, and how many of them are decisions, confirmations, chat, or not yet classified. */
597
+ readonly ownerLines: number;
598
+ readonly decisions: number;
599
+ readonly confirmations: number;
600
+ readonly chat: number;
601
+ readonly unjudged: number;
602
+ readonly agentSummaries: number;
603
+ /** The sources that hold this session (its message ranges), for its original. */
604
+ readonly sourceIds: readonly string[];
605
+ /** When the draft was last written. */
606
+ readonly at: string | null;
607
+ }
608
+
609
+ /**
610
+ * One session's draft (§3.11, D88) as the owner drills into it: the owner's lines verbatim with their kind, what a
611
+ * confirmation answers and what it confirms, and the agents' intents and reports marked as claims.
612
+ */
613
+ export interface SessionDraftView {
614
+ readonly id: string;
615
+ readonly session: { readonly host: string; readonly sessionId: string; readonly file: string; readonly startedAt: string | null; readonly endedAt: string | null };
616
+ readonly ownerLines: readonly {
617
+ /** Its position in the session (`[n]`) or its ledger message id. */
618
+ readonly ref: string;
619
+ readonly at: string | null;
620
+ /** Verbatim, as the program took it from the session. */
621
+ readonly text: string;
622
+ /** Null: not classified yet. */
623
+ readonly kind: 'Chat' | 'Decision' | 'Confirmation' | null;
624
+ /** A confirmation: the agent message it answers, verbatim. */
625
+ readonly answers: string | null;
626
+ /** A confirmation: what the owner confirmed, in the Keeper's words. */
627
+ readonly confirms: string | null;
628
+ /** The source holding this message, to open the original. */
629
+ readonly sourceId: string | null;
630
+ }[];
631
+ /** The agents' intents and reports: claims, as the agents made them — who and when (§2.4). */
632
+ readonly agentSummary: readonly { readonly at: string | null; readonly who: string; readonly summary: string; readonly basis: 'Claimed' }[];
633
+ readonly counts: { readonly lines: number; readonly chat: number; readonly decisions: number; readonly confirmations: number; readonly unjudged: number };
634
+ readonly sourceIds: readonly string[];
635
+ /** When the draft was last written, and by which jobs of which rounds. */
636
+ readonly at: string;
637
+ readonly writtenBy: readonly { readonly jobId: string | null; readonly roundId: string | null; readonly roundLabel: string | null; readonly at: string }[];
638
+ }
639
+
640
+ // ───────────────────────── §1.17 semantic patches ─────────────────────────
641
+
642
+ /** A semantic patch as the workbench shows it: in `Change log`, and as the details a strike-through points at (CKC-26 AC-4). */
643
+ export interface PatchView {
644
+ readonly id: string;
645
+ /** SP-n, the Keeper's number (§1.17). */
646
+ readonly number: string;
647
+ readonly title: string;
648
+ readonly status: 'Draft' | 'Confirmed' | 'Rejected';
649
+ readonly partial: boolean;
650
+ /** When the supersession happened, from its candidate (§2.11). */
651
+ readonly occurred: Occurred;
652
+ readonly invalidated: string;
653
+ readonly replacedBy: string;
654
+ readonly affects: readonly { readonly id: string; readonly label: string }[];
655
+ readonly affectsText: string;
656
+ readonly mustNotPassAsCurrent: string;
657
+ readonly oldAnchor: EvidenceRef;
658
+ readonly newAnchor: EvidenceRef | null;
659
+ readonly decision: EvidenceRef | null;
660
+ readonly candidate: EvidenceRef;
661
+ readonly writtenToFolder: { readonly path: string; readonly commit: string | null; readonly at: string } | null;
662
+ /** The details (`GET …/patches/:pid` only): the text `pk get SP-n` prints, the same words (context/k-briefs.ts). */
663
+ readonly text?: string;
664
+ }
665
+
666
+ // ───────────────────────── §6.7 Project scope additions ─────────────────────────
667
+
668
+ export interface ScopeKView {
669
+ /** The ledger's coverage (§1.16 "看得见"). */
670
+ readonly ledger: {
671
+ readonly repos: readonly { readonly repo: string; readonly commits: number; /** On the trunk alone, when it differs from all refs. */ readonly trunkCommits?: number | null; readonly branches: number; readonly merges: number; readonly from: string | null; readonly to: string | null; readonly historyFrom: string | null }[];
672
+ /**
673
+ * Every language of the project with how far the ledger goes in it. `code`: for a language of the code, how deep the
674
+ * ledger reads it, the same `CodeLanguageView` the `Code` view says (read by the compiler; by the code engine, with the
675
+ * imports it resolved and those it left unresolved; or not read); absent for prose and data, which are no code.
676
+ */
677
+ readonly languages: readonly { readonly language: string; readonly level: 'symbol' | 'file' | 'file tree'; readonly files: number; readonly code?: CodeLanguageView }[];
678
+ readonly sessions: { readonly read: number; readonly hosts: readonly string[]; readonly missing: readonly { readonly host: string; readonly from: string | null; readonly to: string | null; readonly why: string }[] };
679
+ readonly unversionedDocs: number;
680
+ readonly lastRebuild: { readonly at: string; readonly ms: number } | null;
681
+ /**
682
+ * What the ledger holds without reading it, said rather than left out (QC AY): document versions kept without their
683
+ * text (over the size it reads to, or not text) — reports among them, whose verdicts are not read — and files outside
684
+ * version control too large to read. Absent when there is none.
685
+ */
686
+ readonly notRead?: {
687
+ readonly versionsWithoutText: number;
688
+ readonly paths: readonly string[];
689
+ readonly morePaths: number;
690
+ readonly reports: readonly string[];
691
+ readonly unversionedTooLarge: number;
692
+ readonly unversionedPaths: readonly string[];
693
+ readonly effect: string;
694
+ /** The sizes the ledger reads to (bytes): a document version, a file outside version control. Absent from older servers. */
695
+ readonly documentLimitBytes?: number;
696
+ readonly looseLimitBytes?: number;
697
+ } | null;
698
+ } | null;
699
+ /** Which file is which layer (orientation, §3.3). */
700
+ readonly layers: readonly { readonly path: string; readonly layer: LayerKind; readonly note: string | null; readonly current: boolean }[];
701
+ /** Earlier generations, as orientation recognised them (§2.12). */
702
+ readonly generations: readonly { readonly id: string; readonly name: string; readonly ended: Occurred; readonly endedBy: EvidenceRef }[];
703
+ /** The questions the deepening asks, and the sweeps (§3.7). */
704
+ readonly questions: { readonly roundId: string; readonly docId: string; readonly paths: readonly string[] } | null;
705
+ /** The `Project folder` standing authorization and its last write (§1.14, §1.17). */
706
+ readonly projectFolder: { readonly granted: boolean; readonly path: string | null; readonly commits: boolean; readonly lastWrite: { readonly at: string; readonly commit: string | null } | null; readonly authorizationId: string | null } | null;
707
+ }