perttool 0.10.6 → 0.11.1

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 (241) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/README.md +273 -609
  3. package/dist/application/cli-facade.d.ts +4 -10
  4. package/dist/application/cli-facade.d.ts.map +1 -1
  5. package/dist/application/cli-facade.js +1 -1
  6. package/dist/application/cli-facade.js.map +1 -1
  7. package/dist/application/contract10-candidate.d.ts +33 -0
  8. package/dist/application/contract10-candidate.d.ts.map +1 -0
  9. package/dist/application/contract10-candidate.js +38 -0
  10. package/dist/application/contract10-candidate.js.map +1 -0
  11. package/dist/application/contract10-planning-history.d.ts +4 -0
  12. package/dist/application/contract10-planning-history.d.ts.map +1 -0
  13. package/dist/application/contract10-planning-history.js +28 -0
  14. package/dist/application/contract10-planning-history.js.map +1 -0
  15. package/dist/application/contract10-planning.d.ts +61 -0
  16. package/dist/application/contract10-planning.d.ts.map +1 -0
  17. package/dist/application/contract10-planning.js +165 -0
  18. package/dist/application/contract10-planning.js.map +1 -0
  19. package/dist/application/contract10-runtime.d.ts +185 -0
  20. package/dist/application/contract10-runtime.d.ts.map +1 -0
  21. package/dist/application/contract10-runtime.js +236 -0
  22. package/dist/application/contract10-runtime.js.map +1 -0
  23. package/dist/application/contract8-milestone-acceptance.d.ts +6 -22
  24. package/dist/application/contract8-milestone-acceptance.d.ts.map +1 -1
  25. package/dist/application/contract8-milestone-acceptance.js +21 -99
  26. package/dist/application/contract8-milestone-acceptance.js.map +1 -1
  27. package/dist/application/contract8-milestone-read.d.ts +25 -0
  28. package/dist/application/contract8-milestone-read.d.ts.map +1 -0
  29. package/dist/application/contract8-milestone-read.js +111 -0
  30. package/dist/application/contract8-milestone-read.js.map +1 -0
  31. package/dist/application/contract9-assurance-evaluate.d.ts +3 -0
  32. package/dist/application/contract9-assurance-evaluate.d.ts.map +1 -0
  33. package/dist/application/contract9-assurance-evaluate.js +75 -0
  34. package/dist/application/contract9-assurance-evaluate.js.map +1 -0
  35. package/dist/application/contract9-assurance.d.ts +1 -2
  36. package/dist/application/contract9-assurance.d.ts.map +1 -1
  37. package/dist/application/contract9-assurance.js +2 -56
  38. package/dist/application/contract9-assurance.js.map +1 -1
  39. package/dist/application/contract9-candidate.d.ts +8 -0
  40. package/dist/application/contract9-candidate.d.ts.map +1 -1
  41. package/dist/application/contract9-candidate.js +36 -11
  42. package/dist/application/contract9-candidate.js.map +1 -1
  43. package/dist/application/contract9-mixed-mutation.d.ts +3 -0
  44. package/dist/application/contract9-mixed-mutation.d.ts.map +1 -1
  45. package/dist/application/contract9-mixed-mutation.js +5 -4
  46. package/dist/application/contract9-mixed-mutation.js.map +1 -1
  47. package/dist/application/contract9-temporal.js +1 -1
  48. package/dist/application/contract9-temporal.js.map +1 -1
  49. package/dist/application/target-actuals-analysis.d.ts.map +1 -1
  50. package/dist/application/target-actuals-analysis.js +10 -6
  51. package/dist/application/target-actuals-analysis.js.map +1 -1
  52. package/dist/application/target-temporal-analysis.d.ts +1 -0
  53. package/dist/application/target-temporal-analysis.d.ts.map +1 -1
  54. package/dist/application/target-temporal-analysis.js +5 -1
  55. package/dist/application/target-temporal-analysis.js.map +1 -1
  56. package/dist/cli.js +761 -87
  57. package/dist/cli.js.map +1 -1
  58. package/dist/command/contract10-discovery.d.ts +17 -0
  59. package/dist/command/contract10-discovery.d.ts.map +1 -0
  60. package/dist/command/contract10-discovery.js +304 -0
  61. package/dist/command/contract10-discovery.js.map +1 -0
  62. package/dist/command/contract10-usage.d.ts +24 -0
  63. package/dist/command/contract10-usage.d.ts.map +1 -0
  64. package/dist/command/contract10-usage.js +49 -0
  65. package/dist/command/contract10-usage.js.map +1 -0
  66. package/dist/core/index.d.ts +11 -2
  67. package/dist/core/index.d.ts.map +1 -1
  68. package/dist/core/index.js +3 -1
  69. package/dist/core/index.js.map +1 -1
  70. package/dist/help/assurance-guide.js +1 -1
  71. package/dist/help/assurance-guide.js.map +1 -1
  72. package/dist/help/contract10-guide.d.ts +10 -0
  73. package/dist/help/contract10-guide.d.ts.map +1 -0
  74. package/dist/help/contract10-guide.js +244 -0
  75. package/dist/help/contract10-guide.js.map +1 -0
  76. package/dist/index.d.ts +18 -8
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +8 -5
  79. package/dist/index.js.map +1 -1
  80. package/dist/milestone-acceptance/advance.d.ts +9 -0
  81. package/dist/milestone-acceptance/advance.d.ts.map +1 -1
  82. package/dist/milestone-acceptance/advance.js +29 -2
  83. package/dist/milestone-acceptance/advance.js.map +1 -1
  84. package/dist/milestone-acceptance/mutation.d.ts +2 -0
  85. package/dist/milestone-acceptance/mutation.d.ts.map +1 -1
  86. package/dist/milestone-acceptance/mutation.js +48 -12
  87. package/dist/milestone-acceptance/mutation.js.map +1 -1
  88. package/dist/model/source-result.d.ts +12 -0
  89. package/dist/model/source-result.d.ts.map +1 -0
  90. package/dist/model/source-result.js +16 -0
  91. package/dist/model/source-result.js.map +1 -0
  92. package/dist/mutation/advance-deletion.d.ts +1 -0
  93. package/dist/mutation/advance-deletion.d.ts.map +1 -1
  94. package/dist/mutation/advance-deletion.js +4 -1
  95. package/dist/mutation/advance-deletion.js.map +1 -1
  96. package/dist/mutation/validated-source.d.ts +30 -0
  97. package/dist/mutation/validated-source.d.ts.map +1 -0
  98. package/dist/mutation/validated-source.js +58 -0
  99. package/dist/mutation/validated-source.js.map +1 -0
  100. package/dist/node/planning-token-store.d.ts +3 -0
  101. package/dist/node/planning-token-store.d.ts.map +1 -0
  102. package/dist/node/planning-token-store.js +90 -0
  103. package/dist/node/planning-token-store.js.map +1 -0
  104. package/dist/parser/document-parser.d.ts +1 -0
  105. package/dist/parser/document-parser.d.ts.map +1 -1
  106. package/dist/parser/document-parser.js +1 -1
  107. package/dist/parser/document-parser.js.map +1 -1
  108. package/dist/perttool-vscode-private-0.0.0-d1578b9.vsix +0 -0
  109. package/dist/planning-pool/advance.d.ts +10 -0
  110. package/dist/planning-pool/advance.d.ts.map +1 -0
  111. package/dist/planning-pool/advance.js +158 -0
  112. package/dist/planning-pool/advance.js.map +1 -0
  113. package/dist/planning-pool/format.d.ts +12 -0
  114. package/dist/planning-pool/format.d.ts.map +1 -0
  115. package/dist/planning-pool/format.js +199 -0
  116. package/dist/planning-pool/format.js.map +1 -0
  117. package/dist/planning-pool/history-guard.d.ts +19 -0
  118. package/dist/planning-pool/history-guard.d.ts.map +1 -0
  119. package/dist/planning-pool/history-guard.js +123 -0
  120. package/dist/planning-pool/history-guard.js.map +1 -0
  121. package/dist/planning-pool/history-types.d.ts +174 -0
  122. package/dist/planning-pool/history-types.d.ts.map +1 -0
  123. package/dist/planning-pool/history-types.js +2 -0
  124. package/dist/planning-pool/history-types.js.map +1 -0
  125. package/dist/planning-pool/history.d.ts +11 -0
  126. package/dist/planning-pool/history.d.ts.map +1 -0
  127. package/dist/planning-pool/history.js +977 -0
  128. package/dist/planning-pool/history.js.map +1 -0
  129. package/dist/planning-pool/human.d.ts +9 -0
  130. package/dist/planning-pool/human.d.ts.map +1 -0
  131. package/dist/planning-pool/human.js +305 -0
  132. package/dist/planning-pool/human.js.map +1 -0
  133. package/dist/planning-pool/intent-types.d.ts +76 -0
  134. package/dist/planning-pool/intent-types.d.ts.map +1 -0
  135. package/dist/planning-pool/intent-types.js +2 -0
  136. package/dist/planning-pool/intent-types.js.map +1 -0
  137. package/dist/planning-pool/intent.d.ts +7 -0
  138. package/dist/planning-pool/intent.d.ts.map +1 -0
  139. package/dist/planning-pool/intent.js +590 -0
  140. package/dist/planning-pool/intent.js.map +1 -0
  141. package/dist/planning-pool/observation-types.d.ts +143 -0
  142. package/dist/planning-pool/observation-types.d.ts.map +1 -0
  143. package/dist/planning-pool/observation-types.js +2 -0
  144. package/dist/planning-pool/observation-types.js.map +1 -0
  145. package/dist/planning-pool/observation.d.ts +8 -0
  146. package/dist/planning-pool/observation.d.ts.map +1 -0
  147. package/dist/planning-pool/observation.js +582 -0
  148. package/dist/planning-pool/observation.js.map +1 -0
  149. package/dist/planning-pool/projection.d.ts +28 -0
  150. package/dist/planning-pool/projection.d.ts.map +1 -0
  151. package/dist/planning-pool/projection.js +148 -0
  152. package/dist/planning-pool/projection.js.map +1 -0
  153. package/dist/planning-pool/public-core.d.ts +32 -0
  154. package/dist/planning-pool/public-core.d.ts.map +1 -0
  155. package/dist/planning-pool/public-core.js +122 -0
  156. package/dist/planning-pool/public-core.js.map +1 -0
  157. package/dist/planning-pool/reshape-normalize.d.ts +15 -0
  158. package/dist/planning-pool/reshape-normalize.d.ts.map +1 -0
  159. package/dist/planning-pool/reshape-normalize.js +688 -0
  160. package/dist/planning-pool/reshape-normalize.js.map +1 -0
  161. package/dist/planning-pool/reshape-token.d.ts +20 -0
  162. package/dist/planning-pool/reshape-token.d.ts.map +1 -0
  163. package/dist/planning-pool/reshape-token.js +193 -0
  164. package/dist/planning-pool/reshape-token.js.map +1 -0
  165. package/dist/planning-pool/reshape-types.d.ts +183 -0
  166. package/dist/planning-pool/reshape-types.d.ts.map +1 -0
  167. package/dist/planning-pool/reshape-types.js +2 -0
  168. package/dist/planning-pool/reshape-types.js.map +1 -0
  169. package/dist/planning-pool/reshape.d.ts +13 -0
  170. package/dist/planning-pool/reshape.d.ts.map +1 -0
  171. package/dist/planning-pool/reshape.js +1434 -0
  172. package/dist/planning-pool/reshape.js.map +1 -0
  173. package/dist/planning-pool/source-lexical.d.ts +30 -0
  174. package/dist/planning-pool/source-lexical.d.ts.map +1 -0
  175. package/dist/planning-pool/source-lexical.js +158 -0
  176. package/dist/planning-pool/source-lexical.js.map +1 -0
  177. package/dist/planning-pool/source-types.d.ts +169 -0
  178. package/dist/planning-pool/source-types.d.ts.map +1 -0
  179. package/dist/planning-pool/source-types.js +2 -0
  180. package/dist/planning-pool/source-types.js.map +1 -0
  181. package/dist/planning-pool/source-values.d.ts +16 -0
  182. package/dist/planning-pool/source-values.d.ts.map +1 -0
  183. package/dist/planning-pool/source-values.js +120 -0
  184. package/dist/planning-pool/source-values.js.map +1 -0
  185. package/dist/planning-pool/source.d.ts +18 -0
  186. package/dist/planning-pool/source.d.ts.map +1 -0
  187. package/dist/planning-pool/source.js +811 -0
  188. package/dist/planning-pool/source.js.map +1 -0
  189. package/dist/planning-pool/window-types.d.ts +133 -0
  190. package/dist/planning-pool/window-types.d.ts.map +1 -0
  191. package/dist/planning-pool/window-types.js +2 -0
  192. package/dist/planning-pool/window-types.js.map +1 -0
  193. package/dist/planning-pool/window.d.ts +6 -0
  194. package/dist/planning-pool/window.d.ts.map +1 -0
  195. package/dist/planning-pool/window.js +625 -0
  196. package/dist/planning-pool/window.js.map +1 -0
  197. package/dist/schema/registry.d.ts +1 -1
  198. package/dist/schema/registry.d.ts.map +1 -1
  199. package/dist/schema/registry.js +17 -3
  200. package/dist/schema/registry.js.map +1 -1
  201. package/dist/temporal-schedule/format.d.ts.map +1 -1
  202. package/dist/temporal-schedule/format.js +4 -54
  203. package/dist/temporal-schedule/format.js.map +1 -1
  204. package/dist/temporal-schedule/source-lexical.d.ts +9 -0
  205. package/dist/temporal-schedule/source-lexical.d.ts.map +1 -1
  206. package/dist/temporal-schedule/source-lexical.js +21 -10
  207. package/dist/temporal-schedule/source-lexical.js.map +1 -1
  208. package/dist/temporal-schedule/source.d.ts.map +1 -1
  209. package/dist/temporal-schedule/source.js +3 -13
  210. package/dist/temporal-schedule/source.js.map +1 -1
  211. package/dist/version.d.ts +1 -1
  212. package/dist/version.js +1 -1
  213. package/package.json +1 -1
  214. package/schemas/{Perttool.AdvanceResult.v3.schema.json → Perttool.AdvanceResult.v4.schema.json} +42 -4
  215. package/schemas/Perttool.AgentGuidanceResult.v1.schema.json +1 -1
  216. package/schemas/Perttool.AnalysisResult.v7.schema.json +1 -1
  217. package/schemas/Perttool.CheckResult.v6.schema.json +1 -1
  218. package/schemas/Perttool.CliError.v1.schema.json +1 -1
  219. package/schemas/Perttool.CommandHelpResult.v1.schema.json +2 -2
  220. package/schemas/Perttool.ExportResult.v1.schema.json +1 -1
  221. package/schemas/Perttool.FormatResult.v1.schema.json +1 -1
  222. package/schemas/Perttool.GuideResult.v1.schema.json +1 -1
  223. package/schemas/Perttool.HistoricalGraphResult.v1.schema.json +1 -1
  224. package/schemas/Perttool.ImportResult.v1.schema.json +1 -1
  225. package/schemas/Perttool.InitResult.v1.schema.json +1 -1
  226. package/schemas/Perttool.MilestoneAcceptanceMigrationResult.v1.schema.json +1 -1
  227. package/schemas/Perttool.MilestoneAcceptanceResult.v1.schema.json +1 -1
  228. package/schemas/Perttool.MutationResult.v6.schema.json +1 -1
  229. package/schemas/Perttool.NextResult.v8.schema.json +7 -4
  230. package/schemas/Perttool.PlanAssuranceResult.v2.schema.json +1 -1
  231. package/schemas/Perttool.PlanningMutationResult.v1.schema.json +567 -0
  232. package/schemas/Perttool.PlanningObservationRequest.v1.schema.json +6 -0
  233. package/schemas/Perttool.PlanningPoolResult.v1.schema.json +469 -0
  234. package/schemas/Perttool.PlanningReshapePreflightResult.v1.schema.json +906 -0
  235. package/schemas/Perttool.PlanningReshapeRequest.v1.schema.json +19 -0
  236. package/schemas/Perttool.ProjectHistoryResult.v1.schema.json +1 -1
  237. package/schemas/Perttool.ProjectResult.v5.schema.json +1 -1
  238. package/schemas/Perttool.SchemaResult.v1.schema.json +1 -1
  239. package/schemas/{Perttool.UnitMigrationResult.v4.schema.json → Perttool.UnitMigrationResult.v5.schema.json} +42 -17
  240. package/schemas/Perttool.VelocityObservationResult.v1.schema.json +1 -1
  241. package/schemas/Perttool.WindowMutationRequest.v1.schema.json +6 -0
