nightralph 0.0.54 → 0.0.56
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.
- package/README.md +100 -11
- package/dist/blockers.js +149 -0
- package/dist/blockers.js.map +7 -0
- package/dist/display.js +12 -4
- package/dist/display.js.map +2 -2
- package/dist/docs-templates/issue-tracker.md +9 -1
- package/dist/index.js +740 -137
- package/dist/index.js.map +4 -4
- package/dist/learnings.js +4 -0
- package/dist/learnings.js.map +2 -2
- package/dist/meta.json +69 -16
- package/dist/orchestrator.js +325 -93
- package/dist/orchestrator.js.map +2 -2
- package/dist/resolve.js +98 -9
- package/dist/resolve.js.map +2 -2
- package/dist/review.js +9 -2
- package/dist/review.js.map +2 -2
- package/dist/rules.js +13 -0
- package/dist/rules.js.map +2 -2
- package/dist/skills/to-tickets/SKILL.md +5 -5
- package/dist/src/blockers.d.ts +45 -0
- package/dist/src/blockers.d.ts.map +1 -0
- package/dist/src/display.d.ts +9 -0
- package/dist/src/display.d.ts.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/learnings.d.ts +2 -0
- package/dist/src/learnings.d.ts.map +1 -1
- package/dist/src/orchestrator.d.ts +71 -17
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/dist/src/resolve.d.ts +24 -0
- package/dist/src/resolve.d.ts.map +1 -1
- package/dist/src/review.d.ts +4 -0
- package/dist/src/review.d.ts.map +1 -1
- package/dist/src/rules.d.ts +1 -0
- package/dist/src/rules.d.ts.map +1 -1
- package/dist/src/stats.d.ts +43 -0
- package/dist/src/stats.d.ts.map +1 -0
- package/dist/stats.js +111 -0
- package/dist/stats.js.map +7 -0
- package/package.json +3 -3
package/dist/learnings.js
CHANGED
|
@@ -50,6 +50,8 @@ __name(sanitize, "sanitize");
|
|
|
50
50
|
function renderAgentSummary(run, effort) {
|
|
51
51
|
const effortLine = effort ? `Effort: ${effort}.` : "";
|
|
52
52
|
const exitLine = `Agent exit: ${run.exitCode}.`;
|
|
53
|
+
const subagentsLine = run.subagents === void 0 ? "" : `Subagents: ${run.subagents}.`;
|
|
54
|
+
const costLine = run.costUsd === void 0 ? "" : `Cost: $${run.costUsd.toFixed(2)}.`;
|
|
53
55
|
const itemsText = run.completedItems.length > 0 ? run.completedItems.map(
|
|
54
56
|
(item) => `"${sanitize(item)}"`
|
|
55
57
|
).join(", ") + "." : "none.";
|
|
@@ -57,6 +59,8 @@ function renderAgentSummary(run, effort) {
|
|
|
57
59
|
return [
|
|
58
60
|
effortLine,
|
|
59
61
|
exitLine,
|
|
62
|
+
subagentsLine,
|
|
63
|
+
costLine,
|
|
60
64
|
itemsLine
|
|
61
65
|
].filter(Boolean).join(" ");
|
|
62
66
|
}
|
package/dist/learnings.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/learnings.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n appendFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\n\n// -- Constants and types --\n\nexport const MAX_OWN_ENTRIES = 4\nexport const MAX_ENTRY_CHARS = 4000\nexport const LOG_TAIL_LINES = 40\nexport const NOTES_PATH = '.nightralph/notes.md'\n\nconst SENTINEL_PREFIX = '<!-- nightralph:entry'\nexport const TRUNCATED_MARKER = '[truncated]'\n\nexport const LEARNING_OUTCOMES = [\n 'done',\n 'exit',\n 'tests',\n 'install',\n 'no-commits',\n 'error',\n 'merge',\n] as const\nexport type LearningOutcome = typeof LEARNING_OUTCOMES[number]\n\nexport type LearningEntry = {\n key:string\n attempt:number\n outcome:LearningOutcome\n timedOut:boolean\n // Everything after the sentinel line, trimmed, without\n // the trailing `---` separator\n body:string\n}\n\ntype EntryBase = {\n key:string // ticketKey(feature, num)\n label:string // ticketLabel(ticket), e.g. \"my-feature/04\"\n attempt:number // 0 for merge entries\n now:Date\n}\n\n// What one agent process did: its exit code, the items it reported,\n// whether it was killed at the timeout, and the notes it left.\nexport type AgentRunRecord = {\n exitCode:number\n completedItems:string[]\n timedOut:boolean\n notes:string|null\n}\n\ntype AgentFields = { run:AgentRunRecord; effort?:string }\n\ntype LogTail = { logName:string; logTail:string }\n\nexport type EntryInput = EntryBase&(\n | (AgentFields&{ outcome:'done'|'exit'|'no-commits' })\n | (AgentFields&LogTail&{ outcome:'tests' })\n | (LogTail&{ outcome:'install' })\n | { outcome:'error'; error:string }\n | { outcome:'merge'; stderr:string }\n)\n\nexport type HistorySelection = {\n own:LearningEntry[]\n blockers:LearningEntry[]\n}\n\n// -- Helpers --\n\nfunction encodeKey (key:string):string {\n return key\n .replace(/%/g, '%25')\n .replace(/\\s/g, c => encodeURIComponent(c))\n}\n\nfunction fence (content:string):string {\n const longest = Math.max(\n 0,\n ...[...content.matchAll(/`+/g)].map(m => m[0].length)\n )\n const ticks = '`'.repeat(Math.max(3, longest + 1))\n return `${ticks}\\n${content}\\n${ticks}`\n}\n\nfunction sanitize (text:string|null):string {\n if (!text) return ''\n return text.replace(\n new RegExp(SENTINEL_PREFIX, 'g'),\n '<!-- nightralph-entry'\n )\n}\n\nfunction renderAgentSummary (\n run:AgentRunRecord,\n effort?:string\n):string {\n const effortLine = effort ?\n `Effort: ${effort}.` :\n ''\n\n const exitLine = `Agent exit: ${run.exitCode}.`\n\n const itemsText = run.completedItems.length > 0 ?\n run.completedItems.map(item =>\n `\"${sanitize(item)}\"`\n ).join(', ') + '.' :\n 'none.'\n\n const itemsLine = `Checked items: ${itemsText}`\n\n return [\n effortLine,\n exitLine,\n itemsLine,\n ].filter(Boolean).join(' ')\n}\n\nfunction renderNotesSection (notes:string|null):string {\n const notesSanitized = sanitize(notes)\n return notesSanitized.trim() ?\n `### Agent notes\\n${notesSanitized}` :\n 'The agent left no notes.'\n}\n\nexport function formatDate (date:Date):string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n return `${year}-${month}-${day} ${hours}:${minutes}`\n}\n\nexport function isLearningOutcome (\n value:string\n):value is LearningOutcome {\n return LEARNING_OUTCOMES.some(o => o === value)\n}\n\nexport function renderEntry (input:EntryInput):string {\n const encodedKey = encodeKey(input.key)\n\n const hasRun = 'run' in input\n const timedOut = hasRun && input.run.timedOut\n\n const timedOutStr = timedOut ?\n ' timedout=true' :\n ''\n\n const sentinel =\n `<!-- nightralph:entry ticket=${encodedKey} ` +\n `attempt=${input.attempt} outcome=${input.outcome}` +\n `${timedOutStr} -->`\n\n const timestamp = formatDate(input.now)\n const attemptStr = input.outcome === 'merge' ?\n '' :\n ` attempt ${input.attempt}`\n\n let description:string\n\n switch (input.outcome) {\n case 'done':\n description = 'done'\n break\n case 'exit':\n description = `failed (exit ${input.run.exitCode})`\n break\n case 'tests':\n description = 'failed (tests)'\n break\n case 'install':\n description = 'failed (install)'\n break\n case 'no-commits':\n description = 'no commits'\n break\n case 'error':\n description = 'error'\n break\n case 'merge':\n description = 'merge failed'\n break\n default: {\n const _exhaustive:never = input\n description = _exhaustive\n }\n }\n\n const timedOutPrefix = timedOut ?\n 'timed out, then ' :\n ''\n\n const heading =\n `## ${timestamp} -- ${input.label}${attemptStr} -- ` +\n `${timedOutPrefix}${description}`\n\n let body:string\n\n switch (input.outcome) {\n case 'done':\n case 'exit':\n case 'no-commits': {\n const run = input.run\n const summary = renderAgentSummary(run, input.effort)\n const notesSection = renderNotesSection(run.notes)\n body = summary + '\\n\\n' + notesSection\n break\n }\n case 'tests': {\n const logTail = sanitize(input.logTail)\n const fenced = fence(logTail)\n const summary = renderAgentSummary(\n input.run,\n input.effort\n )\n const notesSection = renderNotesSection(input.run.notes)\n\n const lastNLines =\n `Last ${LOG_TAIL_LINES} lines of ` +\n `\\`${sanitize(input.logName)}\\`:`\n\n body =\n summary + '\\n\\n' +\n 'Test gate failed.\\n' +\n `${lastNLines}\\n` +\n `${fenced}\\n\\n` +\n notesSection\n break\n }\n case 'install': {\n const logTail = sanitize(input.logTail)\n const fenced = fence(logTail)\n\n const lastNLines =\n `Last ${LOG_TAIL_LINES} lines of ` +\n `\\`${sanitize(input.logName)}\\`:`\n\n body =\n 'Install failed.\\n' +\n `${lastNLines}\\n` +\n fenced\n break\n }\n case 'error': {\n const errorText = sanitize(input.error)\n const fenced = fence(errorText)\n body = fenced\n break\n }\n case 'merge': {\n const stderrText = sanitize(input.stderr)\n const fenced = fence(stderrText)\n body = `Merge failed.\\n${fenced}`\n break\n }\n default: {\n const unknown:never = input\n throw new Error(`Unknown outcome: ${JSON.stringify(unknown)}`)\n }\n }\n\n return `${sentinel}\\n${heading}\\n\\n${body}\\n\\n---\\n`\n}\n\nexport function parseEntries (text:string):LearningEntry[] {\n const lines = text.split('\\n').map(line => {\n // Strip trailing \\r for CRLF support\n return line.endsWith('\\r') ? line.slice(0, -1) : line\n })\n const entries:LearningEntry[] = []\n\n let currentSentinel:string|null = null\n let currentBody:string[] = []\n\n const sentinelRegex = /^<!-- nightralph:entry (.*) -->$/\n\n for (const line of lines) {\n const match = line.match(sentinelRegex)\n\n if (match) {\n // Process previous entry if exists\n if (currentSentinel !== null) {\n const entry = parseSentinel(currentSentinel, currentBody)\n if (entry) {\n entries.push(entry)\n }\n }\n\n currentSentinel = match[1]\n currentBody = []\n } else if (currentSentinel !== null) {\n currentBody.push(line)\n }\n }\n\n // Process last entry\n if (currentSentinel !== null) {\n const entry = parseSentinel(currentSentinel, currentBody)\n if (entry) {\n entries.push(entry)\n }\n }\n\n return entries\n}\n\nfunction parseSentinel (\n sentinel:string,\n bodyLines:string[]\n):LearningEntry|null {\n const parts = sentinel.split(/\\s+/).filter(Boolean)\n const attrs:Record<string, string> = {}\n\n for (const part of parts) {\n const idx = part.indexOf('=')\n if (idx > 0) {\n const key = part.slice(0, idx)\n const value = part.slice(idx + 1)\n if (value) {\n attrs[key] = value\n }\n }\n }\n\n // Validate ticket\n let key = attrs.ticket\n if (!key) return null\n\n try {\n key = decodeURIComponent(key)\n } catch (_e) {\n return null\n }\n\n if (!key.trim()) return null\n\n // Validate attempt\n const attemptStr = attrs.attempt\n if (!attemptStr) return null\n\n if (!/^\\d+$/.test(attemptStr)) return null\n const attempt = Number(attemptStr)\n\n // Validate outcome\n const outcome = attrs.outcome\n if (!outcome || !isLearningOutcome(outcome)) return null\n\n // Parse timedOut\n const timedOut = attrs.timedout === 'true'\n\n // Parse body\n let body = bodyLines.join('\\n').trim()\n\n // Remove trailing --- line (full line only)\n const lines = body.split('\\n')\n if (lines.length > 0 && lines[lines.length - 1] === '---') {\n body = lines.slice(0, -1).join('\\n').trim()\n }\n\n return {\n key,\n attempt,\n outcome,\n timedOut,\n body,\n }\n}\n\nexport function selectHistory (\n entries:LearningEntry[],\n opts:{ key:string; blockerKeys:string[] }\n):HistorySelection {\n const own = entries\n .filter(e => e.key === opts.key)\n .slice(-MAX_OWN_ENTRIES)\n\n const blockers = opts.blockerKeys.flatMap(k => {\n const done = entries.filter(e => {\n return e.key === k && e.outcome === 'done'\n })\n const last = done[done.length - 1]\n return last ? [last] : []\n })\n\n return { own, blockers }\n}\n\nexport function renderHistory (selection:HistorySelection):string {\n if (selection.own.length === 0 && selection.blockers.length === 0) {\n return ''\n }\n\n const framing =\n 'These are records of earlier runs. The ticket or spec may ' +\n 'have changed since then; where they disagree, follow the ' +\n 'ticket and spec. Do not repeat an approach these notes say ' +\n 'failed unless you can see why it failed.'\n\n const parts = [framing, '']\n\n if (selection.own.length > 0) {\n parts.push('---- PREVIOUS ATTEMPTS AT THIS TICKET ----')\n parts.push(selection.own.map(e => capEntry(e)).join('\\n\\n'))\n parts.push('')\n }\n\n if (selection.blockers.length > 0) {\n parts.push('---- WHAT THE BLOCKING TICKETS DID ----')\n parts.push(selection.blockers.map(e => capEntry(e)).join('\\n\\n'))\n }\n\n return parts.join('\\n')\n}\n\nfunction capEntry (entry:LearningEntry):string {\n if (entry.body.length <= MAX_ENTRY_CHARS) {\n return entry.body\n }\n\n return entry.body.slice(0, MAX_ENTRY_CHARS) + '\\n' + TRUNCATED_MARKER\n}\n\nexport function tailLines (text:string, n:number):string {\n let lines = text.split('\\n')\n\n // Remove empty string at end if text ended with newline\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines = lines.slice(0, -1)\n }\n\n // Keep last n\n if (lines.length > n) {\n lines = lines.slice(-n)\n }\n\n return lines.join('\\n')\n}\n\nexport function learningsPathFor (progressPath:string):string {\n return join(dirname(progressPath), 'learnings.md')\n}\n\n// -- IO functions --\n\n// A missing log means no history yet. Any other read error (e.g.\n// the path is a directory) is thrown for the caller to report.\nexport function readEntries (path:string):LearningEntry[] {\n if (!existsSync(path)) return []\n return parseEntries(readFileSync(path, 'utf8'))\n}\n\n// Synchronous on purpose: tickets in a wave run concurrently in one\n// Node thread, so sync appends can never interleave.\nexport function appendEntry (path:string, text:string):void {\n mkdirSync(dirname(path), { recursive:true })\n appendFileSync(path, text)\n}\n\n// Reads one file from the worktree's notes directory (the notes\n// by default), then removes the whole directory (also when the\n// file is missing), so nothing in it can reach a commit. Blank\n// text counts as none.\nexport function collectNotes (\n worktreePath:string,\n file:string = basename(NOTES_PATH)\n):string|null {\n const dir = join(worktreePath, dirname(NOTES_PATH))\n const path = join(dir, file)\n const text = existsSync(path) ?\n readFileSync(path, 'utf8').trim() :\n ''\n rmSync(dir, { recursive:true, force:true })\n return text || null\n}\n\n// Makes the notes directory ignore itself, so an agent's\n// `git add -A` cannot stage its notes. Deliberately not\n// info/exclude: that file can be a symlink shared by every repo on\n// the machine (e.g. via init.templateDir).\nexport function ensureNotesIgnored (worktreePath:string):void {\n const dir = join(worktreePath, dirname(NOTES_PATH))\n mkdirSync(dir, { recursive:true })\n writeFileSync(join(dir, '.gitignore'), '*\\n')\n}\n"],
|
|
5
|
-
"mappings": ";;AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,UAAU,SAAS,YAAY;AAIjC,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AAE1B,MAAM,kBAAkB;AACjB,MAAM,mBAAmB;AAEzB,MAAM,oBAAoB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ;
|
|
4
|
+
"sourcesContent": ["import {\n appendFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\n\n// -- Constants and types --\n\nexport const MAX_OWN_ENTRIES = 4\nexport const MAX_ENTRY_CHARS = 4000\nexport const LOG_TAIL_LINES = 40\nexport const NOTES_PATH = '.nightralph/notes.md'\n\nconst SENTINEL_PREFIX = '<!-- nightralph:entry'\nexport const TRUNCATED_MARKER = '[truncated]'\n\nexport const LEARNING_OUTCOMES = [\n 'done',\n 'exit',\n 'tests',\n 'install',\n 'no-commits',\n 'error',\n 'merge',\n] as const\nexport type LearningOutcome = typeof LEARNING_OUTCOMES[number]\n\nexport type LearningEntry = {\n key:string\n attempt:number\n outcome:LearningOutcome\n timedOut:boolean\n // Everything after the sentinel line, trimmed, without\n // the trailing `---` separator\n body:string\n}\n\ntype EntryBase = {\n key:string // ticketKey(feature, num)\n label:string // ticketLabel(ticket), e.g. \"my-feature/04\"\n attempt:number // 0 for merge entries\n now:Date\n}\n\n// What one agent process did: its exit code, the items it reported,\n// whether it was killed at the timeout, and the notes it left.\nexport type AgentRunRecord = {\n exitCode:number\n completedItems:string[]\n timedOut:boolean\n notes:string|null\n // claude only; absent = not reported\n subagents?:number\n costUsd?:number\n}\n\ntype AgentFields = { run:AgentRunRecord; effort?:string }\n\ntype LogTail = { logName:string; logTail:string }\n\nexport type EntryInput = EntryBase&(\n | (AgentFields&{ outcome:'done'|'exit'|'no-commits' })\n | (AgentFields&LogTail&{ outcome:'tests' })\n | (LogTail&{ outcome:'install' })\n | { outcome:'error'; error:string }\n | { outcome:'merge'; stderr:string }\n)\n\nexport type HistorySelection = {\n own:LearningEntry[]\n blockers:LearningEntry[]\n}\n\n// -- Helpers --\n\nfunction encodeKey (key:string):string {\n return key\n .replace(/%/g, '%25')\n .replace(/\\s/g, c => encodeURIComponent(c))\n}\n\nfunction fence (content:string):string {\n const longest = Math.max(\n 0,\n ...[...content.matchAll(/`+/g)].map(m => m[0].length)\n )\n const ticks = '`'.repeat(Math.max(3, longest + 1))\n return `${ticks}\\n${content}\\n${ticks}`\n}\n\nfunction sanitize (text:string|null):string {\n if (!text) return ''\n return text.replace(\n new RegExp(SENTINEL_PREFIX, 'g'),\n '<!-- nightralph-entry'\n )\n}\n\nfunction renderAgentSummary (\n run:AgentRunRecord,\n effort?:string\n):string {\n const effortLine = effort ?\n `Effort: ${effort}.` :\n ''\n\n const exitLine = `Agent exit: ${run.exitCode}.`\n\n const subagentsLine = run.subagents === undefined ?\n '' :\n `Subagents: ${run.subagents}.`\n\n const costLine = run.costUsd === undefined ?\n '' :\n `Cost: $${run.costUsd.toFixed(2)}.`\n\n const itemsText = run.completedItems.length > 0 ?\n run.completedItems.map(item =>\n `\"${sanitize(item)}\"`\n ).join(', ') + '.' :\n 'none.'\n\n const itemsLine = `Checked items: ${itemsText}`\n\n return [\n effortLine,\n exitLine,\n subagentsLine,\n costLine,\n itemsLine,\n ].filter(Boolean).join(' ')\n}\n\nfunction renderNotesSection (notes:string|null):string {\n const notesSanitized = sanitize(notes)\n return notesSanitized.trim() ?\n `### Agent notes\\n${notesSanitized}` :\n 'The agent left no notes.'\n}\n\nexport function formatDate (date:Date):string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n return `${year}-${month}-${day} ${hours}:${minutes}`\n}\n\nexport function isLearningOutcome (\n value:string\n):value is LearningOutcome {\n return LEARNING_OUTCOMES.some(o => o === value)\n}\n\nexport function renderEntry (input:EntryInput):string {\n const encodedKey = encodeKey(input.key)\n\n const hasRun = 'run' in input\n const timedOut = hasRun && input.run.timedOut\n\n const timedOutStr = timedOut ?\n ' timedout=true' :\n ''\n\n const sentinel =\n `<!-- nightralph:entry ticket=${encodedKey} ` +\n `attempt=${input.attempt} outcome=${input.outcome}` +\n `${timedOutStr} -->`\n\n const timestamp = formatDate(input.now)\n const attemptStr = input.outcome === 'merge' ?\n '' :\n ` attempt ${input.attempt}`\n\n let description:string\n\n switch (input.outcome) {\n case 'done':\n description = 'done'\n break\n case 'exit':\n description = `failed (exit ${input.run.exitCode})`\n break\n case 'tests':\n description = 'failed (tests)'\n break\n case 'install':\n description = 'failed (install)'\n break\n case 'no-commits':\n description = 'no commits'\n break\n case 'error':\n description = 'error'\n break\n case 'merge':\n description = 'merge failed'\n break\n default: {\n const _exhaustive:never = input\n description = _exhaustive\n }\n }\n\n const timedOutPrefix = timedOut ?\n 'timed out, then ' :\n ''\n\n const heading =\n `## ${timestamp} -- ${input.label}${attemptStr} -- ` +\n `${timedOutPrefix}${description}`\n\n let body:string\n\n switch (input.outcome) {\n case 'done':\n case 'exit':\n case 'no-commits': {\n const run = input.run\n const summary = renderAgentSummary(run, input.effort)\n const notesSection = renderNotesSection(run.notes)\n body = summary + '\\n\\n' + notesSection\n break\n }\n case 'tests': {\n const logTail = sanitize(input.logTail)\n const fenced = fence(logTail)\n const summary = renderAgentSummary(\n input.run,\n input.effort\n )\n const notesSection = renderNotesSection(input.run.notes)\n\n const lastNLines =\n `Last ${LOG_TAIL_LINES} lines of ` +\n `\\`${sanitize(input.logName)}\\`:`\n\n body =\n summary + '\\n\\n' +\n 'Test gate failed.\\n' +\n `${lastNLines}\\n` +\n `${fenced}\\n\\n` +\n notesSection\n break\n }\n case 'install': {\n const logTail = sanitize(input.logTail)\n const fenced = fence(logTail)\n\n const lastNLines =\n `Last ${LOG_TAIL_LINES} lines of ` +\n `\\`${sanitize(input.logName)}\\`:`\n\n body =\n 'Install failed.\\n' +\n `${lastNLines}\\n` +\n fenced\n break\n }\n case 'error': {\n const errorText = sanitize(input.error)\n const fenced = fence(errorText)\n body = fenced\n break\n }\n case 'merge': {\n const stderrText = sanitize(input.stderr)\n const fenced = fence(stderrText)\n body = `Merge failed.\\n${fenced}`\n break\n }\n default: {\n const unknown:never = input\n throw new Error(`Unknown outcome: ${JSON.stringify(unknown)}`)\n }\n }\n\n return `${sentinel}\\n${heading}\\n\\n${body}\\n\\n---\\n`\n}\n\nexport function parseEntries (text:string):LearningEntry[] {\n const lines = text.split('\\n').map(line => {\n // Strip trailing \\r for CRLF support\n return line.endsWith('\\r') ? line.slice(0, -1) : line\n })\n const entries:LearningEntry[] = []\n\n let currentSentinel:string|null = null\n let currentBody:string[] = []\n\n const sentinelRegex = /^<!-- nightralph:entry (.*) -->$/\n\n for (const line of lines) {\n const match = line.match(sentinelRegex)\n\n if (match) {\n // Process previous entry if exists\n if (currentSentinel !== null) {\n const entry = parseSentinel(currentSentinel, currentBody)\n if (entry) {\n entries.push(entry)\n }\n }\n\n currentSentinel = match[1]\n currentBody = []\n } else if (currentSentinel !== null) {\n currentBody.push(line)\n }\n }\n\n // Process last entry\n if (currentSentinel !== null) {\n const entry = parseSentinel(currentSentinel, currentBody)\n if (entry) {\n entries.push(entry)\n }\n }\n\n return entries\n}\n\nfunction parseSentinel (\n sentinel:string,\n bodyLines:string[]\n):LearningEntry|null {\n const parts = sentinel.split(/\\s+/).filter(Boolean)\n const attrs:Record<string, string> = {}\n\n for (const part of parts) {\n const idx = part.indexOf('=')\n if (idx > 0) {\n const key = part.slice(0, idx)\n const value = part.slice(idx + 1)\n if (value) {\n attrs[key] = value\n }\n }\n }\n\n // Validate ticket\n let key = attrs.ticket\n if (!key) return null\n\n try {\n key = decodeURIComponent(key)\n } catch (_e) {\n return null\n }\n\n if (!key.trim()) return null\n\n // Validate attempt\n const attemptStr = attrs.attempt\n if (!attemptStr) return null\n\n if (!/^\\d+$/.test(attemptStr)) return null\n const attempt = Number(attemptStr)\n\n // Validate outcome\n const outcome = attrs.outcome\n if (!outcome || !isLearningOutcome(outcome)) return null\n\n // Parse timedOut\n const timedOut = attrs.timedout === 'true'\n\n // Parse body\n let body = bodyLines.join('\\n').trim()\n\n // Remove trailing --- line (full line only)\n const lines = body.split('\\n')\n if (lines.length > 0 && lines[lines.length - 1] === '---') {\n body = lines.slice(0, -1).join('\\n').trim()\n }\n\n return {\n key,\n attempt,\n outcome,\n timedOut,\n body,\n }\n}\n\nexport function selectHistory (\n entries:LearningEntry[],\n opts:{ key:string; blockerKeys:string[] }\n):HistorySelection {\n const own = entries\n .filter(e => e.key === opts.key)\n .slice(-MAX_OWN_ENTRIES)\n\n const blockers = opts.blockerKeys.flatMap(k => {\n const done = entries.filter(e => {\n return e.key === k && e.outcome === 'done'\n })\n const last = done[done.length - 1]\n return last ? [last] : []\n })\n\n return { own, blockers }\n}\n\nexport function renderHistory (selection:HistorySelection):string {\n if (selection.own.length === 0 && selection.blockers.length === 0) {\n return ''\n }\n\n const framing =\n 'These are records of earlier runs. The ticket or spec may ' +\n 'have changed since then; where they disagree, follow the ' +\n 'ticket and spec. Do not repeat an approach these notes say ' +\n 'failed unless you can see why it failed.'\n\n const parts = [framing, '']\n\n if (selection.own.length > 0) {\n parts.push('---- PREVIOUS ATTEMPTS AT THIS TICKET ----')\n parts.push(selection.own.map(e => capEntry(e)).join('\\n\\n'))\n parts.push('')\n }\n\n if (selection.blockers.length > 0) {\n parts.push('---- WHAT THE BLOCKING TICKETS DID ----')\n parts.push(selection.blockers.map(e => capEntry(e)).join('\\n\\n'))\n }\n\n return parts.join('\\n')\n}\n\nfunction capEntry (entry:LearningEntry):string {\n if (entry.body.length <= MAX_ENTRY_CHARS) {\n return entry.body\n }\n\n return entry.body.slice(0, MAX_ENTRY_CHARS) + '\\n' + TRUNCATED_MARKER\n}\n\nexport function tailLines (text:string, n:number):string {\n let lines = text.split('\\n')\n\n // Remove empty string at end if text ended with newline\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines = lines.slice(0, -1)\n }\n\n // Keep last n\n if (lines.length > n) {\n lines = lines.slice(-n)\n }\n\n return lines.join('\\n')\n}\n\nexport function learningsPathFor (progressPath:string):string {\n return join(dirname(progressPath), 'learnings.md')\n}\n\n// -- IO functions --\n\n// A missing log means no history yet. Any other read error (e.g.\n// the path is a directory) is thrown for the caller to report.\nexport function readEntries (path:string):LearningEntry[] {\n if (!existsSync(path)) return []\n return parseEntries(readFileSync(path, 'utf8'))\n}\n\n// Synchronous on purpose: tickets in a wave run concurrently in one\n// Node thread, so sync appends can never interleave.\nexport function appendEntry (path:string, text:string):void {\n mkdirSync(dirname(path), { recursive:true })\n appendFileSync(path, text)\n}\n\n// Reads one file from the worktree's notes directory (the notes\n// by default), then removes the whole directory (also when the\n// file is missing), so nothing in it can reach a commit. Blank\n// text counts as none.\nexport function collectNotes (\n worktreePath:string,\n file:string = basename(NOTES_PATH)\n):string|null {\n const dir = join(worktreePath, dirname(NOTES_PATH))\n const path = join(dir, file)\n const text = existsSync(path) ?\n readFileSync(path, 'utf8').trim() :\n ''\n rmSync(dir, { recursive:true, force:true })\n return text || null\n}\n\n// Makes the notes directory ignore itself, so an agent's\n// `git add -A` cannot stage its notes. Deliberately not\n// info/exclude: that file can be a symlink shared by every repo on\n// the machine (e.g. via init.templateDir).\nexport function ensureNotesIgnored (worktreePath:string):void {\n const dir = join(worktreePath, dirname(NOTES_PATH))\n mkdirSync(dir, { recursive:true })\n writeFileSync(join(dir, '.gitignore'), '*\\n')\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["key"]
|
|
7
7
|
}
|
package/dist/meta.json
CHANGED
|
@@ -104,9 +104,25 @@
|
|
|
104
104
|
],
|
|
105
105
|
"format": "esm"
|
|
106
106
|
},
|
|
107
|
+
"src/stats.ts": {
|
|
108
|
+
"bytes": 5943,
|
|
109
|
+
"imports": [
|
|
110
|
+
{
|
|
111
|
+
"path": "<runtime>",
|
|
112
|
+
"kind": "import-statement",
|
|
113
|
+
"external": true
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"format": "esm"
|
|
117
|
+
},
|
|
107
118
|
"src/display.ts": {
|
|
108
|
-
"bytes":
|
|
119
|
+
"bytes": 16115,
|
|
109
120
|
"imports": [
|
|
121
|
+
{
|
|
122
|
+
"path": "src/stats.ts",
|
|
123
|
+
"kind": "import-statement",
|
|
124
|
+
"original": "./stats.js"
|
|
125
|
+
},
|
|
110
126
|
{
|
|
111
127
|
"path": "<runtime>",
|
|
112
128
|
"kind": "import-statement",
|
|
@@ -142,7 +158,7 @@
|
|
|
142
158
|
"format": "esm"
|
|
143
159
|
},
|
|
144
160
|
"src/learnings.ts": {
|
|
145
|
-
"bytes":
|
|
161
|
+
"bytes": 13837,
|
|
146
162
|
"imports": [
|
|
147
163
|
{
|
|
148
164
|
"path": "node:fs",
|
|
@@ -163,7 +179,7 @@
|
|
|
163
179
|
"format": "esm"
|
|
164
180
|
},
|
|
165
181
|
"src/rules.ts": {
|
|
166
|
-
"bytes":
|
|
182
|
+
"bytes": 5272,
|
|
167
183
|
"imports": [
|
|
168
184
|
{
|
|
169
185
|
"path": "src/learnings.ts",
|
|
@@ -195,7 +211,7 @@
|
|
|
195
211
|
"format": "esm"
|
|
196
212
|
},
|
|
197
213
|
"src/review.ts": {
|
|
198
|
-
"bytes":
|
|
214
|
+
"bytes": 26999,
|
|
199
215
|
"imports": [
|
|
200
216
|
{
|
|
201
217
|
"path": "node:fs",
|
|
@@ -250,8 +266,19 @@
|
|
|
250
266
|
],
|
|
251
267
|
"format": "esm"
|
|
252
268
|
},
|
|
269
|
+
"src/blockers.ts": {
|
|
270
|
+
"bytes": 7891,
|
|
271
|
+
"imports": [
|
|
272
|
+
{
|
|
273
|
+
"path": "<runtime>",
|
|
274
|
+
"kind": "import-statement",
|
|
275
|
+
"external": true
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
"format": "esm"
|
|
279
|
+
},
|
|
253
280
|
"src/orchestrator.ts": {
|
|
254
|
-
"bytes":
|
|
281
|
+
"bytes": 107814,
|
|
255
282
|
"imports": [
|
|
256
283
|
{
|
|
257
284
|
"path": "node:child_process",
|
|
@@ -318,6 +345,11 @@
|
|
|
318
345
|
"kind": "import-statement",
|
|
319
346
|
"original": "./review.js"
|
|
320
347
|
},
|
|
348
|
+
{
|
|
349
|
+
"path": "src/stats.ts",
|
|
350
|
+
"kind": "import-statement",
|
|
351
|
+
"original": "./stats.js"
|
|
352
|
+
},
|
|
321
353
|
{
|
|
322
354
|
"path": "src/retry.ts",
|
|
323
355
|
"kind": "import-statement",
|
|
@@ -333,6 +365,11 @@
|
|
|
333
365
|
"kind": "import-statement",
|
|
334
366
|
"original": "./learnings.js"
|
|
335
367
|
},
|
|
368
|
+
{
|
|
369
|
+
"path": "src/blockers.ts",
|
|
370
|
+
"kind": "import-statement",
|
|
371
|
+
"original": "./blockers.js"
|
|
372
|
+
},
|
|
336
373
|
{
|
|
337
374
|
"path": "<runtime>",
|
|
338
375
|
"kind": "import-statement",
|
|
@@ -363,7 +400,7 @@
|
|
|
363
400
|
"format": "esm"
|
|
364
401
|
},
|
|
365
402
|
"src/resolve.ts": {
|
|
366
|
-
"bytes":
|
|
403
|
+
"bytes": 7069,
|
|
367
404
|
"imports": [
|
|
368
405
|
{
|
|
369
406
|
"path": "node:fs",
|
|
@@ -395,6 +432,16 @@
|
|
|
395
432
|
"kind": "import-statement",
|
|
396
433
|
"original": "./orchestrator.js"
|
|
397
434
|
},
|
|
435
|
+
{
|
|
436
|
+
"path": "src/display.ts",
|
|
437
|
+
"kind": "import-statement",
|
|
438
|
+
"original": "./display.js"
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
"path": "src/blockers.ts",
|
|
442
|
+
"kind": "import-statement",
|
|
443
|
+
"original": "./blockers.js"
|
|
444
|
+
},
|
|
398
445
|
{
|
|
399
446
|
"path": "<runtime>",
|
|
400
447
|
"kind": "import-statement",
|
|
@@ -404,7 +451,7 @@
|
|
|
404
451
|
"format": "esm"
|
|
405
452
|
},
|
|
406
453
|
"src/index.ts": {
|
|
407
|
-
"bytes":
|
|
454
|
+
"bytes": 22605,
|
|
408
455
|
"imports": [
|
|
409
456
|
{
|
|
410
457
|
"path": "node:child_process",
|
|
@@ -485,7 +532,7 @@
|
|
|
485
532
|
"imports": [],
|
|
486
533
|
"exports": [],
|
|
487
534
|
"inputs": {},
|
|
488
|
-
"bytes":
|
|
535
|
+
"bytes": 381724
|
|
489
536
|
},
|
|
490
537
|
"dist/index.js": {
|
|
491
538
|
"imports": [
|
|
@@ -687,13 +734,13 @@
|
|
|
687
734
|
"entryPoint": "src/index.ts",
|
|
688
735
|
"inputs": {
|
|
689
736
|
"src/index.ts": {
|
|
690
|
-
"bytesInOutput":
|
|
737
|
+
"bytesInOutput": 14084
|
|
691
738
|
},
|
|
692
739
|
"src/setup.ts": {
|
|
693
740
|
"bytesInOutput": 4816
|
|
694
741
|
},
|
|
695
742
|
"src/orchestrator.ts": {
|
|
696
|
-
"bytesInOutput":
|
|
743
|
+
"bytesInOutput": 72214
|
|
697
744
|
},
|
|
698
745
|
"src/worktree.ts": {
|
|
699
746
|
"bytesInOutput": 9402
|
|
@@ -704,32 +751,38 @@
|
|
|
704
751
|
"src/merge.ts": {
|
|
705
752
|
"bytesInOutput": 4995
|
|
706
753
|
},
|
|
754
|
+
"src/stats.ts": {
|
|
755
|
+
"bytesInOutput": 3792
|
|
756
|
+
},
|
|
707
757
|
"src/display.ts": {
|
|
708
|
-
"bytesInOutput":
|
|
758
|
+
"bytesInOutput": 9881
|
|
709
759
|
},
|
|
710
760
|
"src/testcmd.ts": {
|
|
711
761
|
"bytesInOutput": 2410
|
|
712
762
|
},
|
|
713
763
|
"src/learnings.ts": {
|
|
714
|
-
"bytesInOutput":
|
|
764
|
+
"bytesInOutput": 10202
|
|
715
765
|
},
|
|
716
766
|
"src/rules.ts": {
|
|
717
|
-
"bytesInOutput":
|
|
767
|
+
"bytesInOutput": 3877
|
|
718
768
|
},
|
|
719
769
|
"src/review.ts": {
|
|
720
|
-
"bytesInOutput":
|
|
770
|
+
"bytesInOutput": 19013
|
|
721
771
|
},
|
|
722
772
|
"src/retry.ts": {
|
|
723
773
|
"bytesInOutput": 1852
|
|
724
774
|
},
|
|
775
|
+
"src/blockers.ts": {
|
|
776
|
+
"bytesInOutput": 4423
|
|
777
|
+
},
|
|
725
778
|
"src/preflight.ts": {
|
|
726
779
|
"bytesInOutput": 899
|
|
727
780
|
},
|
|
728
781
|
"src/resolve.ts": {
|
|
729
|
-
"bytesInOutput":
|
|
782
|
+
"bytesInOutput": 5484
|
|
730
783
|
}
|
|
731
784
|
},
|
|
732
|
-
"bytes":
|
|
785
|
+
"bytes": 173426
|
|
733
786
|
}
|
|
734
787
|
}
|
|
735
788
|
}
|