@felixdotgo/aidlc-kit 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/DEVELOPMENT.md +14 -0
  2. package/README.md +11 -13
  3. package/dist/assets/.agents/aidlc/docker/Dockerfile.claude +7 -0
  4. package/dist/assets/.agents/aidlc/docker/Dockerfile.codex +9 -0
  5. package/dist/assets/.agents/aidlc/docker/Dockerfile.opencode +8 -0
  6. package/dist/assets/.agents/aidlc/orchestrator.md +1 -1
  7. package/dist/assets/.agents/aidlc/phase-clarify.md +1 -1
  8. package/dist/assets/.agents/aidlc/phase-plan.md +2 -2
  9. package/dist/assets/.agents/aidlc/schemas/config.schema.json +2 -1
  10. package/dist/assets/.agents/aidlc/scripts/lib/loop-authority.mjs +245 -0
  11. package/dist/assets/.agents/aidlc/scripts/lib/loop-commit-message.mjs +45 -0
  12. package/dist/assets/.agents/aidlc/scripts/lib/loop-daemon.mjs +232 -0
  13. package/dist/assets/.agents/aidlc/scripts/lib/loop-drivers.mjs +15 -3
  14. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-cli.mjs +86 -28
  15. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-remote.mjs +7 -0
  16. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet-supervisor.mjs +22 -6
  17. package/dist/assets/.agents/aidlc/scripts/lib/loop-fleet.mjs +40 -15
  18. package/dist/assets/.agents/aidlc/scripts/lib/loop-git.mjs +14 -6
  19. package/dist/assets/.agents/aidlc/scripts/lib/loop-intake.mjs +23 -5
  20. package/dist/assets/.agents/aidlc/scripts/lib/loop-local-workers.mjs +42 -15
  21. package/dist/assets/.agents/aidlc/scripts/lib/loop-runtime.mjs +75 -5
  22. package/dist/assets/.agents/aidlc/scripts/lib/loop-stream.mjs +60 -0
  23. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor-run-local.mjs +142 -5
  24. package/dist/assets/.agents/aidlc/scripts/lib/loop-supervisor.mjs +9 -1
  25. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-docker.mjs +31 -5
  26. package/dist/assets/.agents/aidlc/scripts/lib/loop-worker-image.mjs +64 -0
  27. package/dist/assets/.agents/aidlc/scripts/lib/store.mjs +57 -2
  28. package/dist/assets/.agents/aidlc/scripts/loop-entry.mjs +85 -73
  29. package/dist/assets/.agents/aidlc/scripts/loop-gate.mjs +19 -7
  30. package/dist/assets/.agents/aidlc/scripts/loop.mjs +2 -1
  31. package/dist/assets/.agents/aidlc/templates/design.md +9 -0
  32. package/dist/assets/.agents/aidlc/templates/intent.md +4 -0
  33. package/dist/assets/.agents/aidlc/templates/workplan.md +1 -1
  34. package/dist/assets/.agents/skills/aidlc-plan/SKILL.md +1 -1
  35. package/dist/assets/ui/bulma.min.css +3 -0
  36. package/dist/assets/ui/dashboard.css +414 -0
  37. package/dist/services/aidlc-coordination/Dockerfile +11 -3
  38. package/dist/services/aidlc-coordination/compose.yaml +12 -0
  39. package/dist/services/aidlc-coordination/package-lock.json +3 -1
  40. package/dist/services/aidlc-coordination/package.json +9 -4
  41. package/dist/services/aidlc-coordination/src/lifecycle-core.mjs +57 -2
  42. package/dist/services/aidlc-coordination/src/repository.mjs +66 -0
  43. package/dist/services/aidlc-coordination/src/server.mjs +9 -3
  44. package/dist/services/aidlc-coordination/test/fleet.test.mjs +21 -0
  45. package/dist/services/aidlc-coordination/test/server-health-auth.test.mjs +67 -0
  46. package/dist/src/adapters.d.ts +0 -3
  47. package/dist/src/adapters.js +3 -5
  48. package/dist/src/cli/argv.d.ts +12 -0
  49. package/dist/src/cli/argv.js +62 -0
  50. package/dist/src/cli/commands.d.ts +8 -0
  51. package/dist/src/cli/commands.js +129 -0
  52. package/dist/src/cli/options.d.ts +25 -0
  53. package/dist/src/cli/options.js +32 -0
  54. package/dist/src/cli/prompt.d.ts +9 -0
  55. package/dist/src/cli/prompt.js +66 -0
  56. package/dist/src/cli.js +25 -191
  57. package/dist/src/gate.js +3 -2
  58. package/dist/src/installer.d.ts +14 -7
  59. package/dist/src/installer.js +38 -141
  60. package/dist/src/legacy.js +1 -0
  61. package/dist/src/managed-content.d.ts +7 -0
  62. package/dist/src/managed-content.js +15 -4
  63. package/dist/src/managed-planning.d.ts +65 -0
  64. package/dist/src/managed-planning.js +219 -0
  65. package/dist/src/mcp-setup.js +3 -1
  66. package/dist/src/model/config-contracts.d.ts +65 -0
  67. package/dist/src/model/config-contracts.js +1 -0
  68. package/dist/src/model/install-contracts.d.ts +29 -0
  69. package/dist/src/model/install-contracts.js +1 -0
  70. package/dist/src/model/lifecycle-enums.d.ts +13 -0
  71. package/dist/src/model/lifecycle-enums.js +1 -0
  72. package/dist/src/model/loop.d.ts +20 -0
  73. package/dist/src/model/loop.js +1 -0
  74. package/dist/src/model/manifest.d.ts +16 -0
  75. package/dist/src/model/manifest.js +1 -0
  76. package/dist/src/model/records.d.ts +138 -0
  77. package/dist/src/model/records.js +1 -0
  78. package/dist/src/model.d.ts +11 -264
  79. package/dist/src/model.js +1 -1
  80. package/dist/src/profiles.d.ts +2 -0
  81. package/dist/src/profiles.js +53 -9
  82. package/dist/src/state/archive-record.d.ts +9 -0
  83. package/dist/src/state/archive-record.js +26 -0
  84. package/dist/src/state/commands.d.ts +18 -0
  85. package/dist/src/state/commands.js +27 -0
  86. package/dist/src/state/domain.d.ts +9 -0
  87. package/dist/src/state/domain.js +9 -0
  88. package/dist/src/state/guards.d.ts +7 -0
  89. package/dist/src/state/guards.js +17 -0
  90. package/dist/src/state/io.d.ts +10 -0
  91. package/dist/src/state/io.js +35 -0
  92. package/dist/src/state/items.d.ts +3 -4
  93. package/dist/src/state/items.js +58 -57
  94. package/dist/src/state/lessons.js +14 -7
  95. package/dist/src/state/lifecycle.js +2 -2
  96. package/dist/src/state/lock.js +7 -6
  97. package/dist/src/state/memory.js +24 -12
  98. package/dist/src/state/{archive.js → migrate.js} +7 -7
  99. package/dist/src/state/partition.d.ts +15 -0
  100. package/dist/src/state/partition.js +90 -0
  101. package/dist/src/state/paths.d.ts +11 -0
  102. package/dist/src/state/paths.js +12 -0
  103. package/dist/src/state/render.js +9 -6
  104. package/dist/src/state/store.js +9 -15
  105. package/dist/src/state/transitions.js +9 -7
  106. package/dist/src/state/validate.js +50 -7
  107. package/dist/src/state.d.ts +16 -11
  108. package/dist/src/state.js +16 -11
  109. package/dist/src/task-ui.d.ts +54 -0
  110. package/dist/src/task-ui.js +1570 -0
  111. package/dist/src/upgrade-board.js +10 -10
  112. package/dist/src/upgrade.d.ts +0 -1
  113. package/dist/src/upgrade.js +19 -83
  114. package/dist/src/workflow.js +3 -3
  115. package/docs/README.md +6 -2
  116. package/docs/architecture.md +9 -8
  117. package/docs/command-reference.md +81 -20
  118. package/docs/configuration.md +28 -8
  119. package/docs/coordination-service.md +18 -6
  120. package/docs/design-decisions.md +83 -0
  121. package/docs/development.md +27 -2
  122. package/docs/loop-local-run.md +495 -0
  123. package/docs/loop-runbook.md +235 -0
  124. package/docs/operating-workflow.md +2 -2
  125. package/docs/testing-and-release.md +5 -1
  126. package/docs/troubleshooting.md +125 -0
  127. package/package.json +4 -1
  128. package/dist/src/ledger.d.ts +0 -22
  129. package/dist/src/ledger.js +0 -119
  130. package/dist/src/state/shared.d.ts +0 -29
  131. package/dist/src/state/shared.js +0 -71
  132. package/dist/src/tracker.d.ts +0 -36
  133. package/dist/src/tracker.js +0 -44
  134. /package/dist/src/state/{archive.d.ts → migrate.d.ts} +0 -0
