mirror of
https://github.com/Heretek-AI/IUMBTEMS.git
synced 2026-10-11 21:09:53 +00:00
- 1.0 cutover: the rewrite monorepo lands on main. 1.1.5 through 1.5.0 never published on their own and ship here as 1.6.0, in lockstep for es-core, es-cli and epistemic-swarm (ADR 0001). - Phase 0 (#140): fail-closed seat models, one CLI grammar for the human-only rule, sealed source-cache readers, pinned MCP identity, a registry-generated permission probe suite, one package list. - Phase 1 (#141): research backends with failover, the Scraper-Swarm gateway, callable brainstorm/harvest, research-only runs, the deep-research coordinator, Markdown/HTML dossiers, domain-pack tiers. - Phase 2 (#142): ADR 0002 and the shared approveStage service, masked TUI approvals, the headless runner (JSONL events, metrics, cancel). - Phase 3 (#144): the human-only es-fleet daemon, DAG scheduler, worktree coordinator with a gated integration branch, telemetry bus and watch. - Phase 4 (#146): the loopback web control plane (SolidJS, ADR 0003): dashboard, browser approvals, config preview, evidence explorer. - Phase 5 (#149): telemetry harvest, distillation into proposals, the self-dogfood preset. - Cutover review remediation (#152): CLI approvals bound to the preview with attempt limiting (#143), human-only `factory run` and fleet token, DNS-resolving SSRF guard, value-level secret scrubbing, fleet gc and allocation races, CodeQL #84, boundary-gate gaps, one REPORT.md writer per run mode. Closes #96. Closes #97. Closes #98. Closes #99. Closes #100. Closes #101. Closes #103. Closes #106. Closes #107. Closes #108. Closes #109. Closes #110. Closes #111. Closes #112. Closes #113. Closes #114. Closes #117. Closes #118. Closes #119. Closes #120. Closes #122. Closes #123. Closes #124. Closes #125. Closes #126. Closes #127. Closes #129. Closes #130. Closes #131. Closes #132. Closes #133. Closes #135. Closes #136. Closes #147. Closes #148. Co-Authored-By: Claude Opus 5.5 <[email protected]>
46 lines
2.1 KiB
TypeScript
46 lines
2.1 KiB
TypeScript
// The record of prior-art searches: what es_harvest_prior_art actually found.
|
|
// It lives under .factory/runtime (a control dir no agent may write), so a
|
|
// brainstorm can only cite prior art that a search returned. Records validate
|
|
// on write and on read (#109): a corrupt record is refused, never trusted.
|
|
import path from "node:path"
|
|
import { factoryLayout } from "../layout.ts"
|
|
import { type PriorArtSearch, PriorArtSearchSchema } from "../schema/harvest.ts"
|
|
import { readJson, writeJson } from "../util/fs.ts"
|
|
|
|
export type { PriorArtSearch }
|
|
|
|
const recordFile = (root: string) => path.join(factoryLayout(root).runtime, "harvest", "prior-art.json")
|
|
|
|
export async function readPriorArt(root: string): Promise<PriorArtSearch[]> {
|
|
const raw = (await readJson<unknown[]>(recordFile(root)).catch(() => undefined)) ?? []
|
|
// Corrupt entries are dropped, never trusted; writers are refused outright.
|
|
return raw.flatMap((entry) => {
|
|
const parsed = PriorArtSearchSchema.safeParse(entry)
|
|
return parsed.success ? [parsed.data] : []
|
|
})
|
|
}
|
|
|
|
/** Add searches to the record (latest search per run+idea wins). */
|
|
export async function recordPriorArt(root: string, searches: readonly PriorArtSearch[]): Promise<void> {
|
|
for (const search of searches) {
|
|
const parsed = PriorArtSearchSchema.safeParse(search)
|
|
if (!parsed.success) throw new Error(`invalid prior-art search: ${parsed.error.message}`)
|
|
}
|
|
const keys = new Set(searches.map((search) => `${search.run ?? ""}::${search.idea}`))
|
|
const kept = (await readPriorArt(root)).filter((search) => !keys.has(`${search.run ?? ""}::${search.idea}`))
|
|
await writeJson(recordFile(root), [...kept, ...searches])
|
|
}
|
|
|
|
/**
|
|
* URLs any recorded, successful search returned. A brainstorm run sees its
|
|
* own searches plus legacy global records (written before runs); other runs'
|
|
* searches do not satisfy it.
|
|
*/
|
|
export async function priorArtUrls(root: string, run?: string): Promise<Set<string>> {
|
|
return new Set(
|
|
(await readPriorArt(root))
|
|
.filter((search) => search.status === "ok" && (search.run === undefined || search.run === run))
|
|
.flatMap((search) => search.results.map((result) => result.url)),
|
|
)
|
|
}
|