compounding-loop 0.2.0 → 0.5.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 (149) hide show
  1. package/README.md +19 -3
  2. package/dist/cli/claim.js +84 -0
  3. package/dist/cli/claim.js.map +1 -0
  4. package/dist/cli/draft.js +69 -0
  5. package/dist/cli/draft.js.map +1 -0
  6. package/dist/cli/index.js +284 -1
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/laneRound.js +96 -0
  9. package/dist/cli/laneRound.js.map +1 -0
  10. package/dist/cli/laneStatus.js +3 -1
  11. package/dist/cli/laneStatus.js.map +1 -1
  12. package/dist/cli/lanesInit.js +8 -2
  13. package/dist/cli/lanesInit.js.map +1 -1
  14. package/dist/cli/lock.js +22 -2
  15. package/dist/cli/lock.js.map +1 -1
  16. package/dist/cli/loops.js +7 -0
  17. package/dist/cli/loops.js.map +1 -1
  18. package/dist/cli/next.js +18 -0
  19. package/dist/cli/next.js.map +1 -0
  20. package/dist/cli/pace.js +41 -0
  21. package/dist/cli/pace.js.map +1 -0
  22. package/dist/cli/pause.js +81 -0
  23. package/dist/cli/pause.js.map +1 -0
  24. package/dist/cli/run.js +18 -6
  25. package/dist/cli/run.js.map +1 -1
  26. package/dist/cli/runs.js +118 -0
  27. package/dist/cli/runs.js.map +1 -0
  28. package/dist/cli/schedule.js +177 -0
  29. package/dist/cli/schedule.js.map +1 -0
  30. package/dist/cli/shipCheck.js +59 -0
  31. package/dist/cli/shipCheck.js.map +1 -0
  32. package/dist/core/brief.js +35 -12
  33. package/dist/core/brief.js.map +1 -1
  34. package/dist/core/draftBrief.js +68 -0
  35. package/dist/core/draftBrief.js.map +1 -0
  36. package/dist/core/laneRound.js +63 -0
  37. package/dist/core/laneRound.js.map +1 -0
  38. package/dist/core/lanes.js +15 -2
  39. package/dist/core/lanes.js.map +1 -1
  40. package/dist/core/lanesInit.js +19 -0
  41. package/dist/core/lanesInit.js.map +1 -1
  42. package/dist/core/next.js +34 -0
  43. package/dist/core/next.js.map +1 -0
  44. package/dist/core/parse/changelog.js +41 -0
  45. package/dist/core/parse/changelog.js.map +1 -0
  46. package/dist/core/parse/claim.js +24 -0
  47. package/dist/core/parse/claim.js.map +1 -0
  48. package/dist/core/parse/controlRoom.js +38 -0
  49. package/dist/core/parse/controlRoom.js.map +1 -0
  50. package/dist/core/parse/index.js +17 -0
  51. package/dist/core/parse/index.js.map +1 -0
  52. package/dist/core/parse/markers.js +20 -0
  53. package/dist/core/parse/markers.js.map +1 -0
  54. package/dist/core/parse/outcomes.js +51 -0
  55. package/dist/core/parse/outcomes.js.map +1 -0
  56. package/dist/core/parse/paused.js +26 -0
  57. package/dist/core/parse/paused.js.map +1 -0
  58. package/dist/core/parse/policy.js +56 -0
  59. package/dist/core/parse/policy.js.map +1 -0
  60. package/dist/core/parse/runs.js +132 -0
  61. package/dist/core/parse/runs.js.map +1 -0
  62. package/dist/core/parse/schedule.js +101 -0
  63. package/dist/core/parse/schedule.js.map +1 -0
  64. package/dist/core/parse/steer.js +68 -0
  65. package/dist/core/parse/steer.js.map +1 -0
  66. package/dist/core/parse/task.js +96 -0
  67. package/dist/core/parse/task.js.map +1 -0
  68. package/dist/core/repo.js +18 -8
  69. package/dist/core/repo.js.map +1 -1
  70. package/dist/core/runPrompt.js +8 -2
  71. package/dist/core/runPrompt.js.map +1 -1
  72. package/dist/core/shipCheck.js +45 -0
  73. package/dist/core/shipCheck.js.map +1 -0
  74. package/dist/core/table.js +3 -1
  75. package/dist/core/table.js.map +1 -1
  76. package/dist/server/actionBody.js +54 -0
  77. package/dist/server/actionBody.js.map +1 -0
  78. package/dist/server/checkLabels.js +32 -0
  79. package/dist/server/checkLabels.js.map +1 -0
  80. package/dist/server/claude.js +18 -0
  81. package/dist/server/claude.js.map +1 -0
  82. package/dist/server/controls.js +99 -0
  83. package/dist/server/controls.js.map +1 -0
  84. package/dist/server/data.js +9 -3
  85. package/dist/server/data.js.map +1 -1
  86. package/dist/server/draftInputs.js +33 -0
  87. package/dist/server/draftInputs.js.map +1 -0
  88. package/dist/server/health.js +9 -30
  89. package/dist/server/health.js.map +1 -1
  90. package/dist/server/index.js +77 -0
  91. package/dist/server/index.js.map +1 -1
  92. package/dist/server/laneChecks.js +25 -0
  93. package/dist/server/laneChecks.js.map +1 -0
  94. package/dist/server/laneSchedule.js +15 -0
  95. package/dist/server/laneSchedule.js.map +1 -0
  96. package/dist/server/live/build.js +178 -0
  97. package/dist/server/live/build.js.map +1 -0
  98. package/dist/server/live/github.js +54 -0
  99. package/dist/server/live/github.js.map +1 -0
  100. package/dist/server/live/index.js +11 -0
  101. package/dist/server/live/index.js.map +1 -0
  102. package/dist/server/live/merge.js +16 -0
  103. package/dist/server/live/merge.js.map +1 -0
  104. package/dist/server/live/urls.js +61 -0
  105. package/dist/server/live/urls.js.map +1 -0
  106. package/dist/server/loops.js +263 -41
  107. package/dist/server/loops.js.map +1 -1
  108. package/dist/server/paceNote.js +13 -0
  109. package/dist/server/paceNote.js.map +1 -0
  110. package/dist/server/roundState.js +51 -0
  111. package/dist/server/roundState.js.map +1 -0
  112. package/dist/server/runs.js +144 -0
  113. package/dist/server/runs.js.map +1 -0
  114. package/dist/server/shipped.js +35 -0
  115. package/dist/server/shipped.js.map +1 -0
  116. package/dist/server/static-export.js +22 -1
  117. package/dist/server/static-export.js.map +1 -1
  118. package/dist/server/taskBullets.js +33 -0
  119. package/dist/server/taskBullets.js.map +1 -0
  120. package/dist/server/this-repo.json +2818 -106
  121. package/dist/web/assets/index-BozIcdeb.js +88 -0
  122. package/dist/web/assets/index-Te_olhNA.css +2 -0
  123. package/dist/web/index.html +2 -2
  124. package/method/COMPOUNDING_LOOP.md +26 -0
  125. package/method/retro.md +7 -0
  126. package/package.json +1 -1
  127. package/plugin/.claude-plugin/plugin.json +1 -1
  128. package/plugin/commands/loop-lanes.md +11 -0
  129. package/plugin/commands/loop-next.md +11 -0
  130. package/plugin/commands/loop-pause.md +10 -0
  131. package/runners/github-actions/lanes.yml +55 -2
  132. package/runners/local/README.md +3 -1
  133. package/runners/local/compounding-loop.service +20 -0
  134. package/runners/local/compounding-loop.timer +11 -0
  135. package/runners/routine/README.md +5 -1
  136. package/runners/routine/control-room-prompt.md +4 -14
  137. package/runners/routine/lane-prompt.md +4 -10
  138. package/runners/routine/prompt.md +2 -2
  139. package/templates/lanes/README.md +5 -1
  140. package/templates/lanes/claude-section.md +5 -1
  141. package/templates/lanes/control-run.md +37 -0
  142. package/templates/lanes/lane-run.md +33 -0
  143. package/templates/lanes/schedule.json +4 -0
  144. package/templates/lanes/steer.md +3 -0
  145. package/templates/lanes/task.md +1 -1
  146. package/templates/static-site/.ai/loop-prompt.md +1 -1
  147. package/templates/static-site/CLAUDE.md +2 -0
  148. package/dist/web/assets/index-B16QCSnY.css +0 -2
  149. package/dist/web/assets/index-CS82DKbF.js +0 -49