@@ -1,8 +1,18 @@
1
+ import { gates, handoffKinds, phaseGate, phases } from "./domain.js";
2
+ import { assertTaskArtifactPath, idPattern, iso, text } from "./guards.js";
1
3
  import { readyTaskItems } from "./items.js";
2
- import { assertTaskArtifactPath, gates, handoffKinds, idPattern, iso, phases, phaseGate, text } from "./shared.js";
4
+ import { archiveRecordPath } from "./paths.js";
3
5
  const taskStatuses = ["active", "blocked_on_user", "paused", "done", "closed", "superseded"];
4
6
  export const validateLesson = (taskId, lesson) => {
5
- if (!lesson || !idPattern.test(lesson.id) || lesson.taskId !== taskId || !Array.isArray(lesson.areas) || !lesson.areas.length || lesson.areas.some((area) => !text(area)) || !text(lesson.summary) || !text(lesson.prevention) || !text(lesson.example) || !text(lesson.promotion) || !text(lesson.source) || !iso(lesson.recordedAt))
7
+ if (!lesson)
8
+ throw new Error(`Invalid lesson: ${taskId}`);
9
+ if (!idPattern.test(lesson.id) || lesson.taskId !== taskId)
10
+ throw new Error(`Invalid lesson: ${taskId}`);
11
+ if (!Array.isArray(lesson.areas) || !lesson.areas.length || lesson.areas.some((area) => !text(area)))
12
+ throw new Error(`Invalid lesson: ${taskId}`);
13
+ if (!text(lesson.summary) || !text(lesson.prevention) || !text(lesson.example))
14
+ throw new Error(`Invalid lesson: ${taskId}`);
15
+ if (!text(lesson.promotion) || !text(lesson.source) || !iso(lesson.recordedAt))
6
16
  throw new Error(`Invalid lesson: ${taskId}`);
7
17
  };