@@ -0,0 +1,977 @@
1
+ import { planTargetPlanAssuranceAdvance } from "../assurance/advance.js";
2
+ import { canonicalJson } from "../assurance/canonical.js";
3
+ import { HISTORICAL_GIT_EVIDENCE_LIMITS, } from "../history/git-probe.js";
4
+ import { projectHistoricalTransitionModel, } from "../history/historical-transition.js";
5
+ import { digestDocumentBytes } from "../io/document-file.js";
6
+ import { milestoneAcceptanceBaseText } from "../milestone-acceptance/source.js";
7
+ import { sha256DigestUtf8 } from "../model/sha256.js";
8
+ import { TARGET_GRAMMAR_6_CAPABILITY } from "../parser/document-parser.js";
9
+ import { validateTargetGrammar6Document } from "../semantic/target-validator.js";
10
+ import { scanTemporalDeclarationBlocks, temporalScheduleBaseText, } from "../temporal-schedule/source-lexical.js";
11
+ import { observePlanningPool, PLANNING_OBSERVATION_CORE_CAPABILITY, } from "./observation.js";
12
+ import { planningPoolBaseText, scanPlanningDeclarationBlocks, } from "./source-lexical.js";
13
+ import { parsePlanningPoolSource, PLANNING_POOL_SOURCE_CAPABILITY, } from "./source.js";
14
+ export const PLANNING_HISTORY_CORE_CAPABILITY = Object.freeze({
15
+ id: "perttool.planning-history-core",
16
+ version: 1,
17
+ });
18
+ export const PLANNING_HISTORY_CORE_LIMITS = Object.freeze({
19
+ inspectedCommits: 2_048,
20
+ rawBytesPerSnapshot: 8_388_608,
21
+ aggregateRawSnapshotBytes: 134_217_728,
22
+ derivedEntityRecords: 100_000,
23
+ });
24
+ const qualifiedPattern = /^[A-Za-z][A-Za-z0-9_-]*::[A-Za-z][A-Za-z0-9_-]*$/u;
25
+ function deepFreeze(value) {
26
+ if (typeof value !== "object" || value === null || Object.isFrozen(value))
27
+ return value;
28
+ for (const child of Object.values(value))
29
+ deepFreeze(child);
30
+ return Object.freeze(value);
31
+ }
32
+ function diagnostic(code, message, severity = "warning", data = {}) {
33
+ return Object.freeze({ code, severity, message, data });
34
+ }
35
+ function requireCapability(capability) {
36
+ if (capability !== PLANNING_HISTORY_CORE_CAPABILITY) {
37
+ throw new TypeError("the private planning history Core capability is required");
38
+ }
39
+ }
40
+ function sorted(values) {
41
+ return Object.freeze([...values].sort((left, right) => left < right ? -1 : left > right ? 1 : 0));
42
+ }
43
+ function semanticDigest(value) {
44
+ return sha256DigestUtf8(canonicalJson(value));
45
+ }
46
+ function valueWithoutSourceLocations(value) {
47
+ if (typeof value === "bigint")
48
+ return value.toString();
49
+ if (Array.isArray(value))
50
+ return value.map(valueWithoutSourceLocations);
51
+ if (typeof value !== "object" || value === null)
52
+ return value;
53
+ const result = {};
54
+ for (const [key, child] of Object.entries(value)) {
55
+ if (key === "span" || key.endsWith("Span") || key === "sourceText")
56
+ continue;
57
+ result[key] = valueWithoutSourceLocations(child);
58
+ }
59
+ return result;
60
+ }
61
+ function eventValue(event) {
62
+ return valueWithoutSourceLocations(event);
63
+ }
64
+ function activityValue(activity) {
65
+ return valueWithoutSourceLocations(activity);
66
+ }
67
+ function workValue(work, model) {
68
+ const eventIds = new Set(work.events.map(({ id }) => id));
69
+ const activityIds = new Set(work.activities.map(({ id }) => id));
70
+ return {
71
+ id: work.qualifiedId,
72
+ title: work.title,
73
+ description: work.description?.value ?? null,
74
+ events: model.events.filter(({ id }) => eventIds.has(id)).map(eventValue),
75
+ activities: model.activities.filter(({ id }) => activityIds.has(id)).map(activityValue),
76
+ milestoneLinks: work.milestoneLinks.map(({ qualifiedId }) => qualifiedId),
77
+ taskLinks: work.taskLinks.map(({ qualifiedId }) => qualifiedId),
78
+ dependsOn: work.dependsOn.map(({ qualifiedId }) => qualifiedId),
79
+ };
80
+ }
81
+ function windowValue(window) {
82
+ return {
83
+ id: window.qualifiedId,
84
+ title: window.title,
85
+ objective: window.objective,
86
+ start: valueWithoutSourceLocations(window.start),
87
+ end: valueWithoutSourceLocations(window.end),
88
+ works: window.works.map(({ qualifiedId }) => qualifiedId),
89
+ };
90
+ }
91
+ function workValues(model) {
92
+ return new Map(model.works.map((work) => [work.qualifiedId, semanticDigest(workValue(work, model))]));
93
+ }
94
+ function windowValues(model) {
95
+ return new Map(model.windows.map((window) => [window.qualifiedId, semanticDigest(windowValue(window))]));
96
+ }
97
+ function firstTaskFact(observation, taskId) {
98
+ for (const work of observation.works) {
99
+ const task = work.execution.tasks.find(({ taskId: candidate }) => candidate === taskId);
100
+ if (task !== undefined)
101
+ return task;
102
+ }
103
+ return null;
104
+ }
105
+ function firstMilestoneFact(observation, milestoneId) {
106
+ for (const work of observation.works) {
107
+ const milestone = work.outcome.milestones.find(({ milestoneId: candidate }) => candidate === milestoneId);
108
+ if (milestone !== undefined)
109
+ return milestone;
110
+ }
111
+ return null;
112
+ }
113
+ function relationKey(kind, ownerId, targetId) {
114
+ return `${kind}:${ownerId}->${targetId}`;
115
+ }
116
+ function relationValue(kind, ownerId, targetId, fact) {
117
+ const key = relationKey(kind, ownerId, targetId);
118
+ return Object.freeze({ key, kind, ownerId, targetId, digest: semanticDigest({ kind, ownerId, targetId, fact }) });
119
+ }
120
+ function relationValues(model, observation) {
121
+ const values = [];
122
+ for (const work of model.works) {
123
+ for (const target of work.events)
124
+ values.push(relationValue("work_event", work.qualifiedId, target.qualifiedId, null));
125
+ for (const target of work.activities)
126
+ values.push(relationValue("work_activity", work.qualifiedId, target.qualifiedId, null));
127
+ for (const target of work.dependsOn)
128
+ values.push(relationValue("work_dependency", work.qualifiedId, target.qualifiedId, null));
129
+ for (const target of work.taskLinks) {
130
+ const fact = firstTaskFact(observation, target.qualifiedId);
131
+ values.push(relationValue("work_task_projection", work.qualifiedId, target.qualifiedId, fact));
132
+ }
133
+ for (const target of work.milestoneLinks) {
134
+ const fact = firstMilestoneFact(observation, target.qualifiedId);
135
+ values.push(relationValue("work_milestone_projection", work.qualifiedId, target.qualifiedId, fact));
136
+ }
137
+ }
138
+ for (const window of model.windows) {
139
+ for (const target of window.works) {
140
+ values.push(relationValue("window_membership", window.qualifiedId, target.qualifiedId, null));
141
+ }
142
+ }
143
+ return new Map(values.map((value) => [value.key, value]));
144
+ }
145
+ function planningSemanticDigest(model, works, windows, relations, strict) {
146
+ return semanticDigest({
147
+ projectId: model.documentId,
148
+ workOrder: model.workOrder.map(({ qualifiedId }) => qualifiedId),
149
+ works: [...works.entries()],
150
+ windows: [...windows.entries()],
151
+ relations: [...relations.values()].map(({ key, digest }) => [key, digest]),
152
+ strict: strict.projection.semantic_digest,
153
+ });
154
+ }
155
+ function strictProjection(text) {
156
+ const grammar8 = planningPoolBaseText(text, scanPlanningDeclarationBlocks(text));
157
+ const grammar7 = temporalScheduleBaseText(grammar8, scanTemporalDeclarationBlocks(grammar8));
158
+ const grammar6 = milestoneAcceptanceBaseText(grammar7);
159
+ const validated = validateTargetGrammar6Document(grammar6, TARGET_GRAMMAR_6_CAPABILITY);
160
+ return !validated.ok || validated.validatedDocument === null
161
+ ? null
162
+ : Object.freeze({
163
+ baseText: grammar6,
164
+ projection: projectHistoricalTransitionModel(validated.validatedDocument),
165
+ });
166
+ }
167
+ function selectionPresent(model, request) {
168
+ if (request.selection.kind === "pool")
169
+ return true;
170
+ if (request.selection.kind === "work") {
171
+ const known = new Set(model.works.map(({ qualifiedId }) => qualifiedId));
172
+ return request.selection.work_ids.every((id) => known.has(id));
173
+ }
174
+ if (request.selection.kind === "persisted") {
175
+ const windowId = request.selection.window_id;
176
+ return model.windows.some(({ qualifiedId }) => qualifiedId === windowId);
177
+ }
178
+ const known = new Set(model.works.map(({ qualifiedId }) => qualifiedId));
179
+ return request.selection.work_ids.every((id) => known.has(id));
180
+ }
181
+ function snapshotRequest(request, sourceDigest, selection = request.selection) {
182
+ return Object.freeze({
183
+ ...request,
184
+ source_digest: sourceDigest,
185
+ selection,
186
+ close_dispositions: Object.freeze([]),
187
+ });
188
+ }
189
+ function unavailableExecution(sourceDigest) {
190
+ return Object.freeze({
191
+ source_digest: sourceDigest,
192
+ evidence_state: "unavailable",
193
+ recommended_task_ids: Object.freeze([]),
194
+ startable_task_ids: Object.freeze([]),
195
+ });
196
+ }
197
+ function executionMap(contexts, diagnostics) {
198
+ const result = new Map();
199
+ for (const entry of contexts.historical) {
200
+ if (result.has(entry.commit_id)) {
201
+ diagnostics.push(diagnostic("PTPOOL-114", `duplicate historical execution context ${entry.commit_id}`));
202
+ continue;
203
+ }
204
+ result.set(entry.commit_id, entry.execution);
205
+ }
206
+ return result;
207
+ }
208
+ function snapshotBasis(snapshot) {
209
+ return Object.freeze({
210
+ repositoryId: snapshot.repositoryId,
211
+ repositoryRelativePath: snapshot.repositoryRelativePath,
212
+ repositoryReadSnapshotId: snapshot.repositoryReadSnapshotId,
213
+ commitId: snapshot.commitId,
214
+ parentCommitIds: Object.freeze([...snapshot.parentCommitIds]),
215
+ blobId: snapshot.blobId,
216
+ sourceDigest: snapshot.sourceDigest,
217
+ recordedAt: snapshot.recordedAt,
218
+ isMergeCommit: snapshot.isMergeCommit,
219
+ isEndpoint: snapshot.isEndpoint,
220
+ isLowerBoundary: snapshot.isLowerBoundary,
221
+ });
222
+ }
223
+ function emptyProcessed(snapshot, validity, diagnosticCodes, documentId = null) {
224
+ return Object.freeze({
225
+ output: Object.freeze({
226
+ basis: snapshotBasis(snapshot),
227
+ validity,
228
+ documentId,
229
+ selectionState: "unavailable",
230
+ observation: null,
231
+ globalExecutionEvidence: "unavailable",
232
+ diagnosticCodes: Object.freeze([...diagnosticCodes]),
233
+ }),
234
+ text: null,
235
+ model: null,
236
+ poolObservation: null,
237
+ strict: null,
238
+ semanticDigest: null,
239
+ workValues: new Map(),
240
+ windowValues: new Map(),
241
+ relationValues: new Map(),
242
+ contextUnavailable: true,
243
+ });
244
+ }
245
+ function decodeSnapshot(snapshot) {
246
+ if (snapshot.source === null)
247
+ return null;
248
+ try {
249
+ return new TextDecoder("utf-8", { fatal: true }).decode(snapshot.source);
250
+ }
251
+ catch {
252
+ return null;
253
+ }
254
+ }
255
+ function preparedSnapshotSource(snapshot) {
256
+ if ([snapshot.source, snapshot.sourceDigest, snapshot.blobId].some((value) => value === null)) {
257
+ return emptyProcessed(snapshot, "source_missing", ["PTPOOL-114"]);
258
+ }
259
+ const text = decodeSnapshot(snapshot);
260
+ if (text === null || digestDocumentBytes(snapshot.source) !== snapshot.sourceDigest) {
261
+ return emptyProcessed(snapshot, "source_binding_invalid", ["PTPOOL-114"]);
262
+ }
263
+ const source = parsePlanningPoolSource(text, PLANNING_POOL_SOURCE_CAPABILITY);
264
+ const codes = source.diagnostics.map(({ code }) => code);
265
+ if (!source.ok)
266
+ return emptyProcessed(snapshot, "source_invalid", codes, source.documentId);
267
+ if (source.model === null)
268
+ return emptyProcessed(snapshot, "planning_absent", codes, source.documentId);
269
+ return Object.freeze({ text, model: source.model, diagnosticCodes: Object.freeze(codes) });
270
+ }
271
+ function isProcessedSnapshot(value) {
272
+ return "output" in value;
273
+ }
274
+ function historicalExecutionContext(snapshot, contexts, diagnostics) {
275
+ const supplied = contexts.get(snapshot.commitId);
276
+ const unavailable = supplied === undefined || supplied.source_digest !== snapshot.sourceDigest;
277
+ if (unavailable) {
278
+ diagnostics.push(diagnostic("PTPOOL-114", `global execution evidence is unavailable at ${snapshot.commitId}`));
279
+ }
280
+ return Object.freeze({
281
+ context: unavailable ? unavailableExecution(snapshot.sourceDigest) : supplied,
282
+ unavailable,
283
+ });
284
+ }
285
+ function successfulProcessedSnapshot(snapshot, prepared, request, context, contextUnavailable) {
286
+ const pool = observePlanningPool(prepared.text, snapshotRequest(request, snapshot.sourceDigest, { kind: "pool" }), context, PLANNING_OBSERVATION_CORE_CAPABILITY);
287
+ const strict = strictProjection(prepared.text);
288
+ if (!pool.ok || strict === null) {
289
+ return emptyProcessed(snapshot, "source_invalid", pool.diagnostics.map(({ code }) => code), prepared.model.documentId);
290
+ }
291
+ const present = selectionPresent(prepared.model, request);
292
+ const selected = present
293
+ ? observePlanningPool(prepared.text, snapshotRequest(request, snapshot.sourceDigest), context, PLANNING_OBSERVATION_CORE_CAPABILITY)
294
+ : null;
295
+ if (selected?.ok === false) {
296
+ return emptyProcessed(snapshot, "source_invalid", selected.diagnostics.map(({ code }) => code), prepared.model.documentId);
297
+ }
298
+ const works = workValues(prepared.model);
299
+ const windows = windowValues(prepared.model);
300
+ const relations = relationValues(prepared.model, pool);
301
+ const diagnosticCodes = [...prepared.diagnosticCodes];
302
+ if (contextUnavailable)
303
+ diagnosticCodes.push("PTPOOL-114");
304
+ return Object.freeze({
305
+ output: Object.freeze({
306
+ basis: snapshotBasis(snapshot),
307
+ validity: "planning_valid",
308
+ documentId: prepared.model.documentId,
309
+ selectionState: present ? "observed" : "absent",
310
+ observation: selected,
311
+ globalExecutionEvidence: context.evidence_state,
312
+ diagnosticCodes: Object.freeze(diagnosticCodes),
313
+ }),
314
+ text: prepared.text,
315
+ model: prepared.model,
316
+ poolObservation: pool,
317
+ strict,
318
+ semanticDigest: planningSemanticDigest(prepared.model, works, windows, relations, strict),
319
+ workValues: works,
320
+ windowValues: windows,
321
+ relationValues: relations,
322
+ contextUnavailable,
323
+ });
324
+ }
325
+ function processPlanningSnapshot(snapshot, request, contexts, diagnostics) {
326
+ const prepared = preparedSnapshotSource(snapshot);
327
+ if (isProcessedSnapshot(prepared))
328
+ return prepared;
329
+ const execution = historicalExecutionContext(snapshot, contexts, diagnostics);
330
+ return successfulProcessedSnapshot(snapshot, prepared, request, execution.context, execution.unavailable);
331
+ }
332
+ function objectIdPattern(objectFormat) {
333
+ return objectFormat === "sha1" ? /^[0-9a-f]{40}$/u : /^[0-9a-f]{64}$/u;
334
+ }
335
+ function evidenceReadSnapshotId(evidence) {
336
+ if (evidence.objectFormat === null || evidence.repositoryId === null ||
337
+ evidence.repositoryRelativePath === null || evidence.resolvedEndpoint === null)
338
+ return null;
339
+ const digest = digestDocumentBytes(Buffer.from(JSON.stringify({
340
+ model: "Perttool.HistoricalGitEvidence.v1",
341
+ objectFormat: evidence.objectFormat,
342
+ repositoryId: evidence.repositoryId,
343
+ repositoryRelativePath: evidence.repositoryRelativePath,
344
+ resolvedEndpoint: evidence.resolvedEndpoint,
345
+ resolvedLowerBoundary: evidence.resolvedLowerBoundary,
346
+ snapshots: evidence.snapshots.map((snapshot) => ({
347
+ commitId: snapshot.commitId,
348
+ parentCommitIds: snapshot.parentCommitIds,
349
+ blobId: snapshot.blobId,
350
+ sourceDigest: snapshot.sourceDigest,
351
+ })),
352
+ }), "utf8"));
353
+ return `git-read:${digest}`;
354
+ }
355
+ function evidenceBindingValid(evidence, currentSourceDigest) {
356
+ if (evidence.currentSourceDigest !== currentSourceDigest)
357
+ return false;
358
+ if (evidence.status === "unavailable")
359
+ return true;
360
+ if (!evidenceHeaderValid(evidence))
361
+ return false;
362
+ const idPattern = objectIdPattern(evidence.objectFormat);
363
+ const seen = new Set();
364
+ let aggregate = 0;
365
+ for (const [index, snapshot] of evidence.snapshots.entries()) {
366
+ aggregate += snapshot.source?.byteLength ?? 0;
367
+ if (!snapshotBindingValid(snapshot, evidence, index, idPattern, seen))
368
+ return false;
369
+ seen.add(snapshot.commitId);
370
+ }
371
+ return evidenceEndpointValid(evidence, aggregate);
372
+ }
373
+ function evidenceHeaderValid(evidence) {
374
+ return [
375
+ evidence.ancestryProfile === "first_parent",
376
+ evidence.objectFormat !== null,
377
+ evidence.repositoryId !== null,
378
+ evidence.repositoryReadSnapshotId !== null,
379
+ evidence.repositoryRelativePath !== null,
380
+ evidence.resolvedEndpoint !== null,
381
+ evidence.snapshots.length > 0,
382
+ evidence.snapshots.length === evidence.inspectedCommitIds.length,
383
+ evidenceReadSnapshotId(evidence) === evidence.repositoryReadSnapshotId,
384
+ ].every(Boolean);
385
+ }
386
+ function snapshotBindingValid(snapshot, evidence, index, idPattern, seen) {
387
+ return [
388
+ snapshot.modelVersion === 1,
389
+ snapshot.objectFormat === evidence.objectFormat,
390
+ snapshot.repositoryId === evidence.repositoryId,
391
+ snapshot.repositoryReadSnapshotId === evidence.repositoryReadSnapshotId,
392
+ snapshot.repositoryRelativePath === evidence.repositoryRelativePath,
393
+ evidence.inspectedCommitIds[index] === snapshot.commitId,
394
+ !seen.has(snapshot.commitId),
395
+ idPattern.test(snapshot.commitId),
396
+ snapshot.parentCommitIds.every((id) => idPattern.test(id)),
397
+ snapshot.blobId === null || idPattern.test(snapshot.blobId),
398
+ (snapshot.source === null) === (snapshot.sourceDigest === null),
399
+ (snapshot.source === null) === (snapshot.blobId === null),
400
+ snapshot.source === null || digestDocumentBytes(snapshot.source) === snapshot.sourceDigest,
401
+ ].every(Boolean);
402
+ }
403
+ function evidenceEndpointValid(evidence, aggregate) {
404
+ return [
405
+ aggregate === evidence.aggregateRawSnapshotBytes,
406
+ evidence.snapshots.at(-1)?.commitId === evidence.resolvedEndpoint,
407
+ evidence.snapshots.at(-1)?.isEndpoint === true,
408
+ ].every(Boolean);
409
+ }
410
+ function evidenceWithinLimits(evidence) {
411
+ if (evidence.status === "unavailable")
412
+ return true;
413
+ return evidence.inspectedCommitIds.length <= PLANNING_HISTORY_CORE_LIMITS.inspectedCommits &&
414
+ evidence.snapshots.every(({ source }) => (source?.byteLength ?? 0) <= PLANNING_HISTORY_CORE_LIMITS.rawBytesPerSnapshot) &&
415
+ evidence.aggregateRawSnapshotBytes <= PLANNING_HISTORY_CORE_LIMITS.aggregateRawSnapshotBytes &&
416
+ evidence.limits.inspectedCommits <= PLANNING_HISTORY_CORE_LIMITS.inspectedCommits &&
417
+ evidence.limits.rawBytesPerSnapshot <= PLANNING_HISTORY_CORE_LIMITS.rawBytesPerSnapshot &&
418
+ evidence.limits.aggregateRawSnapshotBytes <= PLANNING_HISTORY_CORE_LIMITS.aggregateRawSnapshotBytes;
419
+ }
420
+ function emptyAxisStates(state) {
421
+ return Object.freeze({
422
+ refinement: state,
423
+ execution: state,
424
+ outcome: state,
425
+ organization: state,
426
+ temporal: state,
427
+ closeDisposition: state,
428
+ });
429
+ }
430
+ function completeAxisStates() {
431
+ return Object.freeze({
432
+ refinement: "complete",
433
+ execution: "complete",
434
+ outcome: "complete",
435
+ organization: "complete",
436
+ temporal: "complete",
437
+ closeDisposition: "complete",
438
+ });
439
+ }
440
+ function evidenceBasis(evidence, sourceDigest, state, continuityQualified) {
441
+ if (!evidence.ok) {
442
+ return Object.freeze({
443
+ mode: "historical",
444
+ state,
445
+ ancestryProfile: "first_parent",
446
+ repositoryId: null,
447
+ repositoryRelativePath: null,
448
+ repositoryReadSnapshotId: null,
449
+ requestedEndpoint: "HEAD",
450
+ resolvedEndpoint: null,
451
+ requestedLowerBoundary: null,
452
+ resolvedLowerBoundary: null,
453
+ currentSourceDigest: sourceDigest,
454
+ limits: HISTORICAL_GIT_EVIDENCE_LIMITS,
455
+ causes: Object.freeze([]),
456
+ continuityQualified,
457
+ forcedLossDistinguishable: false,
458
+ });
459
+ }
460
+ return Object.freeze({
461
+ mode: "historical",
462
+ state,
463
+ ancestryProfile: "first_parent",
464
+ repositoryId: evidence.repositoryId,
465
+ repositoryRelativePath: evidence.repositoryRelativePath,
466
+ repositoryReadSnapshotId: evidence.repositoryReadSnapshotId,
467
+ requestedEndpoint: evidence.requestedEndpoint,
468
+ resolvedEndpoint: evidence.resolvedEndpoint,
469
+ requestedLowerBoundary: evidence.requestedLowerBoundary,
470
+ resolvedLowerBoundary: evidence.resolvedLowerBoundary,
471
+ currentSourceDigest: sourceDigest,
472
+ limits: evidence.limits,
473
+ causes: evidence.causes,
474
+ continuityQualified,
475
+ forcedLossDistinguishable: false,
476
+ });
477
+ }
478
+ function makeEpoch(commitId, digest) {
479
+ return { ordinal: 1, firstObservedCommitId: commitId, lastObservedCommitId: commitId, valueDigest: digest };
480
+ }
481
+ function updateOccurrence(occurrence, commitId, digest) {
482
+ occurrence.lastObservedCommitId = commitId;
483
+ occurrence.observedCommitIds.push(commitId);
484
+ const epoch = occurrence.epochs.at(-1);
485
+ if (epoch.valueDigest === digest)
486
+ epoch.lastObservedCommitId = commitId;
487
+ else
488
+ occurrence.epochs.push({
489
+ ordinal: occurrence.epochs.length + 1,
490
+ firstObservedCommitId: commitId,
491
+ lastObservedCommitId: commitId,
492
+ valueDigest: digest,
493
+ });
494
+ }
495
+ function closeActive(active, endedBy, retiredAtCommitId) {
496
+ for (const occurrence of active.values()) {
497
+ occurrence.endedBy = endedBy;
498
+ occurrence.retiredAtCommitId = retiredAtCommitId;
499
+ }
500
+ active.clear();
501
+ }
502
+ function buildOccurrences(snapshots, select, prefix) {
503
+ const active = new Map();
504
+ const occurrences = [];
505
+ const ordinals = new Map();
506
+ const seen = new Set();
507
+ const ambiguous = new Set();
508
+ let previousValid = false;
509
+ let previousProject = null;
510
+ for (const snapshot of snapshots) {
511
+ const valid = snapshot.model !== null && snapshot.output.validity === "planning_valid";
512
+ const project = snapshot.model?.documentId ?? null;
513
+ if (!valid || (previousValid && previousProject !== project)) {
514
+ if (active.size > 0)
515
+ closeActive(active, "gap", null);
516
+ previousValid = false;
517
+ previousProject = project;
518
+ continue;
519
+ }
520
+ const commitId = snapshot.output.basis.commitId;
521
+ const values = select(snapshot);
522
+ if (!previousValid && active.size > 0)
523
+ closeActive(active, "gap", null);
524
+ for (const [id, occurrence] of [...active]) {
525
+ if (!values.has(id)) {
526
+ occurrence.endedBy = "removed";
527
+ occurrence.retiredAtCommitId = commitId;
528
+ active.delete(id);
529
+ }
530
+ }
531
+ for (const [id, raw] of values) {
532
+ const value = typeof raw === "string" ? raw : raw.digest;
533
+ const existing = active.get(id);
534
+ if (existing !== undefined) {
535
+ updateOccurrence(existing, commitId, value);
536
+ continue;
537
+ }
538
+ if (seen.has(id))
539
+ ambiguous.add(id);
540
+ seen.add(id);
541
+ const ordinal = (ordinals.get(id) ?? 0) + 1;
542
+ ordinals.set(id, ordinal);
543
+ const relation = typeof raw === "string" ? null : raw;
544
+ const occurrence = {
545
+ sourceId: id,
546
+ occurrenceId: `${prefix}:${id}:${ordinal}`,
547
+ firstObservedCommitId: commitId,
548
+ lastObservedCommitId: commitId,
549
+ retiredAtCommitId: null,
550
+ endedBy: "historical_endpoint",
551
+ observedCommitIds: [commitId],
552
+ epochs: [makeEpoch(commitId, value)],
553
+ relation,
554
+ };
555
+ occurrences.push(occurrence);
556
+ active.set(id, occurrence);
557
+ }
558
+ previousValid = true;
559
+ previousProject = project;
560
+ }
561
+ return Object.freeze({ occurrences: Object.freeze(occurrences), ambiguousIds: sorted(ambiguous) });
562
+ }
563
+ function epochs(occurrence) {
564
+ return Object.freeze(occurrence.epochs.map((epoch) => Object.freeze({ ...epoch })));
565
+ }
566
+ function workOccurrences(values) {
567
+ return Object.freeze(values.map((value) => Object.freeze({
568
+ occurrenceId: value.occurrenceId,
569
+ workId: value.sourceId,
570
+ firstObservedCommitId: value.firstObservedCommitId,
571
+ lastObservedCommitId: value.lastObservedCommitId,
572
+ retiredAtCommitId: value.retiredAtCommitId,
573
+ endedBy: value.endedBy,
574
+ observedCommitIds: Object.freeze([...value.observedCommitIds]),
575
+ semanticEpochs: epochs(value),
576
+ })));
577
+ }
578
+ function windowOccurrences(values) {
579
+ return Object.freeze(values.map((value) => Object.freeze({
580
+ occurrenceId: value.occurrenceId,
581
+ windowId: value.sourceId,
582
+ firstObservedCommitId: value.firstObservedCommitId,
583
+ lastObservedCommitId: value.lastObservedCommitId,
584
+ retiredAtCommitId: value.retiredAtCommitId,
585
+ endedBy: value.endedBy,
586
+ observedCommitIds: Object.freeze([...value.observedCommitIds]),
587
+ semanticEpochs: epochs(value),
588
+ })));
589
+ }
590
+ function relationOccurrences(values) {
591
+ return Object.freeze(values.map((value) => Object.freeze({
592
+ occurrenceId: value.occurrenceId,
593
+ kind: value.relation.kind,
594
+ ownerId: value.relation.ownerId,
595
+ targetId: value.relation.targetId,
596
+ firstObservedCommitId: value.firstObservedCommitId,
597
+ lastObservedCommitId: value.lastObservedCommitId,
598
+ retiredAtCommitId: value.retiredAtCommitId,
599
+ endedBy: value.endedBy,
600
+ observedCommitIds: Object.freeze([...value.observedCommitIds]),
601
+ factEpochs: epochs(value),
602
+ })));
603
+ }
604
+ function removedIds(before, after) {
605
+ const retained = new Set(after.map(({ id }) => id));
606
+ return sorted(before.map(({ id }) => id).filter((id) => !retained.has(id)));
607
+ }
608
+ function strictCanonicalAdvance(before, after) {
609
+ const planned = planTargetPlanAssuranceAdvance(before.baseText, TARGET_GRAMMAR_6_CAPABILITY, { governance: { intent: "preview" } });
610
+ if (!planned.ok || !planned.changed || planned.updatedText === null || planned.advance === null ||
611
+ planned.assuranceGuard?.status === "blocked")
612
+ return false;
613
+ const validated = validateTargetGrammar6Document(planned.updatedText, TARGET_GRAMMAR_6_CAPABILITY);
614
+ if (!validated.ok || validated.validatedDocument === null)
615
+ return false;
616
+ const candidate = projectHistoricalTransitionModel(validated.validatedDocument);
617
+ return candidate.semantic_digest === after.projection.semantic_digest;
618
+ }
619
+ function sameMap(left, right) {
620
+ return left.size === right.size && [...left].every(([key, value]) => right.get(key) === value);
621
+ }
622
+ function windowWithoutWorks(window) {
623
+ return semanticDigest({
624
+ id: window.qualifiedId,
625
+ title: window.title,
626
+ objective: window.objective,
627
+ start: valueWithoutSourceLocations(window.start),
628
+ end: valueWithoutSourceLocations(window.end),
629
+ });
630
+ }
631
+ function windowCarryOver(window, prior, members) {
632
+ if (prior !== undefined && windowWithoutWorks(prior) !== windowWithoutWorks(window))
633
+ return null;
634
+ const current = new Set(window.works.map(({ qualifiedId }) => qualifiedId));
635
+ if (prior?.works.some(({ qualifiedId }) => !current.has(qualifiedId)) === true)
636
+ return null;
637
+ const previous = new Set(prior?.works.map(({ qualifiedId }) => qualifiedId) ?? []);
638
+ const additions = window.works.filter(({ qualifiedId }) => !previous.has(qualifiedId));
639
+ if (additions.some(({ qualifiedId }) => !members.has(qualifiedId)))
640
+ return null;
641
+ return Object.freeze(additions.map(({ qualifiedId }) => Object.freeze({
642
+ workId: qualifiedId,
643
+ targetWindowId: window.qualifiedId,
644
+ })));
645
+ }
646
+ function closeWindowCandidate(before, after) {
647
+ if ([before.model, after.model, before.strict, after.strict].some((value) => value === null))
648
+ return null;
649
+ const conditions = [
650
+ before.strict.projection.semantic_digest === after.strict.projection.semantic_digest,
651
+ sameMap(before.workValues, after.workValues),
652
+ ];
653
+ if (!conditions.every(Boolean))
654
+ return null;
655
+ const afterIds = new Set(after.model.windows.map(({ qualifiedId }) => qualifiedId));
656
+ const removed = before.model.windows.filter(({ qualifiedId }) => !afterIds.has(qualifiedId));
657
+ return removed.length === 1 ? removed[0] : null;
658
+ }
659
+ function compareCarryOver(before, after, members) {
660
+ const beforeById = new Map(before.windows.map((window) => [window.qualifiedId, window]));
661
+ const carried = [];
662
+ for (const window of after.windows) {
663
+ const values = windowCarryOver(window, beforeById.get(window.qualifiedId), members);
664
+ if (values === null)
665
+ return null;
666
+ carried.push(...values);
667
+ }
668
+ return Object.freeze(carried);
669
+ }
670
+ function compareCarry(left, right) {
671
+ const a = `${left.workId}\u0000${left.targetWindowId}`;
672
+ const b = `${right.workId}\u0000${right.targetWindowId}`;
673
+ return a < b ? -1 : a > b ? 1 : 0;
674
+ }
675
+ function windowCloseObservation(before, after) {
676
+ const closed = closeWindowCandidate(before, after);
677
+ if (closed === null)
678
+ return null;
679
+ const members = new Set(closed.works.map(({ qualifiedId }) => qualifiedId));
680
+ const carried = compareCarryOver(before.model, after.model, members);
681
+ if (carried === null)
682
+ return null;
683
+ const carriedIds = new Set(carried.map(({ workId }) => workId));
684
+ return Object.freeze({
685
+ windowId: closed.qualifiedId,
686
+ fromCommitId: before.output.basis.commitId,
687
+ toCommitId: after.output.basis.commitId,
688
+ memberWorkIds: sorted(members),
689
+ carriedOver: Object.freeze([...carried].sort(compareCarry)),
690
+ unrecordedDispositionWorkIds: sorted([...members].filter((id) => !carriedIds.has(id))),
691
+ exactMutationRequestAvailable: false,
692
+ });
693
+ }
694
+ function keys(map) {
695
+ return new Set(map.keys());
696
+ }
697
+ function added(before, after) {
698
+ return sorted([...after].filter((value) => !before.has(value)));
699
+ }
700
+ function gapTransition(previous, snapshot) {
701
+ return Object.freeze({
702
+ fromCommitId: previous?.output.basis.commitId ?? null,
703
+ toCommitId: snapshot.output.basis.commitId,
704
+ kind: "gap",
705
+ sourceChanged: true,
706
+ semanticChanged: true,
707
+ addedWorkIds: Object.freeze([]), removedWorkIds: Object.freeze([]),
708
+ addedWindowIds: Object.freeze([]), removedWindowIds: Object.freeze([]),
709
+ addedRelationKeys: Object.freeze([]), removedRelationKeys: Object.freeze([]),
710
+ removedTaskIds: Object.freeze([]), removedMilestoneIds: Object.freeze([]),
711
+ strictCanonicalAdvance: false,
712
+ continuity: "gap",
713
+ });
714
+ }
715
+ function baselineTransition(snapshot) {
716
+ return Object.freeze({
717
+ fromCommitId: null,
718
+ toCommitId: snapshot.output.basis.commitId,
719
+ kind: "baseline",
720
+ sourceChanged: true,
721
+ semanticChanged: true,
722
+ addedWorkIds: sorted(snapshot.workValues.keys()), removedWorkIds: Object.freeze([]),
723
+ addedWindowIds: sorted(snapshot.windowValues.keys()), removedWindowIds: Object.freeze([]),
724
+ addedRelationKeys: sorted(snapshot.relationValues.keys()), removedRelationKeys: Object.freeze([]),
725
+ removedTaskIds: Object.freeze([]), removedMilestoneIds: Object.freeze([]),
726
+ strictCanonicalAdvance: false,
727
+ continuity: "continuous",
728
+ });
729
+ }
730
+ function transitionKind(canonical, close, semanticChanged, removedCount) {
731
+ if (canonical)
732
+ return "canonical_advance";
733
+ if (close !== null)
734
+ return "window_close";
735
+ if (!semanticChanged)
736
+ return "representation";
737
+ return removedCount > 0 ? "contraction" : "planning_change";
738
+ }
739
+ function connectedTransition(previous, snapshot) {
740
+ const beforeWork = keys(previous.workValues);
741
+ const afterWork = keys(snapshot.workValues);
742
+ const beforeWindow = keys(previous.windowValues);
743
+ const afterWindow = keys(snapshot.windowValues);
744
+ const beforeRelations = keys(previous.relationValues);
745
+ const afterRelations = keys(snapshot.relationValues);
746
+ const qualify = (id) => `${snapshot.model.documentId}::${id}`;
747
+ const removedTaskIds = removedIds(previous.strict.projection.semantic.tasks, snapshot.strict.projection.semantic.tasks).map(qualify);
748
+ const removedMilestoneIds = removedIds(previous.strict.projection.semantic.milestones, snapshot.strict.projection.semantic.milestones).map(qualify);
749
+ const canonical = strictCanonicalAdvance(previous.strict, snapshot.strict);
750
+ const close = windowCloseObservation(previous, snapshot);
751
+ const removedWorkIds = added(afterWork, beforeWork);
752
+ const removedWindowIds = added(afterWindow, beforeWindow);
753
+ const removedRelationKeys = added(afterRelations, beforeRelations);
754
+ const semanticChanged = previous.semanticDigest !== snapshot.semanticDigest;
755
+ return Object.freeze({
756
+ close,
757
+ transition: Object.freeze({
758
+ fromCommitId: previous.output.basis.commitId,
759
+ toCommitId: snapshot.output.basis.commitId,
760
+ kind: transitionKind(canonical, close, semanticChanged, removedWorkIds.length + removedWindowIds.length + removedRelationKeys.length),
761
+ sourceChanged: previous.output.basis.sourceDigest !== snapshot.output.basis.sourceDigest,
762
+ semanticChanged,
763
+ addedWorkIds: added(beforeWork, afterWork), removedWorkIds,
764
+ addedWindowIds: added(beforeWindow, afterWindow), removedWindowIds,
765
+ addedRelationKeys: added(beforeRelations, afterRelations), removedRelationKeys,
766
+ removedTaskIds, removedMilestoneIds,
767
+ strictCanonicalAdvance: canonical,
768
+ continuity: "continuous",
769
+ }),
770
+ });
771
+ }
772
+ function transitions(snapshots) {
773
+ const result = [];
774
+ const closes = [];
775
+ let previous = null;
776
+ for (const snapshot of snapshots) {
777
+ const valid = snapshot.model !== null && snapshot.strict !== null && snapshot.semanticDigest !== null;
778
+ if (!valid) {
779
+ result.push(gapTransition(previous, snapshot));
780
+ previous = null;
781
+ continue;
782
+ }
783
+ if (previous === null || previous.model?.documentId !== snapshot.model.documentId) {
784
+ result.push(baselineTransition(snapshot));
785
+ previous = snapshot;
786
+ continue;
787
+ }
788
+ const connected = connectedTransition(previous, snapshot);
789
+ result.push(connected.transition);
790
+ if (connected.close !== null)
791
+ closes.push(connected.close);
792
+ previous = snapshot;
793
+ }
794
+ return Object.freeze({ transitions: Object.freeze(result), closes: Object.freeze(closes) });
795
+ }
796
+ function gapCause(snapshot) {
797
+ if (snapshot.output.validity === "planning_absent")
798
+ return "planning_absent";
799
+ if (snapshot.output.validity === "source_missing")
800
+ return "source_missing";
801
+ if (snapshot.output.validity === "source_binding_invalid")
802
+ return "source_binding_invalid";
803
+ return "source_invalid";
804
+ }
805
+ function buildLineage(snapshots, projectId, endpointIsCurrent) {
806
+ const works = buildOccurrences(snapshots, (snapshot) => snapshot.workValues, "PPHW");
807
+ const windows = buildOccurrences(snapshots, (snapshot) => snapshot.windowValues, "PPHN");
808
+ const relations = buildOccurrences(snapshots, (snapshot) => snapshot.relationValues, "PPHR");
809
+ const lastValidCommit = [...snapshots].reverse().find(({ model }) => model !== null)?.output.basis.commitId ?? null;
810
+ for (const collection of [works.occurrences, windows.occurrences, relations.occurrences]) {
811
+ for (const occurrence of collection) {
812
+ if (occurrence.retiredAtCommitId === null && occurrence.endedBy === "historical_endpoint" &&
813
+ endpointIsCurrent && occurrence.lastObservedCommitId === lastValidCommit) {
814
+ occurrence.endedBy = "current_endpoint";
815
+ }
816
+ }
817
+ }
818
+ const transitionResult = transitions(snapshots);
819
+ const gaps = snapshots
820
+ .filter(({ output }) => output.validity !== "planning_valid")
821
+ .map((snapshot) => Object.freeze({
822
+ commitId: snapshot.output.basis.commitId,
823
+ cause: gapCause(snapshot),
824
+ axisStates: emptyAxisStates("unknown"),
825
+ }));
826
+ const ambiguous = new Set([...works.ambiguousIds, ...windows.ambiguousIds]);
827
+ for (const id of ambiguous) {
828
+ const occurrence = [...works.occurrences, ...windows.occurrences].find(({ sourceId }) => sourceId === id);
829
+ if (occurrence !== undefined)
830
+ gaps.push(Object.freeze({
831
+ commitId: occurrence.firstObservedCommitId,
832
+ cause: "missing_or_forced_loss",
833
+ axisStates: emptyAxisStates("unknown"),
834
+ }));
835
+ }
836
+ return deepFreeze({
837
+ projectId,
838
+ workOccurrences: workOccurrences(works.occurrences),
839
+ windowOccurrences: windowOccurrences(windows.occurrences),
840
+ relationOccurrences: relationOccurrences(relations.occurrences),
841
+ transitions: transitionResult.transitions,
842
+ windowCloses: transitionResult.closes,
843
+ gaps,
844
+ ambiguousIdentityIds: sorted(ambiguous),
845
+ });
846
+ }
847
+ function derivedRecordCount(snapshots, lineage) {
848
+ return snapshots.length +
849
+ snapshots.reduce((sum, snapshot) => sum +
850
+ (snapshot.output.observation?.works.length ?? 0) + snapshot.relationValues.size, 0) +
851
+ lineage.workOccurrences.length + lineage.windowOccurrences.length +
852
+ lineage.relationOccurrences.length + lineage.transitions.length +
853
+ lineage.windowCloses.length + lineage.gaps.length;
854
+ }
855
+ function failedResult(sourceDigest, documentId, request, current, evidence, diagnostics) {
856
+ return deepFreeze({
857
+ schemaVersion: "Perttool.PlanningPoolResult.v1",
858
+ historyCapability: "perttool.planning-history-core@1",
859
+ operation: "observe_history",
860
+ ok: false,
861
+ documentId,
862
+ sourceDigest,
863
+ normalizedRequest: request,
864
+ current,
865
+ evidence: evidenceBasis(evidence, sourceDigest, "unavailable", false),
866
+ axisStates: emptyAxisStates("unavailable"),
867
+ snapshots: [],
868
+ lineage: null,
869
+ diagnostics,
870
+ });
871
+ }
872
+ function prepareCurrentObservation(currentText, input, contexts) {
873
+ const sourceDigest = sha256DigestUtf8(currentText);
874
+ const source = parsePlanningPoolSource(currentText, PLANNING_POOL_SOURCE_CAPABILITY);
875
+ const attempted = observePlanningPool(currentText, input, contexts.current, PLANNING_OBSERVATION_CORE_CAPABILITY);
876
+ const request = attempted.normalizedRequest;
877
+ const absent = source.model !== null && request !== null && !selectionPresent(source.model, request);
878
+ const current = Object.freeze({
879
+ state: attempted.ok ? "observed" : absent ? "selection_absent" : "unavailable",
880
+ sourceDigest,
881
+ observation: attempted.ok ? attempted : null,
882
+ overridesHistoricalFacts: true,
883
+ });
884
+ return Object.freeze({
885
+ sourceDigest,
886
+ documentId: source.documentId,
887
+ model: source.model,
888
+ request,
889
+ current,
890
+ diagnostics: attempted.diagnostics,
891
+ valid: source.ok && source.model !== null && request !== null && (attempted.ok || absent),
892
+ });
893
+ }
894
+ function historicalEvidenceDiagnostic(evidence, sourceDigest) {
895
+ if (!evidence.ok) {
896
+ return diagnostic("PTPOOL-114", `historical Git evidence is unavailable: ${evidence.kind}`);
897
+ }
898
+ if (!evidenceWithinLimits(evidence)) {
899
+ return diagnostic("PTPOOL-115", "historical Git evidence exceeds the accepted hard limits", "error");
900
+ }
901
+ if (!evidenceBindingValid(evidence, sourceDigest)) {
902
+ return diagnostic("PTPOOL-111", "historical Git evidence binding is stale or inconsistent", "error");
903
+ }
904
+ return evidence.status === "unavailable"
905
+ ? diagnostic("PTPOOL-114", "historical Git evidence contains no usable snapshot")
906
+ : null;
907
+ }
908
+ function historicalProjection(evidence, current, contexts, diagnostics) {
909
+ const historicalContexts = executionMap(contexts, diagnostics);
910
+ const processed = Object.freeze(evidence.snapshots.map((snapshot) => processPlanningSnapshot(snapshot, current.request, historicalContexts, diagnostics)));
911
+ if (!processed.some(({ model }) => model !== null)) {
912
+ return diagnostic("PTPOOL-114", "historical evidence has no valid Grammar 9 planning snapshot");
913
+ }
914
+ const endpoint = processed.at(-1);
915
+ const endpointIsCurrent = endpoint.output.basis.sourceDigest === current.sourceDigest &&
916
+ endpoint.output.basis.commitId === evidence.resolvedEndpoint;
917
+ const lineage = buildLineage(processed, current.model.documentId, endpointIsCurrent);
918
+ if (derivedRecordCount(processed, lineage) > PLANNING_HISTORY_CORE_LIMITS.derivedEntityRecords) {
919
+ return diagnostic("PTPOOL-115", "historical derived observation records exceed 100000", "error");
920
+ }
921
+ const hasGap = lineage.gaps.length > 0 || processed.some(({ contextUnavailable }) => contextUnavailable);
922
+ const state = evidence.status === "complete" && !hasGap && endpointIsCurrent
923
+ ? "complete"
924
+ : "incomplete";
925
+ if (state === "incomplete") {
926
+ diagnostics.push(diagnostic("PTPOOL-114", "historical planning observation is bounded or incomplete; affected axes remain unknown"));
927
+ }
928
+ return Object.freeze({
929
+ processed,
930
+ lineage,
931
+ state,
932
+ axisStates: state === "complete" ? completeAxisStates() : emptyAxisStates("unknown"),
933
+ continuityQualified: state === "complete" && lineage.ambiguousIdentityIds.length === 0,
934
+ });
935
+ }
936
+ function isProjectionDiagnostic(value) {
937
+ return "code" in value;
938
+ }
939
+ function successfulHistoricalResult(current, evidence, projection, diagnostics) {
940
+ return deepFreeze({
941
+ schemaVersion: "Perttool.PlanningPoolResult.v1",
942
+ historyCapability: "perttool.planning-history-core@1",
943
+ operation: "observe_history",
944
+ ok: true,
945
+ documentId: current.model.documentId,
946
+ sourceDigest: current.sourceDigest,
947
+ normalizedRequest: current.request,
948
+ current: current.current,
949
+ evidence: evidenceBasis(evidence, current.sourceDigest, projection.state, projection.continuityQualified),
950
+ axisStates: projection.axisStates,
951
+ snapshots: projection.processed.map(({ output }) => output),
952
+ lineage: projection.lineage,
953
+ diagnostics,
954
+ });
955
+ }
956
+ export function reconstructPlanningPoolHistory(currentText, input, contexts, gitEvidence, capability) {
957
+ requireCapability(capability);
958
+ const current = prepareCurrentObservation(currentText, input, contexts);
959
+ const diagnostics = [];
960
+ if (!current.valid) {
961
+ diagnostics.push(...current.diagnostics);
962
+ return failedResult(current.sourceDigest, current.documentId, current.request, current.current, gitEvidence, diagnostics);
963
+ }
964
+ const evidenceFailure = historicalEvidenceDiagnostic(gitEvidence, current.sourceDigest);
965
+ if (evidenceFailure !== null || !gitEvidence.ok) {
966
+ if (evidenceFailure !== null)
967
+ diagnostics.push(evidenceFailure);
968
+ return failedResult(current.sourceDigest, current.documentId, current.request, current.current, gitEvidence, diagnostics);
969
+ }
970
+ const projection = historicalProjection(gitEvidence, current, contexts, diagnostics);
971
+ if (isProjectionDiagnostic(projection)) {
972
+ diagnostics.push(projection);
973
+ return failedResult(current.sourceDigest, current.documentId, current.request, current.current, gitEvidence, diagnostics);
974
+ }
975
+ return successfulHistoricalResult(current, gitEvidence, projection, diagnostics);
976
+ }
977
+ //# sourceMappingURL=history.js.map