@@ -0,0 +1,144 @@
1
+ // Pure (no Node imports): turns the per-lane run logs, the cron slots and the commits into the Runs tab's data.
2
+ import { classifyRunSlots, expectedSlots, matchSlots, missedInARow, notDueReason, parseRunLog, parseSteer, trailingIdleRuns } from '../core/parse/index.js';
3
+ /** How far back the Runs tab looks. */
4
+ export const RUNS_WINDOW_HOURS = 48;
5
+ /** How far back the lane × hour grid needs the slots nobody expected a run for. */
6
+ export const GRID_WINDOW_HOURS = 24;
7
+ /** A slot this young may still be running (the log line is written at the end), so it is not "missing" yet. */
8
+ export const SLOT_GRACE_MINUTES = 90;
9
+ /** Missing runs in a row that raise the "lanes are not running" attention item. */
10
+ export const SILENT_STREAK = 3;
11
+ const HOUR = 3_600_000;
12
+ const MINUTE = 60_000;
13
+ /** Slots (ISO, by lane) that no run was expected for, according to `schedule.json`. */
14
+ function notDueSlots(input, from) {
15
+ const runs = new Map(input.lanes.map((l) => [l.name, parseRunLog(input.logs[l.name] ?? '')]));
16
+ const commits = new Map();
17
+ for (const c of input.commits)
18
+ if (c.lane)
19
+ commits.set(c.lane, [...(commits.get(c.lane) ?? []), new Date(c.at)]);
20
+ const classified = classifyRunSlots({
21
+ lanes: input.lanes, runs, schedule: input.schedule ?? { version: 1, lanes: {} }, paused: false, rootDone: input.lanes.length > 0 && input.lanes.every((l) => l.stopped), laneDone: new Set(input.lanes.filter((l) => l.stopped).map((l) => l.name)), now: input.now, from, commits,
22
+ });
23
+ const skipped = new Map(classified.lanes.map((l) => [l.lane, new Set(l.slots.filter((s) => s.kind === 'not-due').map((s) => s.slot))]));
24
+ return { skipped, routinesLookOff: !input.paused && classified.routinesLookOff, classified };
25
+ }
26
+ function laneRuns(lane, input, skipped, kinds) {
27
+ const from = new Date(input.now.getTime() - RUNS_WINDOW_HOURS * HOUR);
28
+ const everLogged = parseRunLog(input.logs[lane.name] ?? '');
29
+ const entries = everLogged.filter((e) => new Date(e.at) > from);
30
+ const own = input.commits.filter((c) => c.lane === lane.name);
31
+ const slots = lane.cron ? expectedSlots(lane.cron, from, input.now) : [];
32
+ const next = lane.cron ? expectedSlots(lane.cron, input.now, new Date(input.now.getTime() + 7 * 24 * HOUR))[0]?.toISOString() : undefined;
33
+ const results = slots.length > 0 ? matchSlots(slots, entries, own.map((c) => new Date(c.at))) : [];
34
+ // Entries that answered no slot (a manual run, or a lane without cron) are runs too.
35
+ const claimed = new Set(results.flatMap((r) => (r.entry ? [r.entry.at] : [])));
36
+ const manual = entries.filter((e) => !claimed.has(e.at)).map((entry) => ({ slot: new Date(entry.at).toISOString(), entry, outcome: outcomeOf(entry) }));
37
+ const graceEnd = input.now.getTime() - SLOT_GRACE_MINUTES * MINUTE;
38
+ const pausedFrom = input.paused ? (input.paused.at?.getTime() ?? -Infinity) : Infinity;
39
+ const settled = results.filter((r) => r.outcome !== 'no-run-recorded' || (!skipped.has(r.slot) && new Date(r.slot).getTime() <= graceEnd && new Date(r.slot).getTime() < pausedFrom));
40
+ // The heat map wants the slots nobody expected a run for (not due, paused, done) of the last day too; they never count as missed.
41
+ // `.ai/PAUSED` is not in the classifier's input here (it would reclassify skipped slots); slots from the pause on read as paused.
42
+ const kindOfSlot = (r) => (!r.entry && r.outcome === 'no-run-recorded' && new Date(r.slot).getTime() >= pausedFrom && !['done'].includes(kinds.get(r.slot) ?? '') ? 'paused' : kinds.get(r.slot));
43
+ const gridFrom = input.now.getTime() - GRID_WINDOW_HOURS * HOUR;
44
+ const quiet = results.filter((r) => !settled.includes(r) && QUIET_KINDS.has(kindOfSlot(r)) && new Date(r.slot).getTime() >= gridFrom);
45
+ const all = [...settled, ...quiet, ...manual].sort((a, b) => a.slot.localeCompare(b.slot));
46
+ const loggedSessions = new Set(entries.flatMap((e) => (e.session ? [sessionKey(e.session)] : [])));
47
+ const runs = all.map((r, i) => {
48
+ const windowStart = new Date(r.slot).getTime();
49
+ const windowEnd = all[i + 1] ? new Date(all[i + 1].slot).getTime() : Infinity;
50
+ const session = r.entry?.session === undefined ? undefined : sessionKey(r.entry.session);
51
+ const inWindow = (c) => at(c) >= windowStart && at(c) < windowEnd;
52
+ // A commit of this run's session belongs to it; a commit of another logged session belongs to that run; the rest go by time.
53
+ const belongs = (c) => (c.session !== undefined && c.session === session) || (inWindow(c) && !(c.session !== undefined && loggedSessions.has(c.session)));
54
+ const commits = own.filter(belongs);
55
+ return {
56
+ lane: lane.name,
57
+ at: new Date(r.slot).toISOString(),
58
+ outcome: r.outcome,
59
+ ...(kindFor(r, kindOfSlot(r)) && { kind: kindFor(r, kindOfSlot(r)) }),
60
+ ...(r.entry && { endedAt: new Date(r.entry.at).toISOString() }),
61
+ units: r.entry?.units ?? [],
62
+ ...(r.entry?.tests && { tests: r.entry.tests }),
63
+ commits,
64
+ ...(r.entry?.note && { note: r.entry.note }),
65
+ };
66
+ });
67
+ return { runs, ...(next && { next }), // A lane that never logged a run or made a commit is new, not silent.
68
+ missed: !lane.stopped && !input.paused && (everLogged.length > 0 || own.length > 0) ? missedInARow(settled) : 0 };
69
+ }
70
+ export const QUIET_KINDS = new Set(['not-due', 'paused', 'done']);
71
+ /** Core's slot kind for a run: classified slots keep theirs, manual runs derive it from their log line. */
72
+ function kindFor(r, kind) {
73
+ if (kind)
74
+ return kind;
75
+ if (!r.entry)
76
+ return undefined;
77
+ return r.outcome === 'tests-failed' ? 'tests-failed' : r.outcome === 'pushed' || r.entry.units.length > 0 ? 'worked' : 'idle';
78
+ }
79
+ const at = (c) => new Date(c.at).getTime();
80
+ const outcomeOf = (e) => (e.tests && e.tests.failed > 0 ? 'tests-failed' : e.pushed ? 'pushed' : 'nothing-pushed');
81
+ /** The last 8 characters of a session id or `Claude-Session:` URL, the key commits and run lines share. */
82
+ export function sessionKey(idOrUrl) {
83
+ return idOrUrl.trim().replace(/\/+$/, '').slice(-8);
84
+ }
85
+ const LIMIT_WINDOW_HOURS = 5;
86
+ /** The status strip's facts from the classified slots and the schedule. Pure. */
87
+ function outcomesOf(input, classified, routinesLookOff) {
88
+ const since = input.now.getTime() - LIMIT_WINDOW_HOURS * HOUR;
89
+ const live = input.lanes.filter((l) => !l.stopped);
90
+ const slots = classified.lanes.filter((l) => live.some((x) => x.name === l.lane)).flatMap((l) => l.slots.map((s) => ({ lane: l.lane, ...s })));
91
+ const sleeping = live.filter((l) => ['sleeping', 'snoozed'].includes(notDueReason(input.schedule?.lanes[l.name], input.now) ?? '')).map((l) => l.name);
92
+ const upcoming = live.flatMap((l) => {
93
+ const entry = input.schedule?.lanes[l.name];
94
+ if (!l.cron || input.paused || entry?.paused || entry?.sleeping)
95
+ return [];
96
+ const from = new Date(Math.max(input.now.getTime(), entry?.notBefore ? Date.parse(entry.notBefore) : 0));
97
+ const slot = expectedSlots(l.cron, from, new Date(from.getTime() + 7 * 24 * HOUR))[0];
98
+ return slot ? [{ lane: l.name, at: slot.toISOString() }] : [];
99
+ }).sort((a, b) => a.at.localeCompare(b.at));
100
+ return {
101
+ limitStops5h: input.paused || routinesLookOff ? 0 : slots.filter((s) => s.kind === 'missed' && new Date(s.slot).getTime() >= since).length,
102
+ running: input.paused ? [] : [...new Set(slots.filter((s) => s.kind === 'running').map((s) => s.lane))],
103
+ sleeping,
104
+ paused: live.filter((l) => input.schedule?.lanes[l.name]?.paused === true).map((l) => l.name),
105
+ routinesLookOff,
106
+ ...(upcoming[0] && { nextDue: upcoming[0] }),
107
+ };
108
+ }
109
+ export function buildRuns(input) {
110
+ const { skipped, routinesLookOff, classified } = notDueSlots(input, new Date(input.now.getTime() - RUNS_WINDOW_HOURS * HOUR));
111
+ const perLane = input.lanes.map((lane) => ({ lane, ...laneRuns(lane, input, skipped.get(lane.name) ?? new Set(), new Map(classified.lanes.find((c) => c.lane === lane.name)?.slots.map((x) => [x.slot, x.kind]) ?? [])) }));
112
+ return {
113
+ runs: perLane.flatMap((l) => l.runs).sort((a, b) => b.at.localeCompare(a.at)),
114
+ nextRuns: perLane.flatMap((l) => (l.next ? [{ lane: l.lane.name, at: l.next }] : [])),
115
+ silentLanes: perLane.filter((l) => l.missed >= SILENT_STREAK).map((l) => ({ lane: l.lane.name, missed: l.missed })),
116
+ routinesLookOff,
117
+ outcomes: outcomesOf(input, classified, routinesLookOff),
118
+ idleRuns: Object.fromEntries(input.lanes.map((l) => [l.name, trailingIdleRuns(parseRunLog(input.logs[l.name] ?? ''))])),
119
+ steer: input.lanes.flatMap((l) => {
120
+ const text = input.steerTexts?.[l.name];
121
+ return text === undefined ? [] : [{ lane: l.name, entries: parseSteer(text) }];
122
+ }),
123
+ };
124
+ }
125
+ /** The attention item for lanes that stopped running, or none. After 6 h of silence the usage-limit advice is wrong, so the "Routines look off" row replaces it. */
126
+ export function silentLanesItem(loopId, silent, since, routinesLookOff = false) {
127
+ if (silent.length === 0 || routinesLookOff)
128
+ return undefined;
129
+ return {
130
+ loopId,
131
+ file: '.ai/lanes.json',
132
+ kind: 'lanes-not-running',
133
+ question: `Lanes are not running: ${silent.map((s) => `${s.lane} (${s.missed} missed)`).join(', ')}. Check your plan's usage limit.`,
134
+ bestGuess: 'Wait for the limit to reset, or run a lane by hand',
135
+ since,
136
+ };
137
+ }
138
+ /** The newest run of any lane, for the fleet card. Missing runs count: they are what the owner needs to see. */
139
+ export function lastRunOf(runs) {
140
+ // Slots nobody expected a run for (kept for the heat map) are not "the last run".
141
+ const newest = runs.find((r) => !(r.kind && QUIET_KINDS.has(r.kind)));
142
+ return newest && { lane: newest.lane, at: newest.at, outcome: newest.outcome };
143
+ }
144
+ //# sourceMappingURL=runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/server/runs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /** Reads npm's package document (`registry.npmjs.org/<name>`); any other shape means the registry could not be read. */
2
+ export function parseNpmPackage(json) {
3
+ if (typeof json !== 'object' || json === null)
4
+ return undefined;
5
+ const { 'dist-tags': tags, versions } = json;
6
+ if (typeof versions !== 'object' || versions === null)
7
+ return undefined;
8
+ const latest = typeof tags === 'object' && tags !== null ? tags.latest : undefined;
9
+ // No `latest` tag (e.g. every version unpublished) is as good as unreadable: the tag alone decides.
10
+ return typeof latest === 'string' ? { latest, versions: Object.keys(versions) } : undefined;
11
+ }
12
+ /** The npm state of one version. */
13
+ export function npmStateOf(version, npm) {
14
+ if (!npm)
15
+ return 'unknown';
16
+ if (npm.latest === version)
17
+ return 'latest';
18
+ return npm.versions.includes(version) ? 'published' : 'not-published';
19
+ }
20
+ /** True once the tag exists (not older than DONE.md, when both dates are known) and npm, if readable, serves this version as `latest`. */
21
+ export function isShipped({ version, tagExists, npm, tagAt, doneAt }) {
22
+ if (!tagExists)
23
+ return false;
24
+ if (tagAt && doneAt && tagAt < doneAt)
25
+ return false;
26
+ return npm === undefined || npm.latest === version;
27
+ }
28
+ /**
29
+ * CHANGELOG releases with their tag and npm state filled in (`Unreleased` has neither). `tags` or `npm` undefined means
30
+ * that source was not checked: the field stays absent so the UI shows no chip instead of a wrong one.
31
+ */
32
+ export function annotateReleases(releases, tags, npm) {
33
+ return releases.map((r) => (/^unreleased$/i.test(r.version) ? r : { ...r, ...(tags && { tag: tags.includes(`v${r.version}`) }), ...(npm && { npm: npmStateOf(r.version, npm) }) }));
34
+ }
35
+ //# sourceMappingURL=shipped.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shipped.js","sourceRoot":"","sources":["../../src/server/shipped.ts"],"names":[],"mappings":"AAYA,wHAAwH;AACxH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAqD,CAAC;IAC9F,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACxE,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAE,IAA6B,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7G,oGAAoG;IACpG,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9F,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAyB;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC5C,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC;AACxE,CAAC;AAYD,0IAA0I;AAC1I,MAAM,UAAU,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAgB;IAChF,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgC,EAAE,IAAmC,EAAE,GAAyB;IAC/H,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACtL,CAAC"}
@@ -1,6 +1,24 @@
1
1
  import { mkdir, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
+ import { DEFAULT_RUNNER } from './settings.js';
4
+ import { withLabel } from './checkLabels.js';
3
5
  import { sortByAttention, toSummary } from './data.js';
6
+ import { CSP } from './static.js';
7
+ /** The only hosts the static site may fetch from, besides itself: the live data path (src/server/live) and npm's registry (release state). */
8
+ export const LIVE_CONNECT_HOSTS = ['https://api.github.com', 'https://raw.githubusercontent.com', 'https://registry.npmjs.org'];
9
+ /** The local server's CSP with `connect-src` widened to the live hosts. Everything else stays identical. */
10
+ export const STATIC_CSP = CSP.replace("connect-src 'self'", `connect-src 'self' ${LIVE_CONNECT_HOSTS.join(' ')}`);
11
+ export const SELF_LIVE_CONFIG = { repo: 'Minntooos/Compounding-Loop', loop: 'compounding-loop', pages: 'https://minntooos.github.io/Compounding-Loop/' };
12
+ /**
13
+ * GitHub Pages cannot set headers, so the CSP goes into a meta tag as the first child of `<head>`.
14
+ * (`frame-ancestors` is ignored in a meta tag; Pages sends its own framing rules.)
15
+ */
16
+ export function staticIndexHtml(html) {
17
+ const meta = `<meta http-equiv="Content-Security-Policy" content="${STATIC_CSP.replace(/; frame-ancestors [^;]+/, '')}">`;
18
+ if (!/<head[^>]*>/i.test(html))
19
+ throw new Error('index.html has no <head>');
20
+ return html.replace(/<head[^>]*>/i, (head) => `${head}\n ${meta}`);
21
+ }
4
22
  /**
5
23
  * The read-only API as plain files, for hosting the demo on GitHub Pages (no server there).
6
24
  * Keys are paths relative to the site root. The web app in static mode fetches these relative URLs.
@@ -12,7 +30,10 @@ export function staticApiFiles(snapshot, version) {
12
30
  for (const loop of snapshot.loops)
13
31
  files.set(`api/loops/${loop.id}.json`, loop);
14
32
  files.set('api/inbox.json', snapshot.inbox);
15
- files.set('api/checks.json', snapshot.checks);
33
+ files.set('api/checks.json', snapshot.checks.map(withLabel));
34
+ // Same body as the demo server's /api/settings; without the file the static site logged a 404 on every visit.
35
+ files.set('api/settings.json', { demo: true, defaultRunner: DEFAULT_RUNNER });
36
+ files.set('live.json', SELF_LIVE_CONFIG);
16
37
  return files;
17
38
  }
18
39
  export async function writeStaticApi(outDir, snapshot, version) {
@@ -1 +1 @@
1
- {"version":3,"file":"static-export.js","sourceRoot":"","sources":["../../src/server/static-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAsB,EAAE,OAAe;IACpE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACzC,KAAK,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC5E,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK;QAAE,KAAK,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAChF,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,KAAK,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,QAAsB,EAAE,OAAe;IAC1F,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"static-export.js","sourceRoot":"","sources":["../../src/server/static-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /** Bullet lines ("- x") directly under the first heading or bold label that matches `label`. */
2
+ export function bulletsUnder(markdown, label) {
3
+ const lines = markdown.split(/\r?\n/);
4
+ const start = lines.findIndex((l) => label.test(l.replace(/^#+\s*|\*\*/g, '').trim()));
5
+ if (start === -1)
6
+ return [];
7
+ const bullets = [];
8
+ for (const line of lines.slice(start + 1)) {
9
+ if (/^#+\s/.test(line))
10
+ break;
11
+ const bullet = /^\s*[-*]\s+(.*\S)\s*$/.exec(line);
12
+ if (bullet?.[1])
13
+ bullets.push(bullet[1]);
14
+ else if (bullets.length > 0 && line.trim() === '')
15
+ break;
16
+ }
17
+ return bullets;
18
+ }
19
+ /** The sentence of a `**Done when:** a; b; c.` line, split into its items (lane task files write the contract inline). */
20
+ function inlineDoneWhen(markdown) {
21
+ const text = /^\*\*done when:?\*\*:?\s*(.+?)\s*$/im.exec(markdown)?.[1];
22
+ return text === undefined ? [] : text.split(/;\s+/).map((item) => item.replace(/\.$/, '').trim()).filter(Boolean);
23
+ }
24
+ /** The done-when items of a task.md (bullets, else the inline sentence); an item only counts as passing once the loop wrote DONE.md. */
25
+ export function contractFromTask(taskText, finished) {
26
+ const bullets = bulletsUnder(taskText, /^done when/i);
27
+ return (bullets.length > 0 ? bullets : inlineDoneWhen(taskText)).map((text) => ({ text, pass: finished }));
28
+ }
29
+ /** One lane's contract, decisions and knowledge from its task.md. */
30
+ export function laneNotesFromTask(lane, taskText, finished) {
31
+ return { lane, contract: contractFromTask(taskText, finished), decisions: bulletsUnder(taskText, /^decisions/i), knowledge: bulletsUnder(taskText, /^confirmed/i) };
32
+ }
33
+ //# sourceMappingURL=taskBullets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskBullets.js","sourceRoot":"","sources":["../../src/server/taskBullets.ts"],"names":[],"mappings":"AAGA,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvF,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM;QAC9B,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;aACpC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,MAAM;IAC3D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,0HAA0H;AAC1H,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,IAAI,GAAG,sCAAsC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACpH,CAAC;AAED,wIAAwI;AACxI,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,QAAiB;IAClE,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtD,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;AAC7G,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,QAAgB,EAAE,QAAiB;IACjF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;AACtK,CAAC"}