8
18
  export const validateTask = (id, task) => {
@@ -23,7 +33,13 @@ export const validateTask = (id, task) => {
23
33
  if (task.tasks.some((item) => !item.id || !item.label || !["todo", "in_progress", "done", "deferred"].includes(item.status)))
24
34
  throw new Error(`Invalid execution tasks: ${id}`);
25
35
  readyTaskItems(task);
26
- if (task.evidence.some((item) => !["approval", "spec", "test", "lint", "review", "diagnostic"].includes(item.kind) || !["pass", "fail", "skip"].includes(item.result) || !item.source || !iso(item.recordedAt) || (item.area !== undefined && !text(item.area)) || (item.gate !== undefined && !gates.includes(item.gate)) || (item.kind === "approval" && (!item.gate || item.gate === "none"))))
36
+ if (task.evidence.some((item) => !["approval", "spec", "test", "lint", "review", "diagnostic"].includes(item.kind) ||
37
+ !["pass", "fail", "skip"].includes(item.result) ||
38
+ !item.source ||
39
+ !iso(item.recordedAt) ||
40
+ (item.area !== undefined && !text(item.area)) ||
41
+ (item.gate !== undefined && !gates.includes(item.gate)) ||
42
+ (item.kind === "approval" && (!item.gate || item.gate === "none"))))
27
43
  throw new Error(`Invalid evidence: ${id}`);
28
44
  const lessonIds = new Set();
29
45
  for (const lesson of task.lessons ?? []) {
@@ -32,11 +48,21 @@ export const validateTask = (id, task) => {
32
48
  throw new Error(`Duplicate lesson id: ${id}/${lesson.id}`);
33
49
  lessonIds.add(lesson.id);
34
50
  }
35
- if (task.lessonDisposition && (!["captured", "none"].includes(task.lessonDisposition.status) || !text(task.lessonDisposition.source) || !iso(task.lessonDisposition.recordedAt) || (task.lessonDisposition.status === "captured" && !(task.lessons?.length)) || (task.lessonDisposition.status === "none" && (Boolean(task.lessons?.length) || !text(task.lessonDisposition.reason)))))
51
+ if (task.lessonDisposition && (!["captured", "none"].includes(task.lessonDisposition.status) ||
52
+ !text(task.lessonDisposition.source) ||
53
+ !iso(task.lessonDisposition.recordedAt) ||
54
+ (task.lessonDisposition.status === "captured" && !(task.lessons?.length)) ||
55
+ (task.lessonDisposition.status === "none" && (Boolean(task.lessons?.length) || !text(task.lessonDisposition.reason)))))
36
56
  throw new Error(`Invalid lesson disposition: ${id}`);
37
57
  if (task.handoff && (!handoffKinds.includes(task.handoff.kind) || !text(task.handoff.reason) || !text(task.handoff.source) || !iso(task.handoff.recordedAt) || task.status !== "paused"))
38
58
  throw new Error(`Invalid task handoff: ${id}`);
39
- if (task.legacyG2Wait !== undefined && (typeof task.legacyG2Wait !== "object" || Array.isArray(task.legacyG2Wait) || !iso(task.legacyG2Wait.migratedAt) || !text(task.legacyG2Wait.source) || task.phase !== "build" || task.gate !== "G2_codereview" || task.status !== "blocked_on_user"))
59
+ if (task.legacyG2Wait !== undefined && (typeof task.legacyG2Wait !== "object" ||
60
+ Array.isArray(task.legacyG2Wait) ||
61
+ !iso(task.legacyG2Wait.migratedAt) ||
62
+ !text(task.legacyG2Wait.source) ||
63
+ task.phase !== "build" ||
64
+ task.gate !== "G2_codereview" ||
65
+ task.status !== "blocked_on_user"))
40
66
  throw new Error(`Invalid legacy G2 wait marker: ${id}`);
41
67
  if ((task.status === "closed" || task.status === "superseded") !== Boolean(task.closure))
42
68
  throw new Error(`Invalid task closure: ${id}`);
@@ -51,7 +77,21 @@ export const validateTask = (id, task) => {
51
77
  assertTaskArtifactPath(id, path);
52
78
  };
53
79
  const validateArchiveSummary = (id, item) => {
54
- if (!idPattern.test(id) || !item || item.id !== id || !text(item.title) || !["feature", "bug", "refactor", "infra"].includes(item.type) || !phases.includes(item.phase) || !gates.includes(item.gate) || item.gate !== phaseGate(item.phase) || !["done", "closed", "superseded"].includes(item.status) || !["low", "normal", "high", "regulated"].includes(item.risk) || !Array.isArray(item.areas) || !item.areas.length || item.areas.some((area) => !text(area)) || item.record !== `.agents/data/state/archive/${id}.json` || !/^[a-f0-9]{64}$/.test(item.digest) || !Number.isInteger(item.lessonCount) || item.lessonCount < 0 || !iso(item.createdAt) || !iso(item.updatedAt))
80
+ if (!idPattern.test(id))
81
+ throw new Error(`Invalid archived task summary: ${id}`);
82
+ if (!item || item.id !== id || !text(item.title))
83
+ throw new Error(`Invalid archived task summary: ${id}`);
84
+ if (!["feature", "bug", "refactor", "infra"].includes(item.type))
85
+ throw new Error(`Invalid archived task summary: ${id}`);
86
+ if (!phases.includes(item.phase) || !gates.includes(item.gate) || item.gate !== phaseGate(item.phase))
87
+ throw new Error(`Invalid archived task summary: ${id}`);
88
+ if (!["done", "closed", "superseded"].includes(item.status) || !["low", "normal", "high", "regulated"].includes(item.risk))
89
+ throw new Error(`Invalid archived task summary: ${id}`);
90
+ if (!Array.isArray(item.areas) || !item.areas.length || item.areas.some((area) => !text(area)))
91
+ throw new Error(`Invalid archived task summary: ${id}`);
92
+ if (item.record !== archiveRecordPath(id) || !/^[a-f0-9]{64}$/.test(item.digest))
93
+ throw new Error(`Invalid archived task summary: ${id}`);
94
+ if (!Number.isInteger(item.lessonCount) || item.lessonCount < 0 || !iso(item.createdAt) || !iso(item.updatedAt))
55
95
  throw new Error(`Invalid archived task summary: ${id}`);
56
96
  if ((item.status === "superseded") !== Boolean(item.successorTaskId) || (item.status === "closed" && item.successorTaskId) || (item.predecessorTaskId !== undefined && !text(item.predecessorTaskId)))
57
97
  throw new Error(`Invalid archived task links: ${id}`);
@@ -93,7 +133,10 @@ export const validateState = (value) => {
93
133
  if (seen.has(cursor.successorTaskId))
94
134
  throw new Error(`Cyclic successor link: ${id}`);
95
135
  seen.add(cursor.successorTaskId);
96
- cursor = references[cursor.successorTaskId];
136
+ const next = references[cursor.successorTaskId];
137
+ if (!next)
138
+ throw new Error(`Invalid successor link: ${id}`);
139
+ cursor = next;
97
140
  }
98
141
  }
99
142
  return state;
@@ -2,14 +2,19 @@
2
2
  * Facade for the lifecycle-state domain. Behavior-preserving re-export of the
3
3
  * split modules under `src/state/`; import paths from outside remain unchanged.
4
4
  */
5
- export * from "./state/shared.js";
6
- export * from "./state/lock.js";
7
- export * from "./state/items.js";
8
- export * from "./state/transitions.js";
9
- export * from "./state/validate.js";
10
- export * from "./state/store.js";
11
- export * from "./state/memory.js";
12
- export * from "./state/lessons.js";
13
- export * from "./state/archive.js";
14
- export * from "./state/lifecycle.js";
15
- export * from "./state/render.js";
5
+ export { stampLegacyG2Waits, prepareV4Migration, migrateState } from "./state/migrate.js";
6
+ export { taskRecordContent, archivedSummary } from "./state/archive-record.js";
7
+ export { emptyState, legacyG2WaitSource, phases, gates, handoffKinds, terminal, phaseGate, digest } from "./state/domain.js";
8
+ export { iso, text, idPattern, audited, tokens, assertTaskArtifactPath } from "./state/guards.js";
9
+ export { assertNoSymlinkPath, writeAtomic, parseJsonText, parseJsonFile } from "./state/io.js";
10
+ export { type NextAction, readyTaskItems, nextAction } from "./state/items.js";
11
+ export { recordLesson, recordNoLessons, lessonStateDigest, createLessonIndex, rebuildLessonIndex, searchLessons } from "./state/lessons.js";
12
+ export { handoffTask, closeTask, supersedeTask, reopenTask } from "./state/lifecycle.js";
13
+ export { type StateLockOptions, acquireStateLock } from "./state/lock.js";
14
+ export { emptyMemoryRegistry, validateMemoryRegistry, loadMemoryRegistry, saveMemoryRegistry, selectAgenticMemory, promoteAgenticMemory, retireAgenticMemory } from "./state/memory.js";
15
+ export { statePath, lessonIndexPath, memoryRegistryPath, stateLockPath, stateLockGuardPath, archiveRecordPath } from "./state/paths.js";
16
+ export { type TaskSummary, listTaskSummaries, renderWorkplan, renderViews } from "./state/render.js";
17
+ export { pathOverlaps, pathsOverlap, concurrentItemPairs, partitionDiagnostics, loopPartitionStrict, workplanScope } from "./state/partition.js";
18
+ export { loadState, loadTask, saveState } from "./state/store.js";
19
+ export { latestApproval, buildBoundary, hasApproval, hasCurrentBuildApproval, hasAreaVerification, hasVerification, hasReview, type RepairBounds, repairBounds, isLegacyG2Wait, transitionDiagnostics, transitionTask } from "./state/transitions.js";
20
+ export { validateLesson, validateTask, validateState } from "./state/validate.js";
package/dist/src/state.js CHANGED
@@ -2,14 +2,19 @@
2
2
  * Facade for the lifecycle-state domain. Behavior-preserving re-export of the
3
3
  * split modules under `src/state/`; import paths from outside remain unchanged.
4
4
  */
5
- export * from "./state/shared.js";
6
- export * from "./state/lock.js";
7
- export * from "./state/items.js";
8
- export * from "./state/transitions.js";
9
- export * from "./state/validate.js";
10
- export * from "./state/store.js";
11
- export * from "./state/memory.js";
12
- export * from "./state/lessons.js";
13
- export * from "./state/archive.js";
14
- export * from "./state/lifecycle.js";
15
- export * from "./state/render.js";
5
+ export { stampLegacyG2Waits, prepareV4Migration, migrateState } from "./state/migrate.js";
6
+ export { taskRecordContent, archivedSummary } from "./state/archive-record.js";
7
+ export { emptyState, legacyG2WaitSource, phases, gates, handoffKinds, terminal, phaseGate, digest } from "./state/domain.js";
8
+ export { iso, text, idPattern, audited, tokens, assertTaskArtifactPath } from "./state/guards.js";
9
+ export { assertNoSymlinkPath, writeAtomic, parseJsonText, parseJsonFile } from "./state/io.js";
10
+ export { readyTaskItems, nextAction } from "./state/items.js";
11
+ export { recordLesson, recordNoLessons, lessonStateDigest, createLessonIndex, rebuildLessonIndex, searchLessons } from "./state/lessons.js";
12
+ export { handoffTask, closeTask, supersedeTask, reopenTask } from "./state/lifecycle.js";
13
+ export { acquireStateLock } from "./state/lock.js";
14
+ export { emptyMemoryRegistry, validateMemoryRegistry, loadMemoryRegistry, saveMemoryRegistry, selectAgenticMemory, promoteAgenticMemory, retireAgenticMemory } from "./state/memory.js";
15
+ export { statePath, lessonIndexPath, memoryRegistryPath, stateLockPath, stateLockGuardPath, archiveRecordPath } from "./state/paths.js";
16
+ export { listTaskSummaries, renderWorkplan, renderViews } from "./state/render.js";
17
+ export { pathOverlaps, pathsOverlap, concurrentItemPairs, partitionDiagnostics, loopPartitionStrict, workplanScope } from "./state/partition.js";
18
+ export { loadState, loadTask, saveState } from "./state/store.js";
19
+ export { latestApproval, buildBoundary, hasApproval, hasCurrentBuildApproval, hasAreaVerification, hasVerification, hasReview, repairBounds, isLegacyG2Wait, transitionDiagnostics, transitionTask } from "./state/transitions.js";
20
+ export { validateLesson, validateTask, validateState } from "./state/validate.js";
@@ -0,0 +1,54 @@
1
+ import { type IncomingMessage, type ServerResponse, type Server } from "node:http";
2
+ export type UiAuthorityMode = "local" | "fleet";
3
+ export interface UiOptions {
4
+ root: string;
5
+ host: string;
6
+ port: number;
7
+ token?: string;
8
+ /** Loop authority the dashboard reads and acts on; defaults to `.agents/config.json` `loop.mode` (local unless fleet). */
9
+ mode?: UiAuthorityMode;
10
+ /** Fleet reviewer credential held server-side; passed only to the approve child process. */
11
+ reviewerToken?: string;
12
+ }
13
+ export declare const scrubbedEnv: (extra?: Record<string, string>) => NodeJS.ProcessEnv;
14
+ /**
15
+ * Fixed token from a file (`--token-file`, `--reviewer-token-file`) so the browser stays signed in across
16
+ * UI restarts. The file must live outside the project (agents work inside it), be a regular non-symlink
17
+ * file, and be private to the owner (mode 600/400). With `create`, a missing file is created with a
18
+ * random token. The token is never passed to the daemon, lead, or workers.
19
+ */
20
+ export declare const readUiTokenFile: (root: string, path: string, { create }: {
21
+ create: boolean;
22
+ }) => string;
23
+ /** Best-effort browser launch for `aidlc-kit ui --open`; failures are ignored (the URL is printed anyway). */
24
+ export declare const openBrowser: (url: string) => void;
25
+ /** The configured loop authority: `fleet` only when `loop.mode` says so; everything else reads local state. */
26
+ export declare const resolveUiMode: (root: string) => UiAuthorityMode;
27
+ /** DNS-rebinding and CSRF guard: the Host header must name the bound address (any loopback name when
28
+ * bound to loopback; a wildcard bind cannot be pinned and relies on the token and Origin check), and a
29
+ * state-changing request that carries an Origin must be same-origin. */
30
+ export declare const requestAllowed: (options: Pick<UiOptions, "host">, req: IncomingMessage) => {
31
+ ok: true;
32
+ } | {
33
+ ok: false;
34
+ error: string;
35
+ };
36
+ export interface DaemonStatus {
37
+ running: boolean;
38
+ pid: number | null;
39
+ startedAt: string | null;
40
+ }
41
+ /** Reads the singleton loop daemon lock written by `loop-daemon.mjs`. */
42
+ export declare const daemonStatus: (root: string) => DaemonStatus;
43
+ /** Renders a small subset of Markdown to escaped HTML. Exported for tests. */
44
+ export declare const markdownToHtml: (markdown: string) => string;
45
+ /** On a fresh connection the SSE stream replays at most this many lines. */
46
+ export declare const SSE_REPLAY_LINES = 200;
47
+ /** Builds the request handler for the UI server (exported for unit tests). */
48
+ export declare const createUiHandler: (options: UiOptions) => (req: IncomingMessage, res: ServerResponse) => void;
49
+ /** Starts the UI HTTP server and resolves once it is listening. */
50
+ export declare const startUiServer: (options: UiOptions) => Promise<{
51
+ server: Server;
52
+ port: number;
53
+ token: string;
54
+ }>;