@open-tomato/rafa 0.18.0 → 0.20.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.
@@ -1,23 +1,23 @@
1
1
  // @bun
2
2
  import {
3
- ACTION_HEADING,
4
3
  AGENT_DEFINITION_DIR,
5
4
  BRANCH_PREFIX,
6
- CAUSE_HEADING,
7
5
  CI_POLL_INTERVAL_MS,
8
6
  DEFAULT_BASE_BRANCH,
9
7
  DEFAULT_CI_ATTEMPTS,
10
8
  DEFAULT_CI_TIMEOUT_MIN,
11
9
  DEFAULT_ISSUE_SEAMS,
12
10
  DEFAULT_PLAN_FILE,
11
+ DEMOTION_VERDICTS,
13
12
  DESCRIPTION_LIMIT,
14
13
  DISK_FILE_SYSTEM,
15
14
  HINT_FLAG_SPEC,
16
15
  ID_PREFIX,
16
+ LEARNED_DIRECTORY,
17
17
  LISTING_LIMIT,
18
- MARKDOWN_EXTENSION,
19
18
  MECHANICAL_CONFLICT_SENTENCE,
20
19
  NEXT_COMMAND_ACTIONS,
20
+ ORIGIN_FIELD,
21
21
  PREVIOUS_COPY_WARN_ABOVE,
22
22
  PROVENANCE_FIELD,
23
23
  REMOTE,
@@ -32,9 +32,9 @@ import {
32
32
  SCOPE_DIR,
33
33
  SERVE_CLI_VERSION,
34
34
  SESSION_ID_FLAG,
35
- SKILL_FILE,
36
- SKILL_FILE1 as SKILL_FILE2,
35
+ SKILL_FILE as SKILL_FILE2,
37
36
  SKILL_SIGNALS,
37
+ SKILL_USE_CLI_VERSION,
38
38
  SPEC_BLOCKED_LABEL,
39
39
  SPEC_EXTENSION,
40
40
  SPEC_LABEL,
@@ -46,7 +46,7 @@ import {
46
46
  UNREADABLE,
47
47
  VENDOR_COMMAND,
48
48
  VERSION_SHAPE,
49
- actionHash,
49
+ WHEN_TO_USE_HEADING,
50
50
  actionInvocation,
51
51
  actionOutput,
52
52
  announceRiskTotal,
@@ -54,6 +54,7 @@ import {
54
54
  blockedFaultMessage,
55
55
  blockedLineSentence,
56
56
  boardId,
57
+ bodySections,
57
58
  branchClaims,
58
59
  bundledAgentsDirectory,
59
60
  byName,
@@ -62,13 +63,14 @@ import {
62
63
  checkReferences,
63
64
  checkbox,
64
65
  checkboxAt,
66
+ classifySkill,
65
67
  cleanUpSteps,
66
68
  closedIssuesIn,
67
69
  collect,
68
- collectReferences,
69
70
  collectSessionRow,
70
71
  commandLine,
71
72
  commandWords,
73
+ convertToInstinct,
72
74
  coreRoster,
73
75
  countCharacters,
74
76
  countPreviousCopies,
@@ -95,6 +97,7 @@ import {
95
97
  failingRows,
96
98
  findReadinessGaps,
97
99
  fingerprintText,
100
+ firstSentence,
98
101
  formatCounts,
99
102
  formatRows,
100
103
  ghHostOf,
@@ -104,7 +107,6 @@ import {
104
107
  ghPreflightItems,
105
108
  ghPullRequestsIn,
106
109
  ghUnauthenticatedMessage,
107
- gitRemoteUrl,
108
110
  gitSaid,
109
111
  groupChangeNotes,
110
112
  hasDiverged,
@@ -125,16 +127,13 @@ import {
125
127
  list_default,
126
128
  loadConfig,
127
129
  memoiseVerifier,
128
- mergeFrontmatter,
129
130
  missingPlanAgents,
130
131
  name,
131
132
  nextQuestion,
132
- normalizeRemote,
133
133
  notesFileName,
134
134
  onTracker,
135
135
  openNextSources,
136
136
  parseBaseStanding,
137
- parseInstinct,
138
137
  parseRoadmapBody,
139
138
  parseSemanticVersion,
140
139
  parseWorkingTree,
@@ -150,6 +149,7 @@ import {
150
149
  previousDir,
151
150
  projectRoot,
152
151
  provenanceBlock,
152
+ rankCandidates,
153
153
  readAgentDirectory,
154
154
  readAuthorTrust,
155
155
  readBlockedBy,
@@ -158,9 +158,6 @@ import {
158
158
  readChoice,
159
159
  readChoiceFlag,
160
160
  readCopyRefs,
161
- readFrontmatter,
162
- readFrontmatterDocument,
163
- readInventoryFrontmatter,
164
161
  readManifestVersion,
165
162
  readMergeRefusal,
166
163
  readNextState,
@@ -168,6 +165,7 @@ import {
168
165
  readOpenPull,
169
166
  readPlanChanges,
170
167
  readPlans,
168
+ readRankCandidate,
171
169
  readRecords,
172
170
  readRefsText,
173
171
  readRequiredFlag,
@@ -182,7 +180,6 @@ import {
182
180
  refusal,
183
181
  refuseMisplacedRuntime,
184
182
  remainingFrom,
185
- renderFrontmatter,
186
183
  renderNoteLines,
187
184
  renderRiskText,
188
185
  report,
@@ -204,7 +201,6 @@ import {
204
201
  runAction,
205
202
  runsDir,
206
203
  scanClaimBranches,
207
- scanLayout,
208
204
  scopeAt,
209
205
  selfAndAncestors,
210
206
  serveVerdict,
@@ -230,10 +226,8 @@ import {
230
226
  version,
231
227
  versionLine,
232
228
  waitForChecks,
233
- writeFrontmatter,
234
- writeInstinct,
235
229
  writeSession
236
- } from "./index-6vkd153j.js";
230
+ } from "./index-02fx0mzf.js";
237
231
  import {
238
232
  PROBE_TIMEOUT_MS,
239
233
  findNextTask,
@@ -247,8 +241,10 @@ import {
247
241
  runPreflight,
248
242
  splitBlockerComment,
249
243
  trackerPathFor
250
- } from "./index-0pdsq2hy.js";
244
+ } from "./index-21qkxk63.js";
251
245
  import {
246
+ ACTION_HEADING,
247
+ CAUSE_HEADING,
252
248
  CLAUDE_BIN,
253
249
  CORE_ADAPTER_REGISTRY,
254
250
  EFFORT_STORE_DIR,
@@ -256,17 +252,34 @@ import {
256
252
  ISSUE_PRIORITIES,
257
253
  ISSUE_STATES,
258
254
  ISSUE_TYPES,
255
+ MARKDOWN_EXTENSION,
256
+ SKILL_FILE,
257
+ SQLITE_MIGRATIONS,
258
+ allRecords,
259
259
  claudeArgs,
260
260
  createGhRunner,
261
261
  effortStorePath,
262
+ findRecords,
263
+ gitRemoteUrl,
264
+ instinctProject,
265
+ mergeFrontmatter,
266
+ migrateSchema,
262
267
  moduleOfLabels,
268
+ normalizeRemote,
269
+ readFrontmatter,
270
+ readFrontmatterDocument,
271
+ readScopes,
272
+ renderFrontmatter,
263
273
  runClaudeCaptured,
274
+ scanLayout,
264
275
  selectEffortStore,
265
276
  sessionSpawnEnv,
266
277
  spawnClaudeCaptured,
267
278
  sqliteStorePath,
268
- typeOfLabels
269
- } from "./index-at9f1z2z.js";
279
+ toHeldRecords,
280
+ typeOfLabels,
281
+ writeFrontmatter
282
+ } from "./index-afersvp3.js";
270
283
  import {
271
284
  CONFIG_DEFAULTS,
272
285
  CONFIG_FILE,
@@ -280,15 +293,18 @@ import {
280
293
  readItemBytes,
281
294
  readRafaBlocks,
282
295
  resolveTiers
283
- } from "./index-jva32qe6.js";
296
+ } from "./index-twbp38kz.js";
297
+ import {
298
+ promotable
299
+ } from "./index-d6d0942q.js";
284
300
  import {
285
301
  createCommandRegistry,
286
302
  describeRegistry,
287
303
  mountKey
288
- } from "./index-kvnggvyk.js";
304
+ } from "./index-4a45ffqh.js";
289
305
  import {
290
306
  CommandExit
291
- } from "./index-ddf85qac.js";
307
+ } from "./index-28jzpyks.js";
292
308
  import {
293
309
  MERGE_METHODS,
294
310
  RELEASE_AUTO,
@@ -299,10 +315,11 @@ import {
299
315
  isMergeMethod,
300
316
  isSkillTier,
301
317
  messageOf,
302
- parseBudgetUsd,
303
- resolveInstinctScopes,
304
- tierExists
305
- } from "./index-944pncd8.js";
318
+ parseBudgetUsd
319
+ } from "./index-pmkgvtfe.js";
320
+ import {
321
+ triggerKey
322
+ } from "./index-wp8c28fd.js";
306
323
 
307
324
  // src/inventory/disabled.ts
308
325
  import { readFileSync } from "fs";
@@ -2274,148 +2291,6 @@ async function checkQuotes(matches, files) {
2274
2291
  return { kept, dropped: matches.length - kept.length };
2275
2292
  }
2276
2293
 
2277
- // src/inventory/search/rank.ts
2278
- import { readFileSync as readFileSync5 } from "fs";
2279
- var SEARCH_LIMIT = 12;
2280
- var MIN_WORD_LENGTH = 2;
2281
- var MIN_PREFIX_LENGTH = 4;
2282
- var FIELD_WEIGHTS = {
2283
- tags: 4,
2284
- prevents: 3,
2285
- whenToUse: 3,
2286
- description: 2,
2287
- body: 1
2288
- };
2289
- var FIELDS = ["tags", "prevents", "whenToUse", "description", "body"];
2290
- var STOP_WORDS = new Set([
2291
- "a",
2292
- "about",
2293
- "an",
2294
- "and",
2295
- "any",
2296
- "are",
2297
- "as",
2298
- "at",
2299
- "be",
2300
- "by",
2301
- "can",
2302
- "could",
2303
- "do",
2304
- "does",
2305
- "for",
2306
- "from",
2307
- "has",
2308
- "have",
2309
- "how",
2310
- "if",
2311
- "in",
2312
- "into",
2313
- "is",
2314
- "it",
2315
- "its",
2316
- "me",
2317
- "my",
2318
- "of",
2319
- "on",
2320
- "or",
2321
- "should",
2322
- "so",
2323
- "that",
2324
- "the",
2325
- "their",
2326
- "there",
2327
- "this",
2328
- "to",
2329
- "use",
2330
- "was",
2331
- "we",
2332
- "what",
2333
- "when",
2334
- "where",
2335
- "which",
2336
- "who",
2337
- "why",
2338
- "will",
2339
- "with",
2340
- "would",
2341
- "you",
2342
- "your",
2343
- "agent",
2344
- "agents",
2345
- "skill",
2346
- "skills"
2347
- ]);
2348
- function wordsOf(text) {
2349
- return text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
2350
- }
2351
- function questionWords(question) {
2352
- const kept = wordsOf(question).filter((word) => word.length >= MIN_WORD_LENGTH && !STOP_WORDS.has(word));
2353
- return [...new Set(kept)];
2354
- }
2355
- function wordsMatch(word, other) {
2356
- if (word === other)
2357
- return true;
2358
- const [shorter, longer] = word.length <= other.length ? [word, other] : [other, word];
2359
- return shorter.length >= MIN_PREFIX_LENGTH && longer.startsWith(shorter);
2360
- }
2361
- function fieldWords(candidate) {
2362
- const { record } = candidate;
2363
- const texts = {
2364
- tags: record.tags.join(" "),
2365
- prevents: record.prevents ?? "",
2366
- whenToUse: record.whenToUse ?? "",
2367
- description: candidate.description ?? "",
2368
- body: candidate.body
2369
- };
2370
- return new Map(FIELDS.map((field) => [field, [...new Set(wordsOf(texts[field]))]]));
2371
- }
2372
- function scoreCandidate(candidate, words) {
2373
- const byField = fieldWords(candidate);
2374
- const matchedWords = new Set;
2375
- const matchedFields = new Set;
2376
- let score = 0;
2377
- for (const word of words) {
2378
- for (const field of FIELDS) {
2379
- const found = (byField.get(field) ?? []).some((other) => wordsMatch(word, other));
2380
- if (!found)
2381
- continue;
2382
- score += FIELD_WEIGHTS[field];
2383
- matchedWords.add(word);
2384
- matchedFields.add(field);
2385
- }
2386
- }
2387
- return {
2388
- record: candidate.record,
2389
- score,
2390
- words: words.filter((word) => matchedWords.has(word)),
2391
- fields: FIELDS.filter((field) => matchedFields.has(field))
2392
- };
2393
- }
2394
- function rankCandidates(question, candidates, limit = SEARCH_LIMIT) {
2395
- const words = questionWords(question);
2396
- if (words.length === 0)
2397
- return [];
2398
- return candidates.map((candidate) => scoreCandidate(candidate, words)).filter((ranked) => ranked.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
2399
- }
2400
- function readRankCandidate(record, read = (path) => readFileSync5(path, "utf8")) {
2401
- let text;
2402
- try {
2403
- text = read(record.path);
2404
- } catch {
2405
- return {
2406
- record,
2407
- description: record.summary === "" ? null : record.summary,
2408
- body: ""
2409
- };
2410
- }
2411
- const document = readFrontmatterDocument(text);
2412
- return {
2413
- record,
2414
- description: readInventoryFrontmatter(document?.data ?? null).description,
2415
- body: document?.body ?? text
2416
- };
2417
- }
2418
-
2419
2294
  // src/inventory/search/scratch.ts
2420
2295
  import { copyFileSync, mkdirSync, mkdtempSync, rmSync } from "fs";
2421
2296
  import { tmpdir } from "os";
@@ -2838,7 +2713,7 @@ function createAgentShowCommand(seams = DEFAULT_AGENT_SHOW_SEAMS) {
2838
2713
  var show_default = createAgentShowCommand();
2839
2714
 
2840
2715
  // src/commands/agent/vendor.ts
2841
- import { copyFileSync as copyFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync } from "fs";
2716
+ import { copyFileSync as copyFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "fs";
2842
2717
  import { basename as basename2, join as join6 } from "path";
2843
2718
  var USAGE4 = "rafa agent vendor <name>... [--force]";
2844
2719
  var NOTHING_WRITTEN = "Nothing was written.";
@@ -2925,7 +2800,7 @@ function planCopies(names, project, force, entry) {
2925
2800
  function copyOne(copy, date) {
2926
2801
  try {
2927
2802
  copyFileSync2(copy.from, copy.to);
2928
- writeFileSync(copy.to, withSourceHeader(readFileSync6(copy.to, "utf8"), copy.from, date), "utf8");
2803
+ writeFileSync(copy.to, withSourceHeader(readFileSync5(copy.to, "utf8"), copy.from, date), "utf8");
2929
2804
  } catch (error) {
2930
2805
  throw new CommandExit(1, `\u274C ${USAGE4}: agent "${copy.name}" could not be written to ${copy.to}: ${String(error)}`);
2931
2806
  }
@@ -4274,7 +4149,7 @@ import { statSync as statSync5 } from "fs";
4274
4149
  import { join as join10 } from "path";
4275
4150
 
4276
4151
  // src/board/setup-config.ts
4277
- import { readFileSync as readFileSync7 } from "fs";
4152
+ import { readFileSync as readFileSync6 } from "fs";
4278
4153
  function roadmapIssueIn(text, path) {
4279
4154
  return parseConfigText(text, path).values.roadmapIssue ?? null;
4280
4155
  }
@@ -4282,7 +4157,7 @@ function readRoadmapSetting(root) {
4282
4157
  const path = configFilePath(root);
4283
4158
  let text;
4284
4159
  try {
4285
- text = readFileSync7(path, "utf8");
4160
+ text = readFileSync6(path, "utf8");
4286
4161
  } catch (error) {
4287
4162
  return { issue: null, text: "", problem: `${path} could not be read: ${messageOf(error)}` };
4288
4163
  }
@@ -4331,7 +4206,7 @@ function withRoadmapIssue(text, issue) {
4331
4206
  }
4332
4207
 
4333
4208
  // src/board/setup.ts
4334
- import { existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync3, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
4209
+ import { existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync3, readFileSync as readFileSync7, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
4335
4210
  import { dirname, join as join9 } from "path";
4336
4211
  import { fileURLToPath } from "url";
4337
4212
  var PREFIX = "board setup";
@@ -4466,7 +4341,7 @@ function readSpecTemplate(moduleDir = MODULE_DIR) {
4466
4341
  if (!existsSync4(source)) {
4467
4342
  throw new Error(`${PREFIX}: the spec issue template is missing: no file at ${source}`);
4468
4343
  }
4469
- return readFileSync8(source, "utf8");
4344
+ return readFileSync7(source, "utf8");
4470
4345
  }
4471
4346
  function writeSpecTemplate(root, moduleDir = MODULE_DIR) {
4472
4347
  const path = join9(root, SPEC_TEMPLATE_PATH);
@@ -4956,7 +4831,7 @@ function readScope2(scope, path, loaded) {
4956
4831
  }
4957
4832
  return { read: { scope, path, loaded, entries }, warnings };
4958
4833
  }
4959
- function readScopes(seams) {
4834
+ function readScopes2(seams) {
4960
4835
  const read = OVERRIDE_SCOPES.flatMap((scope) => {
4961
4836
  const path = overrideSettingsPath(scope, { home: seams.home, projectRoot: seams.projectRoot });
4962
4837
  return path === null ? [] : [readScope2(scope, path, seams.settingSources.includes(scope))];
@@ -5009,7 +4884,7 @@ function pathDifference(shell, session, layer) {
5009
4884
  return Object.freeze({ layer, added: Object.freeze(added), removed: Object.freeze(removed), reordered });
5010
4885
  }
5011
4886
  function readSessionEnv(seams) {
5012
- const { scopes, warnings } = readScopes(seams);
4887
+ const { scopes, warnings } = readScopes2(seams);
5013
4888
  const { env, layers } = overlay(sessionSpawnEnv(seams.env), seams.env, scopes);
5014
4889
  return Object.freeze({
5015
4890
  env: Object.freeze(env),
@@ -6426,7 +6301,7 @@ function writeInstall(context, install) {
6426
6301
  }
6427
6302
 
6428
6303
  // src/commands/doctor-refs.ts
6429
- import { readdirSync, readFileSync as readFileSync9, statSync as statSync8 } from "fs";
6304
+ import { readdirSync, readFileSync as readFileSync8, statSync as statSync8 } from "fs";
6430
6305
  import { join as join16, resolve as resolve5 } from "path";
6431
6306
  function issueCheckCommand(issue) {
6432
6307
  return `rafa issue check ${String(issue)}`;
@@ -6496,7 +6371,7 @@ async function readCopy(file, input, verify) {
6496
6371
  const path = join16(input.specsDir, file.name);
6497
6372
  const empty = { issue: file.issue, path, suspect: 0, dangling: 0, unknown: 0 };
6498
6373
  try {
6499
- const copy = readFileSync9(resolve5(input.root, path), "utf8");
6374
+ const copy = readFileSync8(resolve5(input.root, path), "utf8");
6500
6375
  const { rows } = await readRefsText({ copy, issue: file.issue, verify: await verify() });
6501
6376
  const states = rows.map((row) => row.state);
6502
6377
  return Object.freeze({
@@ -6788,14 +6663,14 @@ function renderBoard(board) {
6788
6663
  }
6789
6664
 
6790
6665
  // src/commands/doctor-tiers.ts
6791
- import { readFileSync as readFileSync10, realpathSync as realpathSync4 } from "fs";
6666
+ import { readFileSync as readFileSync9, realpathSync as realpathSync4 } from "fs";
6792
6667
  import { basename as basename5, dirname as dirname2 } from "path";
6793
6668
  var TIERS_SECTION_TITLE = "Skill tiers";
6794
6669
  var CLAUDE_VERSION_TIMEOUT_MS = 1e4;
6795
6670
  var VERSION_PATTERN = /^\s*(\d+\.\d+\.\d+)/;
6796
6671
  function readTextFile(path) {
6797
6672
  try {
6798
- return readFileSync10(path, "utf8");
6673
+ return readFileSync9(path, "utf8");
6799
6674
  } catch {
6800
6675
  return null;
6801
6676
  }
@@ -6882,12 +6757,18 @@ function cliVersionRows(installed, pinned = SERVE_CLI_VERSION) {
6882
6757
  }
6883
6758
  return [row("cli-version", "warn", name2, `${installed} is installed, and skill delivery was probed against ${pinned}`, 'run the delivery probe again (context/inventory.md, "Serving") before trusting SERVE_CLI_VERSION')];
6884
6759
  }
6760
+ function skillUseVersionRows(installed, pinned = SKILL_USE_CLI_VERSION) {
6761
+ if (installed === null || installed === pinned)
6762
+ return [];
6763
+ return [row("skill-use-version", "warn", "Claude Code", `${installed} is installed, and the skill-use collector reads logs of ${pinned}, ` + "so skill_invocations stores the skill counts of the sessions it logs as unknown", "record the skill-use fixture again under the installed version (src/effort/skill-use.ts) before moving SKILL_USE_CLI_VERSION")];
6764
+ }
6885
6765
  function doctorTierRows(inventory, installed, readers = {}) {
6886
6766
  const readText2 = readers.readText ?? readTextFile;
6887
6767
  return [
6888
6768
  ...collisionRows(inventory.resolution.collisions),
6889
6769
  ...unreviewedRows(inventory.records, readText2),
6890
6770
  ...cliVersionRows(installed),
6771
+ ...skillUseVersionRows(installed),
6891
6772
  ...copyRows(inventory.resolution.items, readers.realPath ?? realPathOf),
6892
6773
  ...noProvenanceRows(inventory, readText2)
6893
6774
  ];
@@ -7243,7 +7124,7 @@ var collect_default = wrapPhaseZeroCommand({
7243
7124
  subject: "effort",
7244
7125
  action: "collect",
7245
7126
  summary: "collect session and commit rows into the effort store",
7246
- description: "Reads the Claude Code session logs of this repo and its commit history, and appends every" + " session and commit the effort store does not hold yet to the store `store` in" + " `.rafa/config.yaml` selects. A run over an unchanged history appends nothing. An unrecognised" + " argument, a `--since` that is no date and a config the loop cannot run on are each refused," + " one line per problem.",
7127
+ description: "Reads the Claude Code session logs of this repo and its commit history, and appends every" + " session and commit the effort store does not hold yet to the store `store` in" + " `.rafa/config.yaml` selects, then counts the skills each appended session invoked into" + " `effort.sqlite`. A run over an unchanged history appends nothing. An unrecognised" + " argument, a `--since` that is no date and a config the loop cannot run on are each refused," + " one line per problem.",
7247
7128
  args: [],
7248
7129
  flags: [
7249
7130
  {
@@ -7259,10 +7140,15 @@ var collect_default = wrapPhaseZeroCommand({
7259
7140
  },
7260
7141
  {
7261
7142
  name: "sessions",
7262
- description: "Collects session rows; `--no-sessions` skips them. Refused beside `--no-git`," + " which would leave nothing to collect.",
7143
+ description: "Collects session rows; `--no-sessions` skips them. Refused beside `--no-git`," + " which would leave nothing to collect, unless `--skills` is given.",
7263
7144
  type: "boolean",
7264
7145
  default: true
7265
7146
  },
7147
+ {
7148
+ name: "skills",
7149
+ description: "Counts the `Skill` calls of every session the store already holds, not only the ones" + " this run appends. Lifts the refusal of `--no-git` beside `--no-sessions`.",
7150
+ type: "boolean"
7151
+ },
7266
7152
  {
7267
7153
  name: "verbose",
7268
7154
  description: "Prints what each half found before the summary: the logs and plan stubs it read," + " each session read, and the commits parsed.",
@@ -7282,6 +7168,275 @@ var collect_default = wrapPhaseZeroCommand({
7282
7168
  outputs: ["text", "json"]
7283
7169
  }, collect);
7284
7170
 
7171
+ // src/effort/store/fix-schema.ts
7172
+ import { existsSync as existsSync5, renameSync, rmSync as rmSync2 } from "fs";
7173
+ import { Database } from "bun:sqlite";
7174
+ class SchemaFixRefusal extends Error {
7175
+ constructor(message) {
7176
+ super(message);
7177
+ this.name = "SchemaFixRefusal";
7178
+ }
7179
+ }
7180
+ var LIVE = "live";
7181
+ function quoted(name2) {
7182
+ return `"${name2.replaceAll('"', '""')}"`;
7183
+ }
7184
+ function tableNames(db, schema) {
7185
+ return db.query(`SELECT name FROM ${schema}.sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name`).all().map((row2) => row2.name);
7186
+ }
7187
+ function columnNames(db, schema, table) {
7188
+ return db.query("SELECT name FROM pragma_table_info(?, ?)").all(table, schema).map((row2) => row2.name);
7189
+ }
7190
+ function count(db, sql) {
7191
+ return db.query(sql).get()?.n ?? 0;
7192
+ }
7193
+ function versionOf(path) {
7194
+ const db = new Database(path, { readonly: true });
7195
+ try {
7196
+ return db.query("PRAGMA user_version").get()?.user_version ?? 0;
7197
+ } finally {
7198
+ db.close();
7199
+ }
7200
+ }
7201
+ function refuseInFlight(path) {
7202
+ for (const suffix of ["-journal", "-wal"]) {
7203
+ if (existsSync5(`${path}${suffix}`)) {
7204
+ throw new SchemaFixRefusal(`${path}${suffix} is there, so a write is in flight or was interrupted; stop whatever uses the store` + " and open it once with rafa before repairing it");
7205
+ }
7206
+ }
7207
+ }
7208
+ function refuseRemoved(db, known, live) {
7209
+ for (const table of known) {
7210
+ if (!live.has(table)) {
7211
+ throw new SchemaFixRefusal(`the store holds no table ${table}, which this rafa writes; its newer schema is not additive`);
7212
+ }
7213
+ const liveColumns = new Set(columnNames(db, LIVE, table));
7214
+ const missing = columnNames(db, "main", table).filter((column) => !liveColumns.has(column));
7215
+ if (missing.length > 0) {
7216
+ throw new SchemaFixRefusal(`the store holds no column ${missing.map((column) => `${table}.${column}`).join(", ")}, which this rafa` + " writes; its newer schema is not additive");
7217
+ }
7218
+ }
7219
+ }
7220
+ function copyKnown(db, known) {
7221
+ db.transaction(() => {
7222
+ for (const table of known) {
7223
+ const columns2 = columnNames(db, "main", table).map(quoted).join(", ");
7224
+ db.run(`INSERT INTO main.${quoted(table)} (${columns2}) SELECT ${columns2} FROM ${LIVE}.${quoted(table)}`);
7225
+ }
7226
+ })();
7227
+ }
7228
+ function checkedCounts(db, known) {
7229
+ return known.map((table) => {
7230
+ const rows = count(db, `SELECT count(*) AS n FROM main.${quoted(table)}`);
7231
+ const liveRows = count(db, `SELECT count(*) AS n FROM ${LIVE}.${quoted(table)}`);
7232
+ if (rows !== liveRows) {
7233
+ throw new SchemaFixRefusal(`the rebuilt ${table} holds ${String(rows)} rows, the store ${String(liveRows)}`);
7234
+ }
7235
+ return { table, rows };
7236
+ });
7237
+ }
7238
+ function leftBehind(db, known, live) {
7239
+ const leftTables = live.filter((table) => !known.has(table)).map((table) => ({ table, rows: count(db, `SELECT count(*) AS n FROM ${LIVE}.${quoted(table)}`) }));
7240
+ const leftColumns = live.filter((table) => known.has(table)).flatMap((table) => {
7241
+ const kept = new Set(columnNames(db, "main", table));
7242
+ return columnNames(db, LIVE, table).filter((column) => !kept.has(column)).map((column) => ({
7243
+ table,
7244
+ column,
7245
+ values: count(db, `SELECT count(*) AS n FROM ${LIVE}.${quoted(table)} WHERE ${quoted(column)} IS NOT NULL`)
7246
+ }));
7247
+ });
7248
+ return { leftTables, leftColumns };
7249
+ }
7250
+ function refuseCorrupt(db) {
7251
+ const answer = db.query("PRAGMA main.integrity_check").get()?.integrity_check;
7252
+ if (answer !== "ok")
7253
+ throw new SchemaFixRefusal(`the rebuilt store failed integrity_check: ${answer ?? "no answer"}`);
7254
+ }
7255
+ function buildParallel(path, parallelPath, migrations) {
7256
+ const db = new Database(parallelPath, { create: true, readwrite: true });
7257
+ try {
7258
+ migrateSchema(db, parallelPath, migrations);
7259
+ db.run(`ATTACH DATABASE ? AS ${LIVE}`, [path]);
7260
+ const known = tableNames(db, "main");
7261
+ const live = tableNames(db, LIVE);
7262
+ refuseRemoved(db, known, new Set(live));
7263
+ copyKnown(db, known);
7264
+ const kept = checkedCounts(db, known);
7265
+ const left = leftBehind(db, new Set(known), live);
7266
+ db.run(`DETACH DATABASE ${LIVE}`);
7267
+ refuseCorrupt(db);
7268
+ return { kept, ...left };
7269
+ } finally {
7270
+ db.close();
7271
+ }
7272
+ }
7273
+ function removeParallel(parallelPath) {
7274
+ rmSync2(parallelPath, { force: true });
7275
+ rmSync2(`${parallelPath}-journal`, { force: true });
7276
+ }
7277
+ function swapIn(path, parallelPath, backupPath) {
7278
+ renameSync(path, backupPath);
7279
+ try {
7280
+ renameSync(parallelPath, path);
7281
+ } catch (error) {
7282
+ renameSync(backupPath, path);
7283
+ throw error;
7284
+ }
7285
+ }
7286
+ function freshPaths(path, version2, stamp) {
7287
+ const parallelPath = `${path}.fix-${stamp}`;
7288
+ const backupPath = `${path}.v${String(version2)}-${stamp}.bak`;
7289
+ for (const taken of [parallelPath, backupPath]) {
7290
+ if (existsSync5(taken))
7291
+ throw new SchemaFixRefusal(`${taken} is already there; move it aside or pass another stamp`);
7292
+ }
7293
+ return { parallelPath, backupPath };
7294
+ }
7295
+ function fixStoreSchema(options) {
7296
+ const { path, dryRun, stamp } = options;
7297
+ const migrations = options.migrations ?? SQLITE_MIGRATIONS;
7298
+ const knownVersion = migrations.length;
7299
+ const nothing = { kept: [], leftTables: [], leftColumns: [], backupPath: null };
7300
+ if (!existsSync5(path))
7301
+ return { path, status: "missing", storeVersion: null, knownVersion, ...nothing };
7302
+ refuseInFlight(path);
7303
+ const storeVersion = versionOf(path);
7304
+ if (storeVersion === knownVersion)
7305
+ return { path, status: "current", storeVersion, knownVersion, ...nothing };
7306
+ if (storeVersion < knownVersion)
7307
+ return { path, status: "behind", storeVersion, knownVersion, ...nothing };
7308
+ const { parallelPath, backupPath } = freshPaths(path, storeVersion, stamp);
7309
+ let built;
7310
+ try {
7311
+ built = buildParallel(path, parallelPath, migrations);
7312
+ } catch (error) {
7313
+ removeParallel(parallelPath);
7314
+ throw error;
7315
+ }
7316
+ if (dryRun) {
7317
+ removeParallel(parallelPath);
7318
+ return { path, status: "would-rebuild", storeVersion, knownVersion, ...built, backupPath: null };
7319
+ }
7320
+ swapIn(path, parallelPath, backupPath);
7321
+ return { path, status: "rebuilt", storeVersion, knownVersion, ...built, backupPath };
7322
+ }
7323
+
7324
+ // src/commands/effort/fix-schema.ts
7325
+ var COMMAND_NAME5 = "rafa effort fix-schema";
7326
+ var FIX_SCHEMA_USAGE = "rafa effort fix-schema [--dry-run]";
7327
+ var DRY_RUN_FLAG2 = "dry-run";
7328
+ function fileStamp(date) {
7329
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
7330
+ }
7331
+ function refuseLiveLoop(root, isAlive) {
7332
+ let records;
7333
+ try {
7334
+ records = readSessions(root, isAlive === undefined ? {} : { isAlive });
7335
+ } catch (error) {
7336
+ throw new CommandExit(1, `\u274C ${COMMAND_NAME5}: the loop's run records cannot be read, so a live loop cannot be ruled out: ${String(error)}`);
7337
+ }
7338
+ const live = records.find((record) => record.state === "running" || record.state === "paused");
7339
+ if (live === undefined)
7340
+ return;
7341
+ throw new CommandExit(1, `\u274C ${COMMAND_NAME5}: loop session ${live.sessionId} on ${live.branch} is ${live.state} and writes the store;` + ` stop it with \`rafa loop stop -s ${live.sessionId}\` first. \`--dry-run\` runs beside it.`);
7342
+ }
7343
+ function rebuildLines(result) {
7344
+ const rows = result.kept.reduce((sum, table) => sum + table.rows, 0);
7345
+ const kept = result.kept.map((table) => `${table.table} ${String(table.rows)}`).join(", ");
7346
+ const left = [
7347
+ ...result.leftTables.map((table) => `table ${table.table} (${String(table.rows)} rows)`),
7348
+ ...result.leftColumns.map((column) => `column ${column.table}.${column.column} (${String(column.values)} values)`)
7349
+ ];
7350
+ return [
7351
+ `${result.path} is at schema version ${String(result.storeVersion)}, past the ${String(result.knownVersion)} this rafa knows.`,
7352
+ `Keeps ${String(result.kept.length)} tables, ${String(rows)} rows: ${kept}.`,
7353
+ left.length === 0 ? "Leaves nothing behind." : `Leaves behind, kept only in the backup: ${left.join("; ")}.`
7354
+ ];
7355
+ }
7356
+ function renderFixSchema(result) {
7357
+ switch (result.status) {
7358
+ case "missing":
7359
+ return [`No effort store at ${result.path}: nothing to repair.`];
7360
+ case "current":
7361
+ return [`\u2705 ${result.path} is at schema version ${String(result.knownVersion)}, the one this rafa knows: nothing to repair.`];
7362
+ case "behind":
7363
+ return [
7364
+ `${result.path} is at schema version ${String(result.storeVersion)}, behind the ${String(result.knownVersion)} this rafa` + " knows; the next command that opens it migrates it. Nothing to repair."
7365
+ ];
7366
+ case "would-rebuild":
7367
+ return [
7368
+ ...rebuildLines(result),
7369
+ `\uD83D\uDD0D Dry run: the rebuild at version ${String(result.knownVersion)} was built, checked (row counts, integrity_check)` + " and deleted. Run without `--dry-run` to swap it in."
7370
+ ];
7371
+ case "rebuilt":
7372
+ return [
7373
+ ...rebuildLines(result),
7374
+ `\u2705 Rebuilt at version ${String(result.knownVersion)}. The original is kept whole at ${String(result.backupPath)};` + " rename it back to undo."
7375
+ ];
7376
+ }
7377
+ }
7378
+ function runFixSchema(context, seams) {
7379
+ expectNoArgument(context.args, FIX_SCHEMA_USAGE);
7380
+ const dryRun = readSwitch(DRY_RUN_FLAG2, context.flags[DRY_RUN_FLAG2], `Usage: ${FIX_SCHEMA_USAGE}`);
7381
+ if (context.project === null)
7382
+ throw new Error(`${COMMAND_NAME5} runs inside a project, and was handed none`);
7383
+ const root = context.project.root;
7384
+ if (!dryRun)
7385
+ refuseLiveLoop(root, seams.isAlive);
7386
+ let result;
7387
+ try {
7388
+ result = fixStoreSchema({
7389
+ path: sqliteStorePath(root),
7390
+ dryRun,
7391
+ stamp: fileStamp((seams.now ?? (() => new Date))())
7392
+ });
7393
+ } catch (error) {
7394
+ if (error instanceof SchemaFixRefusal)
7395
+ throw new CommandExit(1, `\u274C ${COMMAND_NAME5}: ${error.message}`);
7396
+ throw error;
7397
+ }
7398
+ if (context.outputMode === "json") {
7399
+ context.output.result(result);
7400
+ return;
7401
+ }
7402
+ for (const line of renderFixSchema(result))
7403
+ context.output.info(line);
7404
+ }
7405
+ function createFixSchemaCommand(seams = {}) {
7406
+ const command = {
7407
+ name: "effort fix-schema",
7408
+ subject: "effort",
7409
+ action: "fix-schema",
7410
+ summary: "rebuild an effort store a newer rafa migrated at the version this rafa knows, keeping the original",
7411
+ description: "Repairs `.rafa/effort/effort.sqlite` when it is past the schema version this rafa knows, which" + " happens when newer code opens it, such as a plan's own branch code run while an older installed rafa" + " drives the loop. It builds a parallel store beside it at this rafa's version, copies every table and" + " column this rafa knows, checks the row counts and SQLite's integrity_check, and lists what only the" + " newer schema holds. Then it renames the original to `effort.sqlite.v<version>-<stamp>.bak`, whole, and" + " moves the rebuild into its place. A store at or behind this version, or no store, is left alone. It" + " refuses, changing nothing, while a loop session under the project is running or paused, while a" + " journal beside the store shows a write in flight, and when the newer schema lacks a table or column" + " this rafa writes. With `--output=json` the outcome is the data of the terminal result event. Starts no" + " session.",
7412
+ args: [],
7413
+ flags: [
7414
+ {
7415
+ name: DRY_RUN_FLAG2,
7416
+ description: "Build and check the rebuild, print what it keeps and leaves behind, then delete it. The" + " live store is only read, so this runs beside a live loop and can be repeated.",
7417
+ type: "boolean"
7418
+ }
7419
+ ],
7420
+ examples: [
7421
+ {
7422
+ cmd: "rafa effort fix-schema --dry-run",
7423
+ note: "Prints what a rebuild would keep and leave behind, changing nothing."
7424
+ },
7425
+ {
7426
+ cmd: "rafa effort fix-schema",
7427
+ note: "Swaps the rebuild in and prints where the original was kept."
7428
+ }
7429
+ ],
7430
+ outputs: ["text", "json"],
7431
+ run: async (context) => {
7432
+ runFixSchema(context, seams);
7433
+ await Promise.resolve();
7434
+ }
7435
+ };
7436
+ return Object.freeze(command);
7437
+ }
7438
+ var fix_schema_default = createFixSchemaCommand();
7439
+
7285
7440
  // src/commands/effort/report.ts
7286
7441
  var report_default = wrapPhaseZeroCommand({
7287
7442
  name: "effort report",
@@ -7322,12 +7477,12 @@ var report_default = wrapPhaseZeroCommand({
7322
7477
  }, report);
7323
7478
 
7324
7479
  // src/commands/init.ts
7325
- import { existsSync as existsSync7, readFileSync as readFileSync15 } from "fs";
7480
+ import { existsSync as existsSync8, readFileSync as readFileSync14 } from "fs";
7326
7481
  import { homedir } from "os";
7327
7482
  import { join as join21, relative as relative6, sep as sep4 } from "path";
7328
7483
 
7329
7484
  // src/agents/vendorable.ts
7330
- import { readdirSync as readdirSync2, readFileSync as readFileSync11 } from "fs";
7485
+ import { readdirSync as readdirSync2, readFileSync as readFileSync10 } from "fs";
7331
7486
  import { isAbsolute as isAbsolute5, join as join17 } from "path";
7332
7487
  function planFiles(dir) {
7333
7488
  let entries;
@@ -7340,7 +7495,7 @@ function planFiles(dir) {
7340
7495
  }
7341
7496
  function readText2(path) {
7342
7497
  try {
7343
- return readFileSync11(path, "utf8");
7498
+ return readFileSync10(path, "utf8");
7344
7499
  } catch {
7345
7500
  return null;
7346
7501
  }
@@ -7385,7 +7540,7 @@ function vendorableAgentWarnings(agents, root) {
7385
7540
 
7386
7541
  // src/project/gitignore.ts
7387
7542
  import { createHash } from "crypto";
7388
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync3 } from "fs";
7543
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "fs";
7389
7544
  import { dirname as dirname3, isAbsolute as isAbsolute6, join as join18 } from "path";
7390
7545
  var GITIGNORE_FILE = ".gitignore";
7391
7546
  var DIGEST_NAME = "tracking.digest";
@@ -7472,9 +7627,9 @@ function attempt(file, failure3, act) {
7472
7627
  }
7473
7628
  }
7474
7629
  function readIfPresent2(file) {
7475
- if (!existsSync5(file))
7630
+ if (!existsSync6(file))
7476
7631
  return null;
7477
- return attempt(file, "cannot be read", () => readFileSync12(file, "utf8"));
7632
+ return attempt(file, "cannot be read", () => readFileSync11(file, "utf8"));
7478
7633
  }
7479
7634
  function writeTrackingGitignore(root, flags) {
7480
7635
  requireAbsolute(root);
@@ -7537,7 +7692,7 @@ import { resolve as resolve8 } from "path";
7537
7692
 
7538
7693
  // src/project/roots.ts
7539
7694
  import { spawnSync } from "child_process";
7540
- import { accessSync, constants, readFileSync as readFileSync13, statSync as statSync9 } from "fs";
7695
+ import { accessSync, constants, readFileSync as readFileSync12, statSync as statSync9 } from "fs";
7541
7696
  import { isAbsolute as isAbsolute7, join as join19, resolve as resolve7 } from "path";
7542
7697
  var REFUSED_ROOTS = Object.freeze([
7543
7698
  { path: "/", why: "is the filesystem root" },
@@ -7558,7 +7713,7 @@ var PACKAGE_JSON = "package.json";
7558
7713
  var NOT_A_REPOSITORY = "fatal: not a git repository (or any ";
7559
7714
  var DISK_ROOTS_FILE_SYSTEM = Object.freeze({
7560
7715
  ...DISK_FILE_SYSTEM,
7561
- readFile: (path) => readFileSync13(path, "utf8"),
7716
+ readFile: (path) => readFileSync12(path, "utf8"),
7562
7717
  isDirectory: (path) => statSync9(path).isDirectory(),
7563
7718
  assertWritable: (path) => accessSync(path, constants.W_OK)
7564
7719
  });
@@ -7750,10 +7905,10 @@ function namedRoot(typed, start2, source, seams) {
7750
7905
  return chosen(fs.realpath(path), source);
7751
7906
  }
7752
7907
  function numberedCandidate(digits, found) {
7753
- const count = found.candidates.length;
7908
+ const count2 = found.candidates.length;
7754
7909
  const candidate = found.candidates[Number(digits) - 1];
7755
7910
  if (candidate === undefined) {
7756
- return problem(`no candidate is numbered ${digits}; type 1 to ${String(count)}, or a path`);
7911
+ return problem(`no candidate is numbered ${digits}; type 1 to ${String(count2)}, or a path`);
7757
7912
  }
7758
7913
  return candidate.refusal === null ? chosen(candidate.path, candidate.source) : problem(candidate.refusal.reason);
7759
7914
  }
@@ -7783,7 +7938,7 @@ async function promptForRoot(found, prompter, seams) {
7783
7938
  }
7784
7939
 
7785
7940
  // src/project/scaffold.ts
7786
- import { existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync5, statSync as statSync10, writeFileSync as writeFileSync4 } from "fs";
7941
+ import { existsSync as existsSync7, lstatSync as lstatSync2, mkdirSync as mkdirSync5, statSync as statSync10, writeFileSync as writeFileSync4 } from "fs";
7787
7942
  import { join as join20 } from "path";
7788
7943
  var PROJECT_TREE = Object.freeze(["specs", "plans", "runs", "effort", "instincts"]);
7789
7944
  var USER_TREE = Object.freeze(["instincts"]);
@@ -7799,6 +7954,11 @@ var CONFIG_SETTINGS_LINES = Object.freeze([
7799
7954
  `# fallback: [${CONFIG_DEFAULTS.trackerFallback.join(", ")}]`,
7800
7955
  "# learning:",
7801
7956
  `# adapter: ${CONFIG_DEFAULTS.learningAdapter}`,
7957
+ "# bless:",
7958
+ `# minConfidence: ${String(CONFIG_DEFAULTS.learningBlessMinConfidence)} # 0.3..0.9, the least confidence of a lesson tasks may use`,
7959
+ "# promote:",
7960
+ `# after: ${String(CONFIG_DEFAULTS.learningPromoteAfter)} # distinct sources a lesson needs before the wrap-up promotes it`,
7961
+ `# minConfidence: ${String(CONFIG_DEFAULTS.learningPromoteMinConfidence)} # 0.3..0.9, the least confidence of a lesson to promote`,
7802
7962
  "# output:",
7803
7963
  `# mode: ${CONFIG_DEFAULTS.outputMode} # text | json`,
7804
7964
  "# prerequisites:",
@@ -7839,7 +7999,10 @@ var CONFIG_SETTINGS_LINES = Object.freeze([
7839
7999
  "# skills: {} # name: false turns a skill off; name: project | rafa | user pins its tier",
7840
8000
  "# agents: {} # name: false turns an agent off; name: project | rafa | user pins its tier",
7841
8001
  "# routing:",
7842
- ...DEFAULT_ROUTES.map(([shape, agent]) => `# ${shape}: ${agent}`)
8002
+ ...DEFAULT_ROUTES.map(([shape, agent]) => `# ${shape}: ${agent}`),
8003
+ "# task:",
8004
+ `# skills: ${CONFIG_DEFAULTS.taskSkills} # planner | tag | none, the resolver that picks a task's skills`,
8005
+ `# lessons: ${CONFIG_DEFAULTS.taskLessons} # on | off, whether blessed lessons join a task's prompt`
7843
8006
  ]);
7844
8007
  var VERSION_LINE = `version: ${String(CONFIG_DEFAULTS.version)}`;
7845
8008
  var PROJECT_HEADER = Object.freeze([
@@ -7888,7 +8051,7 @@ function isDirectory2(path) {
7888
8051
  function directoryConflict(dir) {
7889
8052
  if (!occupied(dir) || isDirectory2(dir))
7890
8053
  return null;
7891
- return existsSync6(dir) ? `${dir} is not a directory` : `${dir} is a link to nothing`;
8054
+ return existsSync7(dir) ? `${dir} is not a directory` : `${dir} is a link to nothing`;
7892
8055
  }
7893
8056
  function layoutConflicts(layout) {
7894
8057
  const [scopeDir, ...tree] = layout.dirs;
@@ -7896,7 +8059,7 @@ function layoutConflicts(layout) {
7896
8059
  if (opening !== null)
7897
8060
  return [opening];
7898
8061
  const dirs = tree.flatMap((dir) => directoryConflict(dir) ?? []);
7899
- const file = occupied(layout.configFile) && !existsSync6(layout.configFile) ? [`${layout.configFile} is a link to nothing`] : [];
8062
+ const file = occupied(layout.configFile) && !existsSync7(layout.configFile) ? [`${layout.configFile} is a link to nothing`] : [];
7900
8063
  return [...dirs, ...file];
7901
8064
  }
7902
8065
  function scaffoldConflicts(root, home) {
@@ -7910,7 +8073,7 @@ function attempt2(path, failure3, act) {
7910
8073
  }
7911
8074
  }
7912
8075
  function ensureDirectory(path) {
7913
- if (existsSync6(path))
8076
+ if (existsSync7(path))
7914
8077
  return { path, kind: "directory", change: "unchanged" };
7915
8078
  attempt2(path, "cannot be created", () => {
7916
8079
  mkdirSync5(path, { recursive: true });
@@ -7918,7 +8081,7 @@ function ensureDirectory(path) {
7918
8081
  return { path, kind: "directory", change: "created" };
7919
8082
  }
7920
8083
  function ensureFile(path, text) {
7921
- if (existsSync6(path))
8084
+ if (existsSync7(path))
7922
8085
  return { path, kind: "file", change: "unchanged" };
7923
8086
  attempt2(path, "cannot be written", () => {
7924
8087
  writeFileSync4(path, text, { encoding: "utf8", flag: "wx" });
@@ -7941,7 +8104,7 @@ function writeUserScope(home) {
7941
8104
  import { writeFileSync as writeFileSync5 } from "fs";
7942
8105
 
7943
8106
  // src/release/setting.ts
7944
- import { readFileSync as readFileSync14 } from "fs";
8107
+ import { readFileSync as readFileSync13 } from "fs";
7945
8108
  var RELEASE_ENABLED_SETTING = "release.enabled";
7946
8109
  function releaseEnabledIn(text, path) {
7947
8110
  return parseConfigText(text, path).values.releaseEnabled ?? null;
@@ -7950,7 +8113,7 @@ function readReleaseSetting(root) {
7950
8113
  const path = configFilePath(root);
7951
8114
  let text;
7952
8115
  try {
7953
- text = readFileSync14(path, "utf8");
8116
+ text = readFileSync13(path, "utf8");
7954
8117
  } catch (error) {
7955
8118
  return { enabled: null, text: "", problem: `${path} could not be read: ${messageOf(error)}` };
7956
8119
  }
@@ -8227,7 +8390,7 @@ function resolvedConfig2(root, home, warn) {
8227
8390
  function checkGitignore(root, flags) {
8228
8391
  const file = join21(root, GITIGNORE_FILE);
8229
8392
  try {
8230
- const text = existsSync7(file) ? readFileSync15(file, "utf8") : null;
8393
+ const text = existsSync8(file) ? readFileSync14(file, "utf8") : null;
8231
8394
  withTrackingBlock(text, flags, file);
8232
8395
  } catch (error) {
8233
8396
  const message = error instanceof GitignoreError ? error.message : `rafa init: ${file} cannot be read (${messageOf(error)})`;
@@ -8258,8 +8421,8 @@ function initialise(root, start2, home, context, entry) {
8258
8421
  checkConflicts(root.path, home);
8259
8422
  const config = resolvedConfig2(root.path, home, warn);
8260
8423
  checkGitignore(root.path, config);
8261
- const configExisted = existsSync7(configFilePath(root.path));
8262
- const digestExisted = existsSync7(join21(root.path, TRACKING_DIGEST_FILE));
8424
+ const configExisted = existsSync8(configFilePath(root.path));
8425
+ const digestExisted = existsSync8(join21(root.path, TRACKING_DIGEST_FILE));
8263
8426
  const project = writeProjectScope(root.path);
8264
8427
  const tracking = applyTracking(root.path, config, warn);
8265
8428
  const writes = [...project, ...trackingWrites(tracking, digestExisted), ...writeUserScope(home)];
@@ -8558,72 +8721,196 @@ function createInstinctCheckCommand(seams = DEFAULT_CHECK_SEAMS) {
8558
8721
  }
8559
8722
  var check_default = createInstinctCheckCommand();
8560
8723
 
8561
- // src/commands/instinct/instinct-records.ts
8562
- import { readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync11 } from "fs";
8563
- import { join as join22 } from "path";
8564
- function isRecordFile(name2) {
8565
- return !name2.startsWith(".") && name2.endsWith(MARKDOWN_EXTENSION) && name2 !== MARKDOWN_EXTENSION;
8566
- }
8567
- function recordId(name2) {
8568
- return name2.slice(0, -MARKDOWN_EXTENSION.length);
8724
+ // src/commands/instinct/flag.ts
8725
+ var NAME = "rafa instinct flag";
8726
+ var USAGE6 = "rafa instinct flag <id> <reason>";
8727
+ function refusedFlagMessage(id, kind, reason) {
8728
+ return [
8729
+ `\u274C ${NAME}: the \`${kind}\` learning adapter did not flag "${id}": ${reason}`,
8730
+ "Run `rafa instinct list` to see the ids the project holds."
8731
+ ].join(`
8732
+ `);
8569
8733
  }
8570
- function unreadableIssue(message) {
8571
- return { code: "missing-frontmatter", field: "file", message: `the file could not be read: ${message}` };
8734
+ function blankReasonMessage(id) {
8735
+ return `\u274C ${NAME}: the reason to flag "${id}" is blank; say why the lesson is wrong.
8736
+ Usage: ${USAGE6}`;
8572
8737
  }
8573
- function readRecord(path, scope, id) {
8574
- let text;
8738
+ function makeAdapter(registry, kind, context) {
8575
8739
  try {
8576
- text = readFileSync16(path, "utf8");
8740
+ return registry.resolve("learning", kind).create({
8741
+ repoRoot: context.repoRoot,
8742
+ home: context.home,
8743
+ learningBlessMinConfidence: context.minConfidence
8744
+ });
8577
8745
  } catch (error) {
8578
- const message = error instanceof Error ? error.message : String(error);
8579
- return { scope, path, id, instinct: null, issues: [unreadableIssue(message)] };
8746
+ throw new CommandExit(1, `\u274C ${NAME}: the \`${kind}\` learning adapter cannot be made: ${messageOf(error)}`);
8580
8747
  }
8581
- const parsed = parseInstinct(text);
8582
- return { scope, path, id, instinct: parsed.instinct, issues: parsed.issues };
8583
8748
  }
8584
- function isFile2(path) {
8749
+ async function flagInstinct(context, seams) {
8750
+ const [id, reason] = expectTwoArguments(context.args, USAGE6);
8751
+ if (reason.trim() === "")
8752
+ throw new CommandExit(1, blankReasonMessage(id));
8753
+ const project = requireProject(context, NAME);
8754
+ const config = resolveProjectConfig(project, NAME, (message) => {
8755
+ context.output.warn(message);
8756
+ });
8757
+ const kind = config.learningAdapter;
8758
+ const adapter = makeAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, {
8759
+ repoRoot: project.root,
8760
+ home: project.home,
8761
+ minConfidence: config.learningBlessMinConfidence
8762
+ });
8585
8763
  try {
8586
- return statSync11(path).isFile();
8587
- } catch {
8588
- return false;
8764
+ await adapter.flag(id, reason);
8765
+ } catch (error) {
8766
+ throw new CommandExit(1, refusedFlagMessage(id, kind, messageOf(error)));
8589
8767
  }
8768
+ return { id, reason, adapter: kind };
8590
8769
  }
8591
- function recordFiles(dir) {
8592
- return readdirSync3(dir).filter((name2) => isRecordFile(name2) && isFile2(join22(dir, name2))).sort((left, right) => left.localeCompare(right));
8593
- }
8594
- function readScope3(scope, dir) {
8595
- if (!tierExists(dir))
8596
- return { scope, dir, exists: false, records: [] };
8597
- return {
8598
- scope,
8599
- dir,
8600
- exists: true,
8601
- records: recordFiles(dir).map((name2) => readRecord(join22(dir, name2), scope, recordId(name2)))
8770
+ function createInstinctFlagCommand(seams = {}) {
8771
+ const command = {
8772
+ name: "instinct flag",
8773
+ subject: "instinct",
8774
+ action: "flag",
8775
+ summary: "flag one held lesson as wrong, so no later bundle blesses it",
8776
+ description: "Flags one lesson the project holds as wrong, through the learning adapter" + " `learning.adapter` names in `.rafa/config.yaml`. A flagged id is left out of every bundle the" + " loop pulls afterwards, whatever a later merge writes under it; under the `local` adapter the" + " flag is one line appended to `.rafa/instincts/flags.ndjson` and no record file changes. An id" + " no held record carries is refused with exit code 1 in the adapter's words, a user-scope id" + " included, as is a blank reason. With `--output=json` the id, the reason and the adapter kind" + " are the data of the terminal result event.",
8777
+ args: [
8778
+ {
8779
+ name: "id",
8780
+ description: "The id of a lesson the project holds, as `rafa instinct list` prints it.",
8781
+ type: "string",
8782
+ required: true
8783
+ },
8784
+ {
8785
+ name: "reason",
8786
+ description: "Why the lesson is wrong, quoted as one word; stored beside the flag.",
8787
+ type: "string",
8788
+ required: true
8789
+ }
8790
+ ],
8791
+ flags: [],
8792
+ examples: [
8793
+ {
8794
+ cmd: 'rafa instinct flag worktree-missing-node-modules "bun install runs on fork since 0.9"',
8795
+ note: "Keeps that lesson out of every bundle the loop pulls from now on."
8796
+ },
8797
+ {
8798
+ cmd: 'rafa instinct flag worktree-missing-node-modules "stale" --output=json',
8799
+ note: "Gives the id, the reason and the adapter kind as the data of the terminal result event."
8800
+ }
8801
+ ],
8802
+ outputs: ["text", "json"],
8803
+ run: async (context) => {
8804
+ const result = await flagInstinct(context, seams);
8805
+ if (context.outputMode === "json") {
8806
+ context.output.result(result);
8807
+ return;
8808
+ }
8809
+ context.output.info(`\uD83D\uDEA9 Flagged ${result.id}: ${result.reason}`);
8810
+ context.output.info(` The \`${result.adapter}\` learning adapter leaves it out of every later bundle.`);
8811
+ }
8602
8812
  };
8813
+ return Object.freeze(command);
8603
8814
  }
8604
- function readScopes2(seams) {
8605
- return resolveInstinctScopes(seams).map((location) => readScope3(location.scope, location.dir));
8815
+ var flag_default = createInstinctFlagCommand();
8816
+
8817
+ // src/commands/instinct/promote.ts
8818
+ var NAME2 = "rafa instinct promote";
8819
+ var USAGE7 = "rafa instinct promote";
8820
+ var CONFIDENCE_DIGITS = 2;
8821
+ function refusedPullMessage(kind, reason, name2 = NAME2) {
8822
+ return `\u274C ${name2}: the \`${kind}\` learning adapter answered no blessed set: ${reason}`;
8606
8823
  }
8607
- function allRecords(listings) {
8608
- return listings.flatMap((listing) => listing.records);
8824
+ function makeLearningAdapter(registry, kind, context, name2 = NAME2) {
8825
+ try {
8826
+ return registry.resolve("learning", kind).create({
8827
+ repoRoot: context.repoRoot,
8828
+ home: context.home,
8829
+ learningBlessMinConfidence: context.minConfidence
8830
+ });
8831
+ } catch (error) {
8832
+ throw new CommandExit(1, `\u274C ${name2}: the \`${kind}\` learning adapter cannot be made: ${messageOf(error)}`);
8833
+ }
8609
8834
  }
8610
- function findRecords(listings, id) {
8611
- return allRecords(listings).filter((entry) => entry.id === id);
8835
+ async function promotableLessons(context, seams) {
8836
+ expectNoArgument(context.args, USAGE7);
8837
+ const project = requireProject(context, NAME2);
8838
+ const config = resolveProjectConfig(project, NAME2, (message) => {
8839
+ context.output.warn(message);
8840
+ });
8841
+ const kind = config.learningAdapter;
8842
+ const adapter = makeLearningAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, {
8843
+ repoRoot: project.root,
8844
+ home: project.home,
8845
+ minConfidence: config.learningBlessMinConfidence
8846
+ });
8847
+ const after = config.learningPromoteAfter;
8848
+ const minConfidence = config.learningPromoteMinConfidence;
8849
+ let blessed;
8850
+ try {
8851
+ blessed = (await adapter.pullBlessed()).instincts;
8852
+ } catch (error) {
8853
+ throw new CommandExit(1, refusedPullMessage(kind, messageOf(error)));
8854
+ }
8855
+ return { adapter: kind, after, minConfidence, lessons: promotable(blessed, { after, minConfidence }) };
8612
8856
  }
8613
- function instinctProject(context, name2) {
8614
- if (context.project === null)
8615
- throw new Error(`${name2} runs inside a project, and was handed none`);
8616
- return context.project;
8857
+ function renderPromotable(result) {
8858
+ const keys = `learning.promote.after ${String(result.after)},` + ` learning.promote.minConfidence ${result.minConfidence.toFixed(CONFIDENCE_DIGITS)}`;
8859
+ if (result.lessons.length === 0) {
8860
+ return [`No lesson the \`${result.adapter}\` learning adapter holds is promotable at ${keys}.`];
8861
+ }
8862
+ return [
8863
+ `${String(result.lessons.length)} lesson(s) to promote from the \`${result.adapter}\` learning adapter, at ${keys}:`,
8864
+ ...result.lessons.flatMap((lesson) => [
8865
+ ` ${lesson.id} ${lesson.confidence.toFixed(CONFIDENCE_DIGITS)} used ${String(lesson.usage_count)} ${lesson.trigger}`,
8866
+ ` ${lesson.action}`
8867
+ ])
8868
+ ];
8617
8869
  }
8870
+ function createInstinctPromoteCommand(seams = {}) {
8871
+ const command = {
8872
+ name: "instinct promote",
8873
+ subject: "instinct",
8874
+ action: "promote",
8875
+ summary: "print the lessons that recurred enough to promote, writing nothing",
8876
+ description: "Prints the lessons the project holds that recurred enough to promote: the blessed set" + " of the learning adapter `learning.adapter` names in `.rafa/config.yaml`, narrowed to the" + " lessons at least `learning.promote.after` distinct sources confirmed at a confidence of at least" + " `learning.promote.minConfidence`, most trusted first. It is the list the next wrap-up session" + " would be asked to promote. Nothing is written: no lesson is marked promoted and no file" + " changes. A kind no registry holds, an adapter that cannot be made or a pull it refuses is exit" + " code 1. With `--output=json` the adapter kind, the two keys' values and the lessons are the" + " data of the terminal result event.",
8877
+ args: [],
8878
+ flags: [],
8879
+ examples: [
8880
+ {
8881
+ cmd: "rafa instinct promote",
8882
+ note: "Lists each promotable lesson with its confidence, usage, trigger and action."
8883
+ },
8884
+ {
8885
+ cmd: "rafa instinct promote --output=json",
8886
+ note: "Gives the adapter kind, the two keys' values and the lessons as the data of the terminal result event."
8887
+ }
8888
+ ],
8889
+ outputs: ["text", "json"],
8890
+ run: async (context) => {
8891
+ const result = await promotableLessons(context, seams);
8892
+ if (context.outputMode === "json") {
8893
+ context.output.result(result);
8894
+ return;
8895
+ }
8896
+ for (const line of renderPromotable(result))
8897
+ context.output.info(line);
8898
+ }
8899
+ };
8900
+ return Object.freeze(command);
8901
+ }
8902
+ var promote_default = createInstinctPromoteCommand();
8618
8903
 
8619
8904
  // src/commands/instinct/list.ts
8620
- var USAGE6 = "rafa instinct list";
8621
- var CONFIDENCE_DIGITS = 2;
8905
+ var NAME3 = "rafa instinct list";
8906
+ var USAGE8 = "rafa instinct list [--blessed | --conflicts]";
8907
+ var CONFIDENCE_DIGITS2 = 2;
8908
+ var HUNDREDTHS = 100;
8622
8909
  function instinctRowLine(entry) {
8623
8910
  const record = entry.instinct;
8624
8911
  if (record === null)
8625
8912
  return ` \u274C ${entry.id} ${String(entry.issues.length)} issue(s)`;
8626
- const confidence = record.confidence.toFixed(CONFIDENCE_DIGITS);
8913
+ const confidence = record.confidence.toFixed(CONFIDENCE_DIGITS2);
8627
8914
  return ` \u2705 ${entry.id} ${record.kind}/${record.domain} ${record.signal}` + ` ${confidence} ${record.trigger}`;
8628
8915
  }
8629
8916
  function scopeLines(listing) {
@@ -8643,38 +8930,171 @@ function renderInstinctList(result) {
8643
8930
  `${String(result.total)} instinct(s): ${String(result.clean)} read as records,` + ` ${String(result.total - result.clean)} do not`
8644
8931
  ];
8645
8932
  }
8646
- function runList4(context) {
8647
- expectNoArgument(context.args, USAGE6);
8648
- const project = instinctProject(context, "rafa instinct list");
8649
- const scopes = readScopes2({ home: project.home, projectRoot: project.root });
8933
+ function readViewFlag(name2, value) {
8934
+ if (value === undefined || value === false || value === "false")
8935
+ return false;
8936
+ if (value === true || value === "true")
8937
+ return true;
8938
+ throw new CommandExit(1, `\u274C --${name2} takes no value, and read "${value}" as one
8939
+ Usage: ${USAGE8}`);
8940
+ }
8941
+ function readListView(flags) {
8942
+ const blessed = readViewFlag("blessed", flags["blessed"]);
8943
+ const conflicts = readViewFlag("conflicts", flags["conflicts"]);
8944
+ if (blessed && conflicts) {
8945
+ throw new CommandExit(1, `\u274C --blessed and --conflicts are two views; give one
8946
+ Usage: ${USAGE8}`);
8947
+ }
8948
+ if (blessed)
8949
+ return "blessed";
8950
+ return conflicts ? "conflicts" : "all";
8951
+ }
8952
+ function oneLine(text) {
8953
+ return text.trim().replace(/\s+/gu, " ");
8954
+ }
8955
+ function byConfidence(left, right) {
8956
+ const gap = Math.round(right.confidence * HUNDREDTHS) - Math.round(left.confidence * HUNDREDTHS);
8957
+ if (gap !== 0)
8958
+ return gap;
8959
+ if (left.id < right.id)
8960
+ return -1;
8961
+ return left.id > right.id ? 1 : 0;
8962
+ }
8963
+ function scopeConflicts(listing) {
8964
+ const clean = listing.records.map((entry) => entry.instinct).filter((instinct) => instinct !== null);
8965
+ const groups = new Map;
8966
+ for (const record of toHeldRecords(clean)) {
8967
+ if (record.status !== "flagged")
8968
+ continue;
8969
+ const key = triggerKey(record.trigger);
8970
+ groups.set(key, [...groups.get(key) ?? [], record]);
8971
+ }
8972
+ return [...groups.values()].map((records) => ({
8973
+ scope: listing.scope,
8974
+ trigger: records[0].trigger,
8975
+ records: [...records].sort(byConfidence)
8976
+ }));
8977
+ }
8978
+ function lessonLine(indent, record, width, tail) {
8979
+ return `${indent}${record.id.padEnd(width)} ${record.confidence.toFixed(CONFIDENCE_DIGITS2)}` + ` used ${String(record.usage_count)} ${tail}`;
8980
+ }
8981
+ function conflictLines(conflict) {
8982
+ const width = Math.max(...conflict.records.map((record) => record.id.length));
8983
+ return [
8984
+ ` ${conflict.scope} ${conflict.trigger}`,
8985
+ ...conflict.records.map((record) => lessonLine(" ", record, width, oneLine(record.action)))
8986
+ ];
8987
+ }
8988
+ function renderConflicts(result) {
8989
+ if (result.conflicts.length === 0) {
8990
+ return [`No trigger either instinct scope holds carries more than one action (project: ${result.projectRoot}).`];
8991
+ }
8992
+ return [
8993
+ `Triggers held with more than one action (project: ${result.projectRoot}):`,
8994
+ ...result.conflicts.flatMap((conflict) => conflictLines(conflict)),
8995
+ `${String(result.conflicts.length)} flagged trigger(s): no bundle blesses any of their actions`
8996
+ ];
8997
+ }
8998
+ function renderBlessed(result) {
8999
+ const floor = `learning.bless.minConfidence ${result.minConfidence.toFixed(CONFIDENCE_DIGITS2)}`;
9000
+ if (result.lessons.length === 0) {
9001
+ return [`No lesson the \`${result.adapter}\` learning adapter holds is blessed at ${floor}.`];
9002
+ }
9003
+ return [
9004
+ `${String(result.lessons.length)} lesson(s) blessed by the \`${result.adapter}\` learning adapter, at ${floor}:`,
9005
+ ...result.lessons.flatMap((lesson) => [
9006
+ lessonLine(" ", lesson, 0, lesson.trigger),
9007
+ ` ${lesson.action}`
9008
+ ])
9009
+ ];
9010
+ }
9011
+ async function blessedLessons(context, seams) {
9012
+ const project = instinctProject(context, NAME3);
9013
+ const config = resolveProjectConfig(project, NAME3, (message) => {
9014
+ context.output.warn(message);
9015
+ });
9016
+ const kind = config.learningAdapter;
9017
+ const minConfidence = config.learningBlessMinConfidence;
9018
+ const adapter = makeLearningAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, { repoRoot: project.root, home: project.home, minConfidence }, NAME3);
9019
+ try {
9020
+ return { adapter: kind, minConfidence, lessons: (await adapter.pullBlessed()).instincts };
9021
+ } catch (error) {
9022
+ throw new CommandExit(1, refusedPullMessage(kind, messageOf(error), NAME3));
9023
+ }
9024
+ }
9025
+ function conflicts(context) {
9026
+ const project = instinctProject(context, NAME3);
9027
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
9028
+ return { projectRoot: project.root, conflicts: scopes.flatMap((listing) => scopeConflicts(listing)) };
9029
+ }
9030
+ function everyRecord(context) {
9031
+ const project = instinctProject(context, NAME3);
9032
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
8650
9033
  const records = allRecords(scopes);
8651
- const result = {
9034
+ return {
8652
9035
  projectRoot: project.root,
8653
9036
  scopes,
8654
9037
  total: records.length,
8655
9038
  clean: records.filter((entry) => entry.instinct !== null).length
8656
9039
  };
9040
+ }
9041
+ function answer(context, result, lines2) {
8657
9042
  if (context.outputMode === "json") {
8658
9043
  context.output.result(result);
8659
9044
  return;
8660
9045
  }
8661
- for (const line of renderInstinctList(result))
9046
+ for (const line of lines2())
8662
9047
  context.output.info(line);
8663
9048
  }
8664
- function createInstinctListCommand() {
9049
+ async function runList4(context, seams) {
9050
+ expectNoArgument(context.args, USAGE8);
9051
+ const view = readListView(context.flags);
9052
+ if (view === "blessed") {
9053
+ const result2 = await blessedLessons(context, seams);
9054
+ answer(context, result2, () => renderBlessed(result2));
9055
+ return;
9056
+ }
9057
+ if (view === "conflicts") {
9058
+ const result2 = conflicts(context);
9059
+ answer(context, result2, () => renderConflicts(result2));
9060
+ return;
9061
+ }
9062
+ const result = everyRecord(context);
9063
+ answer(context, result, () => renderInstinctList(result));
9064
+ }
9065
+ function createInstinctListCommand(seams = {}) {
8665
9066
  const command = {
8666
9067
  name: "instinct list",
8667
9068
  subject: "instinct",
8668
9069
  action: "list",
8669
9070
  summary: "list the records the project and user instinct scopes hold",
8670
- description: "Lists every instinct record the two scopes hold \u2014 this project's `.rafa/instincts` and" + " `~/.rafa/instincts` \u2014 with, for each, the id its file name gives it, its `kind/domain` pair, its" + " `signal`, its `confidence` and its `trigger`. A record that breaks a rule of the instinct schema" + " shows the number of rules it broke instead, which `rafa instinct check` then names. The local" + " Learning adapter's `instincts.ndjson` and `flags.ndjson` are its store and no records, and are" + " passed over. A scope whose directory is not there says so. The exit code is 0 whatever the rows" + " say: this command reports and `rafa instinct check` gates. With `--output=json` the scopes and" + " their records are the data of the terminal result event.",
9071
+ description: "Lists every instinct record the two scopes hold \u2014 this project's `.rafa/instincts` and" + " `~/.rafa/instincts` \u2014 with, for each, the id its file name gives it, its `kind/domain` pair, its" + " `signal`, its `confidence` and its `trigger`. A record that breaks a rule of the instinct schema" + " shows the number of rules it broke instead, which `rafa instinct check` then names. The local" + " Learning adapter's `instincts.ndjson` and `flags.ndjson` are its store and no records, and are" + " passed over. A scope whose directory is not there says so. The exit code is 0 whatever the rows" + " say: this command reports and `rafa instinct check` gates. `--blessed` lists instead the lessons" + " the learning adapter `learning.adapter` names would hand a task, at `learning.bless.minConfidence`," + " most trusted first, writing nothing; an adapter that cannot be made or a pull it refuses is exit" + " code 1. `--conflicts` lists instead each trigger a scope holds with more than one action, which a" + " merge flagged and no bundle blesses, its actions side by side with their confidence and usage." + " The two views are one at a time. With `--output=json` the scopes and their records, or the view" + " asked for, are the data of the terminal result event.",
8671
9072
  args: [],
8672
- flags: [],
9073
+ flags: [
9074
+ {
9075
+ name: "blessed",
9076
+ description: "List the lessons the configured learning adapter blesses, each with its confidence, usage," + " trigger and action, instead of every record. Takes no value.",
9077
+ type: "boolean"
9078
+ },
9079
+ {
9080
+ name: "conflicts",
9081
+ description: "List each trigger held with more than one action, its actions side by side with their" + " confidence and usage, instead of every record. Takes no value.",
9082
+ type: "boolean"
9083
+ }
9084
+ ],
8673
9085
  examples: [
8674
9086
  {
8675
9087
  cmd: "rafa instinct list",
8676
9088
  note: "Lists both scopes, each record with what it is about."
8677
9089
  },
9090
+ {
9091
+ cmd: "rafa instinct list --blessed",
9092
+ note: "Lists the lessons a task would be handed, most trusted first."
9093
+ },
9094
+ {
9095
+ cmd: "rafa instinct list --conflicts",
9096
+ note: "Lists each flagged trigger with its actions side by side."
9097
+ },
8678
9098
  {
8679
9099
  cmd: "rafa instinct list --output=json",
8680
9100
  note: "Gives the scopes and every record parsed as the data of the terminal result event."
@@ -8682,7 +9102,7 @@ function createInstinctListCommand() {
8682
9102
  ],
8683
9103
  outputs: ["text", "json"],
8684
9104
  run: async (context) => {
8685
- runList4(context);
9105
+ await runList4(context, seams);
8686
9106
  }
8687
9107
  };
8688
9108
  return Object.freeze(command);
@@ -8690,7 +9110,7 @@ function createInstinctListCommand() {
8690
9110
  var list_default4 = createInstinctListCommand();
8691
9111
 
8692
9112
  // src/commands/instinct/show.ts
8693
- var USAGE7 = "rafa instinct show <id>";
9113
+ var USAGE9 = "rafa instinct show <id>";
8694
9114
  var FIELD_ORDER = [
8695
9115
  "trigger",
8696
9116
  "kind",
@@ -8762,13 +9182,13 @@ function unreadableMessage(entry) {
8762
9182
  }
8763
9183
  function unknownIdMessage(id, scopes) {
8764
9184
  const looked = scopes.map((listing) => ` ${listing.scope} ${listing.dir}${listing.exists ? "" : " (no such directory)"}`);
8765
- return [`\u274C No instinct is filed under "${id}". Looked in:`, ...looked, `Usage: ${USAGE7}`].join(`
9185
+ return [`\u274C No instinct is filed under "${id}". Looked in:`, ...looked, `Usage: ${USAGE9}`].join(`
8766
9186
  `);
8767
9187
  }
8768
9188
  function runShow2(context) {
8769
- const id = expectOneArgument(context.args, USAGE7);
9189
+ const id = expectOneArgument(context.args, USAGE9);
8770
9190
  const project = instinctProject(context, "rafa instinct show");
8771
- const scopes = readScopes2({ home: project.home, projectRoot: project.root });
9191
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
8772
9192
  const found = findRecords(scopes, id);
8773
9193
  if (found.length === 0)
8774
9194
  throw new CommandExit(1, unknownIdMessage(id, scopes));
@@ -8825,8 +9245,8 @@ function createInstinctShowCommand() {
8825
9245
  var show_default2 = createInstinctShowCommand();
8826
9246
 
8827
9247
  // src/commands/issue/check.ts
8828
- import { readdirSync as readdirSync4, readFileSync as readFileSync17, statSync as statSync12 } from "fs";
8829
- import { join as join23, resolve as resolve10 } from "path";
9248
+ import { readdirSync as readdirSync3, readFileSync as readFileSync15, statSync as statSync11 } from "fs";
9249
+ import { join as join22, resolve as resolve10 } from "path";
8830
9250
  var CHECK_USAGE = "rafa issue check <n> [--stamp]";
8831
9251
  var STAMP_FLAG = "stamp";
8832
9252
  var ISSUE_NUMBER = /^[1-9]\d*$/u;
@@ -8850,7 +9270,7 @@ function missingCopyMessage(issue, specsDir) {
8850
9270
  function copyNames(dir, issue) {
8851
9271
  let names;
8852
9272
  try {
8853
- names = readdirSync4(dir);
9273
+ names = readdirSync3(dir);
8854
9274
  } catch (error) {
8855
9275
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
8856
9276
  return [];
@@ -8858,7 +9278,7 @@ function copyNames(dir, issue) {
8858
9278
  }
8859
9279
  const prefix = `${boardId(issue)}-`;
8860
9280
  const notes = notesFileName(issue);
8861
- return names.filter((name2) => name2.startsWith(prefix) && name2.endsWith(SPEC_EXTENSION) && name2 !== notes).filter((name2) => name2.length > prefix.length + SPEC_EXTENSION.length).filter((name2) => statSync12(join23(dir, name2)).isFile()).sort();
9281
+ return names.filter((name2) => name2.startsWith(prefix) && name2.endsWith(SPEC_EXTENSION) && name2 !== notes).filter((name2) => name2.length > prefix.length + SPEC_EXTENSION.length).filter((name2) => statSync11(join22(dir, name2)).isFile()).sort();
8862
9282
  }
8863
9283
  function findSavedCopy(root, specsDir, issue) {
8864
9284
  const names = copyNames(resolve10(root, specsDir), issue);
@@ -8868,11 +9288,11 @@ function findSavedCopy(root, specsDir, issue) {
8868
9288
  if (names.length > 1) {
8869
9289
  throw new CommandExit(1, [
8870
9290
  `\u274C Issue #${String(issue)} has ${String(names.length)} saved copies under ${specsDir}; remove the stale one:`,
8871
- ...names.map((name2) => ` ${join23(specsDir, name2)}`)
9291
+ ...names.map((name2) => ` ${join22(specsDir, name2)}`)
8872
9292
  ].join(`
8873
9293
  `));
8874
9294
  }
8875
- const path = join23(specsDir, only);
9295
+ const path = join22(specsDir, only);
8876
9296
  return { path, absolute: resolve10(root, path) };
8877
9297
  }
8878
9298
  function liveText(live) {
@@ -8902,7 +9322,7 @@ function checkedRefLine(ref) {
8902
9322
  }
8903
9323
  function countLine(references) {
8904
9324
  const noun = references.length === 1 ? "reference" : "references";
8905
- const counts = STATE_ORDER.map((state) => [state, references.filter((ref) => ref.state === state).length]).filter(([, count]) => count > 0).map(([state, count]) => `${String(count)} ${state}`);
9325
+ const counts = STATE_ORDER.map((state) => [state, references.filter((ref) => ref.state === state).length]).filter(([, count2]) => count2 > 0).map(([state, count2]) => `${String(count2)} ${state}`);
8906
9326
  return counts.length === 0 ? "No references." : `${String(references.length)} ${noun}: ${counts.join(", ")}`;
8907
9327
  }
8908
9328
  function renderCheck2(result) {
@@ -8921,7 +9341,7 @@ async function readReferences(absolute, issue, verify, stamp) {
8921
9341
  return rows.map((row2) => checkedRef(row2, row2.stamp));
8922
9342
  }
8923
9343
  const once = memoiseVerifier(verify);
8924
- const before = await readRefsText({ copy: readFileSync17(absolute, "utf8"), issue, verify: once });
9344
+ const before = await readRefsText({ copy: readFileSync15(absolute, "utf8"), issue, verify: once });
8925
9345
  const after = await restampCopyRefs({ path: absolute, issue, verify: once });
8926
9346
  return before.rows.map((row2, index) => checkedRef(row2, after.rows[index]?.stamp ?? null));
8927
9347
  }
@@ -8996,10 +9416,10 @@ function createIssueCheckCommand(seams = {}) {
8996
9416
  var check_default2 = createIssueCheckCommand();
8997
9417
 
8998
9418
  // src/commands/issue/comment.ts
8999
- var USAGE8 = "rafa issue comment <id> --body=<text>";
9419
+ var USAGE10 = "rafa issue comment <id> --body=<text>";
9000
9420
  async function commentOnIssue(context, seams) {
9001
- const id = expectOneArgument(context.args, USAGE8);
9002
- const body = readRequiredFlag(context.flags, "body", USAGE8);
9421
+ const id = expectOneArgument(context.args, USAGE10);
9422
+ const body = readRequiredFlag(context.flags, "body", USAGE10);
9003
9423
  const { tracker, data } = await resolveIssueTracker(context, seams);
9004
9424
  const ref = issueRef(tracker, id);
9005
9425
  await onTracker(tracker, `comment on issue ${id}`, () => tracker.comment(ref, body));
@@ -9053,16 +9473,16 @@ function createIssueCommentCommand(seams = DEFAULT_ISSUE_SEAMS) {
9053
9473
  var comment_default = createIssueCommentCommand();
9054
9474
 
9055
9475
  // src/commands/issue/create.ts
9056
- var USAGE9 = "rafa issue create --title=<text> [--body=<text>] [--type=<type>] [--module=<name>] [--priority=<priority>]";
9476
+ var USAGE11 = "rafa issue create --title=<text> [--body=<text>] [--type=<type>] [--module=<name>] [--priority=<priority>]";
9057
9477
  var DEFAULT_ISSUE_TYPE = "code";
9058
9478
  function readIssueDraft(flags) {
9059
9479
  return {
9060
9480
  opt: 0,
9061
- title: readRequiredFlag(flags, "title", USAGE9),
9062
- body: readTextFlag(flags, "body", USAGE9) ?? "",
9063
- type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE9) ?? DEFAULT_ISSUE_TYPE,
9064
- module: readNonBlankFlag(flags, "module", USAGE9) ?? TRIAGE_MODULE,
9065
- priority: readChoiceFlag(flags, "priority", ISSUE_PRIORITIES, USAGE9) ?? null,
9481
+ title: readRequiredFlag(flags, "title", USAGE11),
9482
+ body: readTextFlag(flags, "body", USAGE11) ?? "",
9483
+ type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE11) ?? DEFAULT_ISSUE_TYPE,
9484
+ module: readNonBlankFlag(flags, "module", USAGE11) ?? TRIAGE_MODULE,
9485
+ priority: readChoiceFlag(flags, "priority", ISSUE_PRIORITIES, USAGE11) ?? null,
9066
9486
  project: null,
9067
9487
  blockedBy: []
9068
9488
  };
@@ -9071,7 +9491,7 @@ function renderCreated(ref) {
9071
9491
  return [`Created ${issueName(ref)}.`, ...urlLines(ref)];
9072
9492
  }
9073
9493
  async function createIssue(context, seams) {
9074
- expectNoArgument(context.args, USAGE9);
9494
+ expectNoArgument(context.args, USAGE11);
9075
9495
  const draft = readIssueDraft(context.flags);
9076
9496
  const { tracker, data } = await resolveIssueTracker(context, seams);
9077
9497
  const ref = await onTracker(tracker, "create the issue", () => tracker.create(draft));
@@ -9223,7 +9643,7 @@ function createGhBoardListing(options) {
9223
9643
  }
9224
9644
 
9225
9645
  // src/board/roadmap-rows.ts
9226
- import { readdirSync as readdirSync5 } from "fs";
9646
+ import { readdirSync as readdirSync4 } from "fs";
9227
9647
  var OUTLINE_HEADINGS = 3;
9228
9648
  var UNKNOWN_STATE = "unknown";
9229
9649
  function isMissing(error) {
@@ -9232,7 +9652,7 @@ function isMissing(error) {
9232
9652
  function createPlanDirNames(dir) {
9233
9653
  return () => {
9234
9654
  try {
9235
- return Object.freeze(readdirSync5(dir));
9655
+ return Object.freeze(readdirSync4(dir));
9236
9656
  } catch (error) {
9237
9657
  if (isMissing(error))
9238
9658
  return Object.freeze([]);
@@ -9463,24 +9883,24 @@ function renderRoadmapTable(rows, width) {
9463
9883
  }
9464
9884
 
9465
9885
  // src/commands/issue/list.ts
9466
- var USAGE10 = "rafa issue list [--roadmap [--all]] [--state=<state>] [--type=<type>] [--module=<name>]" + " [--search=<text>] [--limit=<n>]";
9467
- var SWITCH_HINT = `Type it bare: ${USAGE10}`;
9886
+ var USAGE12 = "rafa issue list [--roadmap [--all]] [--state=<state>] [--type=<type>] [--module=<name>]" + " [--search=<text>] [--limit=<n>]";
9887
+ var SWITCH_HINT = `Type it bare: ${USAGE12}`;
9468
9888
  var LIMIT = /^[1-9]\d*$/;
9469
9889
  function readLimit(flags) {
9470
- const value = readTextFlag(flags, "limit", USAGE10);
9890
+ const value = readTextFlag(flags, "limit", USAGE12);
9471
9891
  if (value === undefined)
9472
9892
  return;
9473
9893
  const limit = Number(value);
9474
9894
  if (LIMIT.test(value) && Number.isSafeInteger(limit))
9475
9895
  return limit;
9476
- throw lineRefusal(`--limit is "${value}", expected a positive whole number`, USAGE10);
9896
+ throw lineRefusal(`--limit is "${value}", expected a positive whole number`, USAGE12);
9477
9897
  }
9478
9898
  function readIssueQuery(flags) {
9479
9899
  const narrowed = {
9480
- state: readChoiceFlag(flags, "state", ISSUE_STATES, USAGE10),
9481
- type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE10),
9482
- module: readNonBlankFlag(flags, "module", USAGE10),
9483
- text: readNonBlankFlag(flags, "search", USAGE10),
9900
+ state: readChoiceFlag(flags, "state", ISSUE_STATES, USAGE12),
9901
+ type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE12),
9902
+ module: readNonBlankFlag(flags, "module", USAGE12),
9903
+ text: readNonBlankFlag(flags, "search", USAGE12),
9484
9904
  limit: readLimit(flags)
9485
9905
  };
9486
9906
  return Object.fromEntries(Object.entries(narrowed).filter(([, value]) => value !== undefined));
@@ -9489,10 +9909,10 @@ function readIssueListLine(flags) {
9489
9909
  const roadmap = readSwitch("roadmap", flags["roadmap"], SWITCH_HINT);
9490
9910
  const all = readSwitch("all", flags["all"], SWITCH_HINT);
9491
9911
  if (roadmap && flags["state"] !== undefined) {
9492
- throw lineRefusal("--state cannot narrow --roadmap: the Roadmap is read off the GitHub board, which holds an issue open or" + " closed and so no state of the tracker", USAGE10);
9912
+ throw lineRefusal("--state cannot narrow --roadmap: the Roadmap is read off the GitHub board, which holds an issue open or" + " closed and so no state of the tracker", USAGE12);
9493
9913
  }
9494
9914
  if (all && !roadmap)
9495
- throw lineRefusal("--all keeps the ticked Roadmap lines, so it needs --roadmap", USAGE10);
9915
+ throw lineRefusal("--all keeps the ticked Roadmap lines, so it needs --roadmap", USAGE12);
9496
9916
  return { roadmap, all };
9497
9917
  }
9498
9918
  function renderIssueList(kind, issues) {
@@ -9571,7 +9991,7 @@ async function listRoadmap(context, seams, all, filter) {
9571
9991
  });
9572
9992
  }
9573
9993
  async function listIssues(context, seams) {
9574
- expectNoArgument(context.args, USAGE10);
9994
+ expectNoArgument(context.args, USAGE12);
9575
9995
  const query = readIssueQuery(context.flags);
9576
9996
  const { tracker, data } = await resolveIssueTracker(context, seams);
9577
9997
  const refs = await onTracker(tracker, "list issues", () => tracker.find(query));
@@ -9590,7 +10010,7 @@ async function runIssueList(context, seams) {
9590
10010
  context.output.info(text);
9591
10011
  return;
9592
10012
  }
9593
- expectNoArgument(context.args, USAGE10);
10013
+ expectNoArgument(context.args, USAGE12);
9594
10014
  const filter = readIssueQuery(context.flags);
9595
10015
  const listed2 = await listRoadmap(context, seams, line.all, filter);
9596
10016
  if (context.outputMode === "json") {
@@ -9677,10 +10097,10 @@ function createIssueListCommand(seams = DEFAULT_ISSUE_SEAMS) {
9677
10097
  var list_default5 = createIssueListCommand();
9678
10098
 
9679
10099
  // src/commands/issue/move.ts
9680
- var USAGE11 = "rafa issue move <id> <state>";
10100
+ var USAGE13 = "rafa issue move <id> <state>";
9681
10101
  async function moveIssue(context, seams) {
9682
- const [id, word] = expectTwoArguments(context.args, USAGE11);
9683
- const state = readChoice(word, "The state", ISSUE_STATES, USAGE11);
10102
+ const [id, word] = expectTwoArguments(context.args, USAGE13);
10103
+ const state = readChoice(word, "The state", ISSUE_STATES, USAGE13);
9684
10104
  const { tracker, data } = await resolveIssueTracker(context, seams);
9685
10105
  const ref = issueRef(tracker, id);
9686
10106
  const moved = await onTracker(tracker, `move issue ${id} to ${state}`, () => tracker.transition(ref, state));
@@ -9739,7 +10159,7 @@ function createIssueMoveCommand(seams = DEFAULT_ISSUE_SEAMS) {
9739
10159
  var move_default = createIssueMoveCommand();
9740
10160
 
9741
10161
  // src/commands/issue/show.ts
9742
- var USAGE12 = "rafa issue show <id>";
10162
+ var USAGE14 = "rafa issue show <id>";
9743
10163
  var NO_PRIORITY = "needs-triage";
9744
10164
  function renderIssue(kind, issue) {
9745
10165
  const project = issue.project === null ? [] : [`Project: ${issue.project}`];
@@ -9761,7 +10181,7 @@ function renderIssue(kind, issue) {
9761
10181
  ];
9762
10182
  }
9763
10183
  async function showIssue(context, seams) {
9764
- const id = expectOneArgument(context.args, USAGE12);
10184
+ const id = expectOneArgument(context.args, USAGE14);
9765
10185
  const { tracker, data } = await resolveIssueTracker(context, seams);
9766
10186
  const issue = await onTracker(tracker, `read issue ${id}`, () => tracker.get(issueRef(tracker, id)));
9767
10187
  return { tracker: data, issue };
@@ -10050,8 +10470,8 @@ function projectRoot2(context) {
10050
10470
  throw new Error("rafa issue unblock runs inside a project, and was handed none");
10051
10471
  return context.project.root;
10052
10472
  }
10053
- function isYes(answer) {
10054
- return answer !== null && YES_ANSWERS2.includes(answer.trim().toLowerCase());
10473
+ function isYes(answer2) {
10474
+ return answer2 !== null && YES_ANSWERS2.includes(answer2.trim().toLowerCase());
10055
10475
  }
10056
10476
  function lazyPrompter2(open) {
10057
10477
  let prompter = null;
@@ -10151,7 +10571,7 @@ function createIssueUnblockCommand(seams = DEFAULT_UNBLOCK_SEAMS) {
10151
10571
  var unblock_default = createIssueUnblockCommand();
10152
10572
 
10153
10573
  // src/commands/loop/list.ts
10154
- var USAGE13 = "rafa loop list";
10574
+ var USAGE15 = "rafa loop list";
10155
10575
  function renderSessionList(list) {
10156
10576
  if (list.sessions.length === 0)
10157
10577
  return ["No running sessions."];
@@ -10161,7 +10581,7 @@ function renderSessionList(list) {
10161
10581
  ];
10162
10582
  }
10163
10583
  async function runList5(context, seams) {
10164
- expectNoArgument(context.args, USAGE13);
10584
+ expectNoArgument(context.args, USAGE15);
10165
10585
  const root = projectRoot(context);
10166
10586
  const sessions = readRecords(root, seams).filter(isLive).map((session) => {
10167
10587
  const checklist = readSessionChecklist(root, session);
@@ -10206,7 +10626,7 @@ function createLoopListCommand(seams = {}) {
10206
10626
  var list_default6 = createLoopListCommand();
10207
10627
 
10208
10628
  // src/commands/loop/pause.ts
10209
- var USAGE14 = "rafa loop pause [-s|--session-id=<id>]";
10629
+ var USAGE16 = "rafa loop pause [-s|--session-id=<id>]";
10210
10630
  function renderPause(result) {
10211
10631
  const { session } = result;
10212
10632
  if (!result.changed)
@@ -10215,8 +10635,8 @@ function renderPause(result) {
10215
10635
  return [when, " Nothing is marked. `rafa loop resume` goes on, and `rafa loop stop` ends the run."];
10216
10636
  }
10217
10637
  async function runPause(context, seams) {
10218
- expectNoArgument(context.args, USAGE14);
10219
- const { root, record } = pickSession(context, USAGE14, "live", seams);
10638
+ expectNoArgument(context.args, USAGE16);
10639
+ const { root, record } = pickSession(context, USAGE16, "live", seams);
10220
10640
  if (!isLive(record)) {
10221
10641
  throw refusal(`Session ${record.sessionId} reads ${record.state}: no run is left to pause.`);
10222
10642
  }
@@ -10256,7 +10676,7 @@ function createLoopPauseCommand(seams = {}) {
10256
10676
  var pause_default = createLoopPauseCommand();
10257
10677
 
10258
10678
  // src/commands/loop/resume.ts
10259
- var USAGE15 = "rafa loop resume [-s|--session-id=<id>]";
10679
+ var USAGE17 = "rafa loop resume [-s|--session-id=<id>]";
10260
10680
  function renderResume(result) {
10261
10681
  const { session } = result;
10262
10682
  if (!result.changed)
@@ -10264,8 +10684,8 @@ function renderResume(result) {
10264
10684
  return [session.task === null ? `Resumed session ${session.sessionId}: it goes on with its next task.` : `Resumed session ${session.sessionId}: it goes on past its running task, line ${session.task.line}, ${session.task.text}`];
10265
10685
  }
10266
10686
  async function runResume(context, seams) {
10267
- expectNoArgument(context.args, USAGE15);
10268
- const { root, record } = pickSession(context, USAGE15, "live", seams);
10687
+ expectNoArgument(context.args, USAGE17);
10688
+ const { root, record } = pickSession(context, USAGE17, "live", seams);
10269
10689
  if (!isLive(record)) {
10270
10690
  throw refusal(`Session ${record.sessionId} reads ${record.state}: its run has ended, so there is nothing to resume.`, `\`rafa loop start --plan=${record.plan}\` runs its plan again as a new session, its blocked tasks first.`);
10271
10691
  }
@@ -10328,6 +10748,11 @@ var wrapped = wrapPhaseZeroCommand({
10328
10748
  description: "How much of the plan each task session is handed: `full`, `stage` or `task`." + " Outranks `plan.inject` in `.rafa/config.yaml`. The wrap-up is handed the whole plan.",
10329
10749
  type: "string"
10330
10750
  },
10751
+ {
10752
+ name: "skills-resolver",
10753
+ description: "The resolver that picks the skills each task session is handed: `planner`, `tag`" + " or `none`. Outranks `task.skills` in `.rafa/config.yaml` for this run only.",
10754
+ type: "string"
10755
+ },
10331
10756
  {
10332
10757
  name: "runtime",
10333
10758
  description: "The installed rafa the run goes on in: a version under `~/.rafa/runtime/`, or a path" + " against the working directory to a `cli.js` or the directory holding it. Refused inside the" + " `src/` of the working directory or the project root. Typed after `loop start`.",
@@ -10400,7 +10825,7 @@ var loopStart = Object.freeze({
10400
10825
  var start_default = endingWith(loopStart);
10401
10826
 
10402
10827
  // src/commands/loop/status.ts
10403
- var USAGE16 = "rafa loop status [-s|--session-id=<id>]";
10828
+ var USAGE18 = "rafa loop status [-s|--session-id=<id>]";
10404
10829
  var BLOCKED_TASK_LINE = /^- \[BLOCKED\] (.+)/;
10405
10830
  var NO_BLOCKER = "the line trails no blocker comment";
10406
10831
  function blockerAt(checklist, lineNum) {
@@ -10436,8 +10861,8 @@ function renderStatus(status) {
10436
10861
  ];
10437
10862
  }
10438
10863
  async function runStatus(context, seams) {
10439
- expectNoArgument(context.args, USAGE16);
10440
- const { root, record } = pickSession(context, USAGE16, "live-or-newest", seams);
10864
+ expectNoArgument(context.args, USAGE18);
10865
+ const { root, record } = pickSession(context, USAGE18, "live-or-newest", seams);
10441
10866
  const checklist = readSessionChecklist(root, record);
10442
10867
  const tasks = checklist === null ? null : countTasks(checklist.tasks);
10443
10868
  let eta = null;
@@ -10490,7 +10915,7 @@ function createLoopStatusCommand(seams = {}) {
10490
10915
  var status_default = createLoopStatusCommand();
10491
10916
 
10492
10917
  // src/commands/loop/stop.ts
10493
- var USAGE17 = "rafa loop stop [-s|--session-id=<id>]";
10918
+ var USAGE19 = "rafa loop stop [-s|--session-id=<id>]";
10494
10919
  function signalRun(record, interrupt) {
10495
10920
  try {
10496
10921
  interrupt(record.pid);
@@ -10543,8 +10968,8 @@ function renderStop(result) {
10543
10968
  ];
10544
10969
  }
10545
10970
  async function runStop(context, seams) {
10546
- expectNoArgument(context.args, USAGE17);
10547
- const { root, record } = pickSession(context, USAGE17, "live", seams);
10971
+ expectNoArgument(context.args, USAGE19);
10972
+ const { root, record } = pickSession(context, USAGE19, "live", seams);
10548
10973
  if (!isLive(record)) {
10549
10974
  throw refusal(`Session ${record.sessionId} reads ${record.state}: no run is left to stop.`);
10550
10975
  }
@@ -10595,7 +11020,7 @@ function createLoopStopCommand(seams = {}) {
10595
11020
  var stop_default = createLoopStopCommand();
10596
11021
 
10597
11022
  // src/commands/module/exec.ts
10598
- var USAGE18 = "rafa module exec <module> <action> [args] [flags]";
11023
+ var USAGE20 = "rafa module exec <module> <action> [args] [flags]";
10599
11024
  var execCommand = {
10600
11025
  name: "module exec",
10601
11026
  subject: "module",
@@ -10624,13 +11049,13 @@ var execCommand = {
10624
11049
  const mounts = context.registry.mounts();
10625
11050
  const mounted = mounts.length === 0 ? "none is mounted; a module is mounted when allowList: names it and modules: gives its path source" : mounts.map((mount) => `${mount.name} (${context.registry.actionsOf(mountKey(mount.name)).map((held) => held.action).join(", ")})`).join(", ");
10626
11051
  throw new CommandExit(1, `\u274C Expected a module and one of its actions; mounted: ${mounted}
10627
- Usage: ${USAGE18}`);
11052
+ Usage: ${USAGE20}`);
10628
11053
  }
10629
11054
  };
10630
11055
  var exec_default = Object.freeze(execCommand);
10631
11056
 
10632
11057
  // src/commands/module/list.ts
10633
- var USAGE19 = "rafa module list";
11058
+ var USAGE21 = "rafa module list";
10634
11059
  function sourceText(source) {
10635
11060
  const ref = source.ref === null ? "" : `@${source.ref}`;
10636
11061
  return `${source.kind} ${source.location}${ref}`;
@@ -10651,10 +11076,10 @@ function renderModuleList(list) {
10651
11076
  return ["Modules:", ...list.modules.flatMap(moduleLines)];
10652
11077
  }
10653
11078
  async function runList6(context, seams) {
10654
- expectNoArgument(context.args, USAGE19);
11079
+ expectNoArgument(context.args, USAGE21);
10655
11080
  const { project } = context;
10656
11081
  if (project === null)
10657
- throw new CommandExit(1, `\u274C ${USAGE19} runs inside a project`);
11082
+ throw new CommandExit(1, `\u274C ${USAGE21} runs inside a project`);
10658
11083
  let loaded;
10659
11084
  try {
10660
11085
  const resolved = loadConfig({ root: project.root, home: project.home });
@@ -10807,7 +11232,7 @@ function fastForwardBase(git, plan2) {
10807
11232
 
10808
11233
  // src/commands/next.ts
10809
11234
  var NEXT_USAGE = "rafa next [--dry-run] [--yes[=<action ids>]]";
10810
- var DRY_RUN_FLAG2 = "dry-run";
11235
+ var DRY_RUN_FLAG3 = "dry-run";
10811
11236
  var STATE_MARK = "\uD83D\uDCCD";
10812
11237
  var PROPOSAL_MARK = "\uD83D\uDC49";
10813
11238
  var STOP_MARK = "\u23F9";
@@ -10828,7 +11253,7 @@ function dryRunLine(dryRun) {
10828
11253
  if (dryRun === "no-terminal") {
10829
11254
  return `${STOP_MARK} There is no terminal to answer on, so nothing ran; run rafa next where you can answer,` + ` or type --${YES_FLAG}=${BARE_YES_ACTIONS.join(",")} to allow those steps unasked.`;
10830
11255
  }
10831
- return `${STOP_MARK} --${DRY_RUN_FLAG2}: nothing ran.`;
11256
+ return `${STOP_MARK} --${DRY_RUN_FLAG3}: nothing ran.`;
10832
11257
  }
10833
11258
  function stopLine(stop, state, ceiling, dryRun) {
10834
11259
  if (stop === "dry-run")
@@ -10924,14 +11349,14 @@ function lineRefusal2(problem2) {
10924
11349
  Usage: ${NEXT_USAGE}`);
10925
11350
  }
10926
11351
  function readDryRun(flags) {
10927
- const value = flags[DRY_RUN_FLAG2];
11352
+ const value = flags[DRY_RUN_FLAG3];
10928
11353
  if (value === undefined)
10929
11354
  return false;
10930
11355
  if (typeof value === "boolean")
10931
11356
  return value;
10932
11357
  if (value === "true" || value === "false")
10933
11358
  return value === "true";
10934
- throw lineRefusal2(`--${DRY_RUN_FLAG2} takes no value, and read "${value}" as one`);
11359
+ throw lineRefusal2(`--${DRY_RUN_FLAG3} takes no value, and read "${value}" as one`);
10935
11360
  }
10936
11361
  function dryRunOf(flag, ceiling, hasTerminal) {
10937
11362
  if (flag)
@@ -10983,7 +11408,7 @@ async function runNext(context, seams) {
10983
11408
  var YES_ID_LIST = YES_ACTIONS.join(", ");
10984
11409
  var NEXT_FLAGS = Object.freeze([
10985
11410
  {
10986
- name: DRY_RUN_FLAG2,
11411
+ name: DRY_RUN_FLAG3,
10987
11412
  description: "Print where the project stands and what to do about it, and stop without asking or running it." + " A run with no terminal to answer on and no --yes does this whether or not the flag is typed.",
10988
11413
  type: "boolean"
10989
11414
  },
@@ -11120,10 +11545,10 @@ var wrapped2 = wrapPhaseZeroCommand({
11120
11545
  var create_default2 = endingWith(wrapped2);
11121
11546
 
11122
11547
  // src/commands/plan/risk.ts
11123
- import { readFileSync as readFileSync18 } from "fs";
11548
+ import { readFileSync as readFileSync16 } from "fs";
11124
11549
  import { resolve as resolve11 } from "path";
11125
11550
  var COMMAND2 = "rafa plan risk";
11126
- var USAGE20 = "rafa plan risk [<plan>] [--strict]";
11551
+ var USAGE22 = "rafa plan risk [<plan>] [--strict]";
11127
11552
  var STRICT_HINT = `Type the plan first: ${COMMAND2} <plan> --strict`;
11128
11553
  function spawningRunners(root) {
11129
11554
  return { git: createGitRunner(root), gh: createGhRunner({ cwd: root }) };
@@ -11136,7 +11561,7 @@ function riskPlanPath(root, planDir, typed) {
11136
11561
  throw new CommandExit(1, `\u274C Plan file not found: ${path}`);
11137
11562
  const lookedFor = [...new Set([resolve11(root, planDir, DEFAULT_PLAN_FILE), resolve11(root, DEFAULT_PLAN_FILE)])];
11138
11563
  throw new CommandExit(1, `\u274C No plan named, and no default plan at ${lookedFor.join(" or ")}
11139
- Usage: ${USAGE20}`);
11564
+ Usage: ${USAGE22}`);
11140
11565
  }
11141
11566
  function riskLine(finding) {
11142
11567
  const line = finding.line === undefined ? "" : `:${String(finding.line)}`;
@@ -11148,7 +11573,7 @@ function strictRefusal(report2) {
11148
11573
  }
11149
11574
  async function readRisk(path, project, config, context, seams) {
11150
11575
  const makeRunners = seams.runners ?? spawningRunners;
11151
- return assessPlanRisk({ path, text: readFileSync18(path, "utf8") }, {
11576
+ return assessPlanRisk({ path, text: readFileSync16(path, "utf8") }, {
11152
11577
  repoRoot: project.root,
11153
11578
  home: project.home,
11154
11579
  settingSources: config.settingSources,
@@ -11200,7 +11625,7 @@ function createPlanRiskCommand(seams = {}) {
11200
11625
  outputs: ["text", "json"],
11201
11626
  run: async (context) => {
11202
11627
  const strict = readSwitch("strict", context.flags["strict"], STRICT_HINT);
11203
- const typed = expectAtMostOneArgument(context.args, USAGE20);
11628
+ const typed = expectAtMostOneArgument(context.args, USAGE22);
11204
11629
  const project = requireProject(context, COMMAND2);
11205
11630
  const config = resolveProjectConfig(project, COMMAND2, (message) => {
11206
11631
  context.output.warn(message);
@@ -11231,9 +11656,9 @@ function createPlanRiskCommand(seams = {}) {
11231
11656
  var risk_default = createPlanRiskCommand();
11232
11657
 
11233
11658
  // src/commands/plan/show.ts
11234
- import { readFileSync as readFileSync19 } from "fs";
11235
- import { join as join24 } from "path";
11236
- var USAGE21 = "rafa plan show <stub> [--tracker]";
11659
+ import { readFileSync as readFileSync17 } from "fs";
11660
+ import { join as join23 } from "path";
11661
+ var USAGE23 = "rafa plan show <stub> [--tracker]";
11237
11662
  var COMMAND3 = "rafa plan show";
11238
11663
  function readTrackerFlag(value) {
11239
11664
  if (value === undefined || value === false || value === "false")
@@ -11250,10 +11675,10 @@ function showPlan(plans, stub, tracker) {
11250
11675
  throw new CommandExit(1, `\u274C "${stub}" is no plan stub: a stub is letters, digits, ".", "_" and "-"`);
11251
11676
  }
11252
11677
  const name2 = planFileName(stub, tracker);
11253
- const file = join24(plans.path, name2);
11678
+ const file = join23(plans.path, name2);
11254
11679
  if (!isFile(file))
11255
- throw new CommandExit(1, missingText(stub, tracker, join24(plans.label, name2)));
11256
- const model = parsePlan(readFileSync19(file, "utf8"));
11680
+ throw new CommandExit(1, missingText(stub, tracker, join23(plans.label, name2)));
11681
+ const model = parsePlan(readFileSync17(file, "utf8"));
11257
11682
  const { header } = model;
11258
11683
  return {
11259
11684
  stub,
@@ -11276,7 +11701,7 @@ function taskLine(task) {
11276
11701
  return ` ${checkbox(task.status)} ${task.text}`;
11277
11702
  }
11278
11703
  function renderShownPlan(shown, dirLabel) {
11279
- const relative7 = join24(dirLabel, planFileName(shown.stub, shown.tracker));
11704
+ const relative7 = join23(dirLabel, planFileName(shown.stub, shown.tracker));
11280
11705
  const fileLabel = shown.tracker ? "Tracker" : "File";
11281
11706
  const lines2 = [`Plan: ${shown.stub}`, `${fileLabel}: ${relative7}`];
11282
11707
  if (shown.header.issue !== null)
@@ -11329,7 +11754,7 @@ var planShowCommand = {
11329
11754
  outputs: ["text", "json"],
11330
11755
  run: async (context) => {
11331
11756
  const tracker = readTrackerFlag(context.flags.tracker);
11332
- const stub = expectOneArgument(context.args, USAGE21);
11757
+ const stub = expectOneArgument(context.args, USAGE23);
11333
11758
  const plans = resolvePlansDir(requireProject(context, COMMAND3), COMMAND3, (message) => {
11334
11759
  context.output.warn(message);
11335
11760
  });
@@ -11468,7 +11893,7 @@ Run rafa pr list to see the open pull requests.`, usage2);
11468
11893
  }
11469
11894
 
11470
11895
  // src/commands/pr/current.ts
11471
- var USAGE22 = PR_USAGE.current;
11896
+ var USAGE24 = PR_USAGE.current;
11472
11897
  var SEPARATOR = " \u2014 ";
11473
11898
  function trimmedOrNull(value) {
11474
11899
  const trimmed = value.trim();
@@ -11499,9 +11924,9 @@ async function probeChecks(pulls, number) {
11499
11924
  }
11500
11925
  }
11501
11926
  async function readCurrent(context, seams) {
11502
- expectNoArguments(context.args, USAGE22);
11927
+ expectNoArguments(context.args, USAGE24);
11503
11928
  const pr = openPrContext(context, seams);
11504
- const pick = await pickPullRequest(pr, null, USAGE22);
11929
+ const pick = await pickPullRequest(pr, null, USAGE24);
11505
11930
  const summary = pick.summary;
11506
11931
  const probe = await probeChecks(pr.pulls, pick.number);
11507
11932
  const reading = {
@@ -11554,7 +11979,7 @@ function createPrCurrentCommand(seams = DEFAULT_PR_SEAMS) {
11554
11979
  var current_default = createPrCurrentCommand();
11555
11980
 
11556
11981
  // src/commands/pr/list.ts
11557
- var USAGE23 = PR_USAGE.list;
11982
+ var USAGE25 = PR_USAGE.list;
11558
11983
  var UNREADABLE2 = "?";
11559
11984
  var PROBE_LIMIT = 6;
11560
11985
  var TITLE_WIDTH = 60;
@@ -11597,8 +12022,8 @@ function titleCell(title) {
11597
12022
  return "(no title)";
11598
12023
  return trimmed.length > TITLE_WIDTH ? `${trimmed.slice(0, TITLE_WIDTH - CUT.length)}${CUT}` : trimmed;
11599
12024
  }
11600
- function headLine3(count) {
11601
- return count === 1 ? "1 open pull request" : `${count} open pull requests`;
12025
+ function headLine3(count2) {
12026
+ return count2 === 1 ? "1 open pull request" : `${count2} open pull requests`;
11602
12027
  }
11603
12028
  function cellsOf(row2, now) {
11604
12029
  return [
@@ -11655,7 +12080,7 @@ async function rowOf3(pulls, pull) {
11655
12080
  };
11656
12081
  }
11657
12082
  async function readList(context, seams, now) {
11658
- expectNoArguments(context.args, USAGE23);
12083
+ expectNoArguments(context.args, USAGE25);
11659
12084
  const pr = openPrContext(context, seams);
11660
12085
  const open = await onProvider("list the open pull requests", () => pr.pulls.list());
11661
12086
  const rows = await mapWithLimit(open, PROBE_LIMIT, (pull) => rowOf3(pr.pulls, pull));
@@ -11695,8 +12120,8 @@ function createPrListCommand(seams = DEFAULT_PR_SEAMS) {
11695
12120
  var list_default8 = createPrListCommand();
11696
12121
 
11697
12122
  // src/commands/pr/merge.ts
11698
- import { existsSync as existsSync9, readFileSync as readFileSync21 } from "fs";
11699
- import { join as join26 } from "path";
12123
+ import { existsSync as existsSync10, readFileSync as readFileSync19 } from "fs";
12124
+ import { join as join25 } from "path";
11700
12125
 
11701
12126
  // src/board/roadmap-tick.ts
11702
12127
  var PREFIX5 = "board roadmap";
@@ -11851,17 +12276,17 @@ function tickSentence(result) {
11851
12276
  import {
11852
12277
  chmodSync,
11853
12278
  copyFileSync as copyFileSync3,
11854
- existsSync as existsSync8,
12279
+ existsSync as existsSync9,
11855
12280
  mkdirSync as mkdirSync6,
11856
- readdirSync as readdirSync6,
11857
- readFileSync as readFileSync20,
12281
+ readdirSync as readdirSync5,
12282
+ readFileSync as readFileSync18,
11858
12283
  realpathSync as realpathSync5,
11859
- renameSync,
11860
- rmSync as rmSync2,
11861
- statSync as statSync13,
12284
+ renameSync as renameSync2,
12285
+ rmSync as rmSync3,
12286
+ statSync as statSync12,
11862
12287
  symlinkSync
11863
12288
  } from "fs";
11864
- import { basename as basename7, delimiter as delimiter2, dirname as dirname4, join as join25, relative as relative7, resolve as resolve12 } from "path";
12289
+ import { basename as basename7, delimiter as delimiter2, dirname as dirname4, join as join24, relative as relative7, resolve as resolve12 } from "path";
11865
12290
  var LINK_NAME = "rafa";
11866
12291
  var FORCE_FLAG = "--force";
11867
12292
  var EXIT_DONE = 0;
@@ -11923,19 +12348,19 @@ function runtimeRefusalLines(runtimeDir, version2) {
11923
12348
  }
11924
12349
  function listTrackers(repoRoot, planDir) {
11925
12350
  const dir = resolve12(repoRoot, planDir);
11926
- return entryNames(dir).filter((entry) => TRACKER_NAME.test(entry)).sort((a, b) => a.localeCompare(b)).map((entry) => join25(dir, entry)).filter((path) => statSync13(path).isFile()).map((path) => relative7(repoRoot, path));
12351
+ return entryNames(dir).filter((entry) => TRACKER_NAME.test(entry)).sort((a, b) => a.localeCompare(b)).map((entry) => join24(dir, entry)).filter((path) => statSync12(path).isFile()).map((path) => relative7(repoRoot, path));
11927
12352
  }
11928
12353
  function openTrackers(repoRoot, planDir) {
11929
12354
  return listTrackers(repoRoot, planDir).flatMap((path) => {
11930
- const task = findNextTask(readFileSync20(join25(repoRoot, path), "utf8"));
12355
+ const task = findNextTask(readFileSync18(join24(repoRoot, path), "utf8"));
11931
12356
  return task ? [{ path, task }] : [];
11932
12357
  });
11933
12358
  }
11934
12359
  function readManifestVersion2(repoRoot) {
11935
- const manifest = JSON.parse(readFileSync20(join25(repoRoot, "package.json"), "utf8"));
12360
+ const manifest = JSON.parse(readFileSync18(join24(repoRoot, "package.json"), "utf8"));
11936
12361
  const record = typeof manifest === "object" && manifest !== null ? manifest : {};
11937
12362
  if (record["name"] !== name) {
11938
- throw new Error(`${join25(repoRoot, "package.json")} names ${JSON.stringify(record["name"])}, not ${name}: this is no rafa checkout`);
12363
+ throw new Error(`${join24(repoRoot, "package.json")} names ${JSON.stringify(record["name"])}, not ${name}: this is no rafa checkout`);
11939
12364
  }
11940
12365
  const version2 = record["version"];
11941
12366
  if (typeof version2 !== "string" || !VERSION_SHAPE.test(version2)) {
@@ -11946,10 +12371,10 @@ function readManifestVersion2(repoRoot) {
11946
12371
  function copyTree(from, to) {
11947
12372
  mkdirSync6(to, { recursive: true });
11948
12373
  let copied = 0;
11949
- const entries = readdirSync6(from, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
12374
+ const entries = readdirSync5(from, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
11950
12375
  for (const entry of entries) {
11951
- const source = join25(from, entry.name);
11952
- const target = join25(to, entry.name);
12376
+ const source = join24(from, entry.name);
12377
+ const target = join24(to, entry.name);
11953
12378
  if (entry.isDirectory()) {
11954
12379
  copied += copyTree(source, target);
11955
12380
  } else if (entry.isFile()) {
@@ -11963,41 +12388,41 @@ function copyTree(from, to) {
11963
12388
  }
11964
12389
  function replaceTree(from, to) {
11965
12390
  const staging = temporaryName(to);
11966
- rmSync2(staging, { recursive: true, force: true });
12391
+ rmSync3(staging, { recursive: true, force: true });
11967
12392
  try {
11968
12393
  const copied = copyTree(from, staging);
11969
- swapIn(staging, to);
12394
+ swapIn2(staging, to);
11970
12395
  return copied;
11971
12396
  } catch (err) {
11972
- rmSync2(staging, { recursive: true, force: true });
12397
+ rmSync3(staging, { recursive: true, force: true });
11973
12398
  throw err;
11974
12399
  }
11975
12400
  }
11976
- function swapIn(staging, to) {
11977
- if (!existsSync8(to)) {
11978
- renameSync(staging, to);
12401
+ function swapIn2(staging, to) {
12402
+ if (!existsSync9(to)) {
12403
+ renameSync2(staging, to);
11979
12404
  return;
11980
12405
  }
11981
12406
  const outgoing = `${temporaryName(to)}.outgoing`;
11982
- rmSync2(outgoing, { recursive: true, force: true });
11983
- renameSync(to, outgoing);
12407
+ rmSync3(outgoing, { recursive: true, force: true });
12408
+ renameSync2(to, outgoing);
11984
12409
  try {
11985
- renameSync(staging, to);
12410
+ renameSync2(staging, to);
11986
12411
  } catch (err) {
11987
- renameSync(outgoing, to);
12412
+ renameSync2(outgoing, to);
11988
12413
  throw err;
11989
12414
  }
11990
- rmSync2(outgoing, { recursive: true, force: true });
12415
+ rmSync3(outgoing, { recursive: true, force: true });
11991
12416
  }
11992
12417
  function relink(linkPath, target) {
11993
12418
  mkdirSync6(dirname4(linkPath), { recursive: true });
11994
12419
  const temporary = temporaryName(linkPath);
11995
- rmSync2(temporary, { force: true });
12420
+ rmSync3(temporary, { force: true });
11996
12421
  try {
11997
12422
  symlinkSync(target, temporary);
11998
- renameSync(temporary, linkPath);
12423
+ renameSync2(temporary, linkPath);
11999
12424
  } catch (err) {
12000
- rmSync2(temporary, { force: true });
12425
+ rmSync3(temporary, { force: true });
12001
12426
  throw err;
12002
12427
  }
12003
12428
  const resolved = realpathSync5(linkPath);
@@ -12044,8 +12469,8 @@ function installRuntime(seams, options = {}) {
12044
12469
  }
12045
12470
  function runInstall(seams, options) {
12046
12471
  const { repoRoot, home, log } = seams;
12047
- const runtimeRoot = join25(home, RUNTIME_SUBDIR);
12048
- const linkPath = join25(home, RAFA_BIN_DIR, LINK_NAME);
12472
+ const runtimeRoot = join24(home, RUNTIME_SUBDIR);
12473
+ const linkPath = join24(home, RAFA_BIN_DIR, LINK_NAME);
12049
12474
  log(`repo root: ${repoRoot}`);
12050
12475
  log(`runtime root: ${runtimeRoot}`);
12051
12476
  log(`link: ${linkPath}`);
@@ -12055,9 +12480,9 @@ function runInstall(seams, options) {
12055
12480
  const open = inStage("trackers", () => openTrackers(repoRoot, planDir));
12056
12481
  if (open.length > 0)
12057
12482
  return { kind: "refused", reason: "trackers", planDir, trackers: open };
12058
- const distDir = join25(repoRoot, "dist");
12059
- const runtimeDir = join25(runtimeRoot, version2);
12060
- const installed = existsSync8(runtimeDir);
12483
+ const distDir = join24(repoRoot, "dist");
12484
+ const runtimeDir = join24(runtimeRoot, version2);
12485
+ const installed = existsSync9(runtimeDir);
12061
12486
  if (installed && options.force !== true) {
12062
12487
  return { kind: "refused", reason: "runtime-exists", version: version2, runtimeDir };
12063
12488
  }
@@ -12065,13 +12490,13 @@ function runInstall(seams, options) {
12065
12490
  const code = inStage("build", () => seams.build(repoRoot));
12066
12491
  if (code !== 0)
12067
12492
  throw new StageFailure("build", `the build exited ${code}`);
12068
- if (!existsSync8(join25(distDir, RUNTIME_ENTRY))) {
12069
- throw new StageFailure("build", `the build exited 0 and left no ${join25(distDir, RUNTIME_ENTRY)}`);
12493
+ if (!existsSync9(join24(distDir, RUNTIME_ENTRY))) {
12494
+ throw new StageFailure("build", `the build exited 0 and left no ${join24(distDir, RUNTIME_ENTRY)}`);
12070
12495
  }
12071
12496
  log(installed ? `copying ${distDir} over ${runtimeDir}, replacing it whole` : `copying ${distDir} into ${runtimeDir}`);
12072
12497
  const copied = inStage("copy", () => replaceTree(distDir, runtimeDir));
12073
12498
  log(`copied ${copied} file(s)`);
12074
- const resolved = inStage("link", () => relink(linkPath, join25(runtimeDir, RUNTIME_ENTRY)));
12499
+ const resolved = inStage("link", () => relink(linkPath, join24(runtimeDir, RUNTIME_ENTRY)));
12075
12500
  log(`${linkPath} resolves to ${resolved}`);
12076
12501
  return { kind: "done", version: version2, runtimeDir, linkPath, resolved, copied };
12077
12502
  }
@@ -12086,7 +12511,7 @@ function inStage(stage, run) {
12086
12511
  }
12087
12512
  function entryNames(dir) {
12088
12513
  try {
12089
- return readdirSync6(dir);
12514
+ return readdirSync5(dir);
12090
12515
  } catch (err) {
12091
12516
  if (typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT")
12092
12517
  return [];
@@ -12097,15 +12522,15 @@ function replaceFile(source, target) {
12097
12522
  const temporary = temporaryName(target);
12098
12523
  try {
12099
12524
  copyFileSync3(source, temporary);
12100
- chmodSync(temporary, statSync13(source).mode & 4095);
12101
- renameSync(temporary, target);
12525
+ chmodSync(temporary, statSync12(source).mode & 4095);
12526
+ renameSync2(temporary, target);
12102
12527
  } catch (err) {
12103
- rmSync2(temporary, { force: true });
12528
+ rmSync3(temporary, { force: true });
12104
12529
  throw err;
12105
12530
  }
12106
12531
  }
12107
12532
  function temporaryName(path) {
12108
- return join25(dirname4(path), `.${basename7(path)}.snapshot-${process.pid}`);
12533
+ return join24(dirname4(path), `.${basename7(path)}.snapshot-${process.pid}`);
12109
12534
  }
12110
12535
 
12111
12536
  // src/commands/pr/merge-followups.ts
@@ -12281,8 +12706,8 @@ async function readUncheckedMerge(options) {
12281
12706
  }
12282
12707
  return Object.freeze({ workflowCount, reading, yes });
12283
12708
  }
12284
- function isYes2(answer) {
12285
- return answer !== null && YES_ANSWERS3.includes(answer.trim().toLowerCase());
12709
+ function isYes2(answer2) {
12710
+ return answer2 !== null && YES_ANSWERS3.includes(answer2.trim().toLowerCase());
12286
12711
  }
12287
12712
  async function confirmUncheckedMerge(unchecked, options) {
12288
12713
  for (const line of unchecked.reading.warning)
@@ -12298,11 +12723,11 @@ async function confirmUncheckedMerge(unchecked, options) {
12298
12723
  }
12299
12724
  }
12300
12725
  function commentProblemLine(number, problem2, body) {
12301
- const quoted = body.split(`
12726
+ const quoted2 = body.split(`
12302
12727
  `).map((line) => `${INDENT3}${line}`).join(`
12303
12728
  `);
12304
12729
  return `the unchecked-merge comment was not posted on #${number}: ${problem2}. Post it yourself:
12305
- ${quoted}`;
12730
+ ${quoted2}`;
12306
12731
  }
12307
12732
  async function postUncheckedComment(pulls, number, unchecked, warn) {
12308
12733
  const body = unchecked.reading.comment;
@@ -12315,7 +12740,7 @@ async function postUncheckedComment(pulls, number, unchecked, warn) {
12315
12740
  }
12316
12741
 
12317
12742
  // src/commands/pr/merge.ts
12318
- var USAGE24 = PR_USAGE.merge;
12743
+ var USAGE26 = PR_USAGE.merge;
12319
12744
  var REMOTE3 = "origin";
12320
12745
  var INDENT4 = " ";
12321
12746
  var YES_ANSWERS4 = ["y", "yes"];
@@ -12373,8 +12798,8 @@ function requireTerminal(seams, summary) {
12373
12798
  "Merge it without the question with --yes."
12374
12799
  ]);
12375
12800
  }
12376
- function isYes3(answer) {
12377
- return answer !== null && YES_ANSWERS4.includes(answer.trim().toLowerCase());
12801
+ function isYes3(answer2) {
12802
+ return answer2 !== null && YES_ANSWERS4.includes(answer2.trim().toLowerCase());
12378
12803
  }
12379
12804
  function prompterOf(seams) {
12380
12805
  return seams.openPrompter ?? (() => createLinePrompter(process.stdin, process.stderr));
@@ -12396,13 +12821,13 @@ function remoteHoldsBranch(git, branch, warn) {
12396
12821
  }
12397
12822
  function textOf(path) {
12398
12823
  try {
12399
- return readFileSync21(path, "utf8");
12824
+ return readFileSync19(path, "utf8");
12400
12825
  } catch {
12401
12826
  return "";
12402
12827
  }
12403
12828
  }
12404
12829
  function followUpsFor(pr, git) {
12405
- const facts = readPackageFacts(textOf(join26(pr.project.root, "package.json")));
12830
+ const facts = readPackageFacts(textOf(join25(pr.project.root, "package.json")));
12406
12831
  if (facts.version === null)
12407
12832
  return [];
12408
12833
  const tags = git(["tag", "--list", versionTag(facts.version)]);
@@ -12410,7 +12835,7 @@ function followUpsFor(pr, git) {
12410
12835
  version: facts.version,
12411
12836
  tagged: tags.ok && tags.stdout.trim() !== "",
12412
12837
  rafaCheckout: facts.rafaCheckout,
12413
- runtimeInstalled: existsSync9(join26(pr.project.home, RUNTIME_SUBDIR, facts.version))
12838
+ runtimeInstalled: existsSync10(join25(pr.project.home, RUNTIME_SUBDIR, facts.version))
12414
12839
  });
12415
12840
  }
12416
12841
  function openGh(pr, seams) {
@@ -12522,22 +12947,22 @@ async function commentIfUnchecked(context, pr, number, unchecked) {
12522
12947
  return posted.url;
12523
12948
  }
12524
12949
  async function runMerge(context, seams) {
12525
- const yes = readBooleanFlag(context.flags, "yes", USAGE24);
12526
- const skipChecks = readBooleanFlag(context.flags, "skip-checks", USAGE24);
12527
- const wanted = readMethodFlag(context.flags, USAGE24);
12528
- const asked = readPullArgument(context.args, USAGE24);
12950
+ const yes = readBooleanFlag(context.flags, "yes", USAGE26);
12951
+ const skipChecks = readBooleanFlag(context.flags, "skip-checks", USAGE26);
12952
+ const wanted = readMethodFlag(context.flags, USAGE26);
12953
+ const asked = readPullArgument(context.args, USAGE26);
12529
12954
  const pr = openPrContext(context, seams);
12530
12955
  const git = (seams.git ?? createGitRunner)(pr.project.root);
12531
12956
  const method = wanted ?? pr.mergeMethod;
12532
- const pick = await pickPullRequest(pr, asked, USAGE24);
12957
+ const pick = await pickPullRequest(pr, asked, USAGE26);
12533
12958
  const detail = await onProvider(`read pull request #${pick.number}`, () => pr.pulls.get(pick.number));
12534
12959
  if (detail === null) {
12535
- throw lineRefusal3(`No pull request #${pick.number} at ${pr.project.root}`, USAGE24);
12960
+ throw lineRefusal3(`No pull request #${pick.number} at ${pr.project.root}`, USAGE26);
12536
12961
  }
12537
12962
  const checks = await onProvider(`read the checks of #${pick.number}`, () => pr.pulls.checks(pick.number));
12538
12963
  refuseFromGit(git, detail, checks, skipChecks);
12539
12964
  const summary = summaryLine2(detail, method);
12540
- const answer = await askToMerge(context, pr, seams, { number: detail.number, summary, yes, skipChecks });
12965
+ const answer2 = await askToMerge(context, pr, seams, { number: detail.number, summary, yes, skipChecks });
12541
12966
  const answered3 = {
12542
12967
  number: detail.number,
12543
12968
  source: pick.source,
@@ -12552,9 +12977,9 @@ async function runMerge(context, seams) {
12552
12977
  followUps: [],
12553
12978
  roadmapTick: null,
12554
12979
  unblocked: null,
12555
- unchecked: uncheckedReport(answer.unchecked, null)
12980
+ unchecked: uncheckedReport(answer2.unchecked, null)
12556
12981
  };
12557
- if (!answer.go) {
12982
+ if (!answer2.go) {
12558
12983
  context.output.info("Nothing was merged.");
12559
12984
  return answered3;
12560
12985
  }
@@ -12563,7 +12988,7 @@ async function runMerge(context, seams) {
12563
12988
  throw refusal5([`\u274C ${pr.pulls.kind} would not merge #${detail.number}: ${outcome2.detail}`]);
12564
12989
  }
12565
12990
  context.output.info(`Merged #${detail.number} into ${detail.baseRefName} (${method}).`);
12566
- const commentUrl = await commentIfUnchecked(context, pr, detail.number, answer.unchecked);
12991
+ const commentUrl = await commentIfUnchecked(context, pr, detail.number, answer2.unchecked);
12567
12992
  const roadmapTick = await reportTick(context, pr, seams, detail);
12568
12993
  const remoteBranchPresent = remoteHoldsBranch(git, detail.headRefName, (message) => {
12569
12994
  context.output.warn(message);
@@ -12586,7 +13011,7 @@ async function runMerge(context, seams) {
12586
13011
  followUps,
12587
13012
  roadmapTick,
12588
13013
  unblocked,
12589
- unchecked: uncheckedReport(answer.unchecked, commentUrl)
13014
+ unchecked: uncheckedReport(answer2.unchecked, commentUrl)
12590
13015
  };
12591
13016
  }
12592
13017
  function createPrMergeCommand(seams = DEFAULT_MERGE_SEAMS) {
@@ -12791,8 +13216,8 @@ function fencedBlock(body, language) {
12791
13216
  return `${fence}${language}
12792
13217
  ${text}${fence}`;
12793
13218
  }
12794
- function counted2(count, noun) {
12795
- return count === 1 ? `1 ${noun}` : `${count} ${noun}s`;
13219
+ function counted2(count2, noun) {
13220
+ return count2 === 1 ? `1 ${noun}` : `${count2} ${noun}s`;
12796
13221
  }
12797
13222
  function excerptCaption(reading) {
12798
13223
  const shown = counted2(reading.lines.length, "line");
@@ -12961,17 +13386,17 @@ function readTriageBlock(body) {
12961
13386
  }
12962
13387
  return readFields(document);
12963
13388
  }
12964
- function quoted(value) {
13389
+ function quoted2(value) {
12965
13390
  return JSON.stringify(value);
12966
13391
  }
12967
13392
  function writeTriageBlock(fields) {
12968
13393
  return [
12969
- `head: ${quoted(fields.head)}`,
12970
- `at: ${quoted(fields.at)}`,
12971
- `class: ${quoted(fields.triageClass)}`,
13394
+ `head: ${quoted2(fields.head)}`,
13395
+ `at: ${quoted2(fields.at)}`,
13396
+ `class: ${quoted2(fields.triageClass)}`,
12972
13397
  `simple: ${String(fields.simple)}`,
12973
13398
  `attempts: ${String(fields.attempts)}`,
12974
- `files: [${fields.files.map((file) => quoted(file)).join(", ")}]`
13399
+ `files: [${fields.files.map((file) => quoted2(file)).join(", ")}]`
12975
13400
  ].join(`
12976
13401
  `);
12977
13402
  }
@@ -13001,10 +13426,10 @@ function noChecksLines(input) {
13001
13426
  return [];
13002
13427
  const number = input.pr.number;
13003
13428
  const unchecked = readUnchecked(number, input.workflowCount ?? null);
13004
- const [count = "", warning = ""] = unchecked.warning;
13429
+ const [count2 = "", warning = ""] = unchecked.warning;
13005
13430
  const yes = unchecked.yesMayAnswer ? "`--yes` may answer it" : "`--yes` is refused, so a person must answer it";
13006
13431
  return [
13007
- `- Workflows: ${count}`,
13432
+ `- Workflows: ${count2}`,
13008
13433
  `- Warning: ${warning}`,
13009
13434
  `- To merge it anyway: \`${skipChecksCommand(number)}\` (it asks first; ${yes})`
13010
13435
  ];
@@ -13088,7 +13513,7 @@ function readLastTriage(comments) {
13088
13513
  }
13089
13514
 
13090
13515
  // src/commands/pr/show.ts
13091
- var USAGE25 = PR_USAGE.show;
13516
+ var USAGE27 = PR_USAGE.show;
13092
13517
  var INDENT5 = " ";
13093
13518
  var SHORT_SHA = 7;
13094
13519
  function headLine4(detail) {
@@ -13186,12 +13611,12 @@ async function probe2(call) {
13186
13611
  }
13187
13612
  }
13188
13613
  async function readShow(context, seams) {
13189
- const asked = readPullArgument(context.args, USAGE25);
13614
+ const asked = readPullArgument(context.args, USAGE27);
13190
13615
  const pr = openPrContext(context, seams);
13191
- const pick = await pickPullRequest(pr, asked, USAGE25);
13616
+ const pick = await pickPullRequest(pr, asked, USAGE27);
13192
13617
  const detail = await onProvider(`read pull request #${pick.number}`, () => pr.pulls.get(pick.number));
13193
13618
  if (detail === null) {
13194
- throw lineRefusal3(`No pull request #${pick.number} in the repository at ${pr.project.root}`, USAGE25);
13619
+ throw lineRefusal3(`No pull request #${pick.number} in the repository at ${pr.project.root}`, USAGE27);
13195
13620
  }
13196
13621
  const checks = await probe2(() => pr.pulls.checks(pick.number));
13197
13622
  const comments = await probe2(() => pr.pulls.comments(pick.number));
@@ -13396,8 +13821,8 @@ function readsAsConflicting(pr, conflictFiles) {
13396
13821
  return true;
13397
13822
  return conflictFiles.length > 0;
13398
13823
  }
13399
- function checkCount(count) {
13400
- return count === 1 ? "1 check" : `${count} checks`;
13824
+ function checkCount(count2) {
13825
+ return count2 === 1 ? "1 check" : `${count2} checks`;
13401
13826
  }
13402
13827
  function fileList(files) {
13403
13828
  const shown = files.slice(0, REASON_FILE_LIMIT).join(", ");
@@ -13408,12 +13833,12 @@ function conflictReason(files) {
13408
13833
  return files.length === 0 ? "the head conflicts with the base and no conflicting file was read" : `the head conflicts with the base on ${fileList(files)}`;
13409
13834
  }
13410
13835
  function failureReason(step, failing) {
13411
- const count = checkCount(failing.length);
13412
- return step === undefined ? `${count} failing, and no failing step was named` : `${count} failing, the failing step being "${step.name}"`;
13836
+ const count2 = checkCount(failing.length);
13837
+ return step === undefined ? `${count2} failing, and no failing step was named` : `${count2} failing, the failing step being "${step.name}"`;
13413
13838
  }
13414
13839
  function noChecksReason(number, workflowCount) {
13415
- const count = workflowCountLine(workflowCount).replace(/\.$/, "");
13416
- return `the head reports no checks at all; ${count.charAt(0).toLowerCase()}${count.slice(1)};` + ` to merge it anyway, run rafa pr merge ${number} --skip-checks`;
13840
+ const count2 = workflowCountLine(workflowCount).replace(/\.$/, "");
13841
+ return `the head reports no checks at all; ${count2.charAt(0).toLowerCase()}${count2.slice(1)};` + ` to merge it anyway, run rafa pr merge ${number} --skip-checks`;
13417
13842
  }
13418
13843
  function decideClass(input, verdict, conflicting) {
13419
13844
  const { conflictFiles, rows, step } = input;
@@ -13495,8 +13920,8 @@ function isSameHead(stored, head) {
13495
13920
  function shortHead(head) {
13496
13921
  return head.trim().slice(0, HEADLINE_HEAD_LENGTH);
13497
13922
  }
13498
- function checkCount2(count) {
13499
- return count === 1 ? "1 check" : `${count} checks`;
13923
+ function checkCount2(count2) {
13924
+ return count2 === 1 ? "1 check" : `${count2} checks`;
13500
13925
  }
13501
13926
  function storedTime(comment, block) {
13502
13927
  if (comment === null)
@@ -13598,8 +14023,8 @@ function isFreshCandidate(updatedAt, now) {
13598
14023
  const age = ageMs(updatedAt, now);
13599
14024
  return age !== null && age <= TRIAGE_FRESH_WINDOW_MS;
13600
14025
  }
13601
- function plural4(count, singular, many) {
13602
- return count === 1 ? `1 ${singular}` : `${count} ${many}`;
14026
+ function plural4(count2, singular, many) {
14027
+ return count2 === 1 ? `1 ${singular}` : `${count2} ${many}`;
13603
14028
  }
13604
14029
  function describeAge(updatedAt, now) {
13605
14030
  const age = ageMs(updatedAt, now);
@@ -13663,17 +14088,17 @@ function listing(decision, assess, rest, headline, exitCode = 0) {
13663
14088
  `)
13664
14089
  });
13665
14090
  }
13666
- function refusal6(rest, count) {
13667
- const headline = `${REFUSAL_PREFIX2}: ${plural4(count, "red pull request", "red pull requests")}, ` + "and --resolve acts on one. Run one of:";
14091
+ function refusal6(rest, count2) {
14092
+ const headline = `${REFUSAL_PREFIX2}: ${plural4(count2, "red pull request", "red pull requests")}, ` + "and --resolve acts on one. Run one of:";
13668
14093
  return listing("refuse", Object.freeze([]), rest, headline, REFUSE_EXIT_CODE);
13669
14094
  }
13670
- function someReading(fresh, stale, count) {
14095
+ function someReading(fresh, stale, count2) {
13671
14096
  const older = stale.length === 0 ? "" : `; ${plural4(stale.length, "older one is", "older ones are")} skipped`;
13672
- const headline = `${count} red: assessing ${joinNumbers(fresh)}${older}`;
14097
+ const headline = `${count2} red: assessing ${joinNumbers(fresh)}${older}`;
13673
14098
  return listing("some", fresh, stale, headline);
13674
14099
  }
13675
- function listReading(rest, count) {
13676
- const headline = count > MAX_TRIAGE_CANDIDATES ? `${count} red, more than the ${MAX_TRIAGE_CANDIDATES} a bare rafa pr triage assesses at once. ` + "Run one of:" : `${count} red, none moved in the last ${TRIAGE_FRESH_HOURS} hours. Run one of:`;
14100
+ function listReading(rest, count2) {
14101
+ const headline = count2 > MAX_TRIAGE_CANDIDATES ? `${count2} red, more than the ${MAX_TRIAGE_CANDIDATES} a bare rafa pr triage assesses at once. ` + "Run one of:" : `${count2} red, none moved in the last ${TRIAGE_FRESH_HOURS} hours. Run one of:`;
13677
14102
  return listing("list", Object.freeze([]), rest, headline);
13678
14103
  }
13679
14104
  function selectTriagePullRequests(input) {
@@ -13683,24 +14108,24 @@ function selectTriagePullRequests(input) {
13683
14108
  return plain("branch", Object.freeze([current]), `assessing #${current.number}, the pull request open on ${current.headRefName}`);
13684
14109
  }
13685
14110
  const candidates = byNumber(input.candidates);
13686
- const count = candidates.length;
14111
+ const count2 = candidates.length;
13687
14112
  const lines2 = candidates.map((pull) => skipped(pull, now, resolve13));
13688
- if (resolve13 && count > 1)
13689
- return refusal6(lines2, count);
13690
- if (count === 0) {
14113
+ if (resolve13 && count2 > 1)
14114
+ return refusal6(lines2, count2);
14115
+ if (count2 === 0) {
13691
14116
  return plain("none", Object.freeze([]), "no red pull request to triage, and no pull request on the current branch");
13692
14117
  }
13693
- if (count === 1) {
14118
+ if (count2 === 1) {
13694
14119
  const only = candidates[0];
13695
14120
  return plain("single", Object.freeze([only]), `1 red: assessing #${only.number}, last moved ${describeAge(only.updatedAt, now)}`);
13696
14121
  }
13697
- if (count > MAX_TRIAGE_CANDIDATES)
13698
- return listReading(lines2, count);
14122
+ if (count2 > MAX_TRIAGE_CANDIDATES)
14123
+ return listReading(lines2, count2);
13699
14124
  const fresh = candidates.filter((pull) => isFreshCandidate(pull.updatedAt, now));
13700
14125
  const stale = lines2.filter((one) => !one.fresh);
13701
14126
  if (fresh.length === 0)
13702
- return listReading(stale, count);
13703
- return someReading(Object.freeze(fresh), stale, count);
14127
+ return listReading(stale, count2);
14128
+ return someReading(Object.freeze(fresh), stale, count2);
13704
14129
  }
13705
14130
 
13706
14131
  // src/pr/triage/conflict.ts
@@ -13719,10 +14144,10 @@ function parseMessages(records, from) {
13719
14144
  const countRecord = records[at];
13720
14145
  if (countRecord === undefined || countRecord === "")
13721
14146
  break;
13722
- const count = Number(countRecord);
13723
- if (!Number.isInteger(count) || count < 0)
14147
+ const count2 = Number(countRecord);
14148
+ if (!Number.isInteger(count2) || count2 < 0)
13724
14149
  break;
13725
- const typeAt = at + 1 + count;
14150
+ const typeAt = at + 1 + count2;
13726
14151
  const messageAt = typeAt + 1;
13727
14152
  const type = records[typeAt];
13728
14153
  const message = records[messageAt];
@@ -13901,10 +14326,10 @@ function noChecksLines2(reading, assessment) {
13901
14326
  return [];
13902
14327
  const number = reading.detail.number;
13903
14328
  const unchecked = readUnchecked(number, workflowCountOf2(reading) ?? null);
13904
- const [count = "", warning = ""] = unchecked.warning;
14329
+ const [count2 = "", warning = ""] = unchecked.warning;
13905
14330
  const yes = unchecked.yesMayAnswer ? "--yes may answer it" : "--yes is refused, so a person must answer it";
13906
14331
  return [
13907
- `${INDENT7}Workflows: ${count}`,
14332
+ `${INDENT7}Workflows: ${count2}`,
13908
14333
  `${INDENT7}Warning: ${warning}`,
13909
14334
  `${INDENT7}To merge it anyway: ${skipChecksCommand(number)} (it asks first; ${yes})`
13910
14335
  ];
@@ -14020,8 +14445,8 @@ function withTaskBudget(plan2, usd) {
14020
14445
  }
14021
14446
 
14022
14447
  // src/pr/plans/load.ts
14023
- import { existsSync as existsSync10, readFileSync as readFileSync22 } from "fs";
14024
- import { dirname as dirname5, join as join27 } from "path";
14448
+ import { existsSync as existsSync11, readFileSync as readFileSync20 } from "fs";
14449
+ import { dirname as dirname5, join as join26 } from "path";
14025
14450
  import { fileURLToPath as fileURLToPath2 } from "url";
14026
14451
  var MODULE_DIR2 = dirname5(fileURLToPath2(import.meta.url));
14027
14452
  var PINNED_PLANS_DIRNAME = "plans";
@@ -14038,8 +14463,8 @@ function hasPinnedPlan(triageClass) {
14038
14463
  function pinnedPlanCandidates(moduleDir, triageClass) {
14039
14464
  const name2 = pinnedPlanFileName(triageClass);
14040
14465
  return [
14041
- join27(moduleDir, PINNED_PLANS_DIRNAME, name2),
14042
- join27(moduleDir, name2)
14466
+ join26(moduleDir, PINNED_PLANS_DIRNAME, name2),
14467
+ join26(moduleDir, name2)
14043
14468
  ];
14044
14469
  }
14045
14470
  function readPinnedPlan(triageClass, lookup = {}) {
@@ -14047,11 +14472,11 @@ function readPinnedPlan(triageClass, lookup = {}) {
14047
14472
  throw new Error(`No pinned resolve plan ships for ${triageClass}; ` + `one ships for ${PINNED_PLAN_CLASSES.join(", ")}`);
14048
14473
  }
14049
14474
  const candidates = pinnedPlanCandidates(lookup.moduleDir ?? MODULE_DIR2, triageClass);
14050
- const found = candidates.find((candidate) => existsSync10(candidate));
14475
+ const found = candidates.find((candidate) => existsSync11(candidate));
14051
14476
  if (found === undefined) {
14052
14477
  throw new Error(`The pinned resolve plan for ${triageClass} is missing: ` + `no file at ${candidates.join(" or ")}`);
14053
14478
  }
14054
- return readFileSync22(found, "utf8");
14479
+ return readFileSync20(found, "utf8");
14055
14480
  }
14056
14481
  var SLOT_PATTERN = /\{[A-Z][A-Z0-9_]*\}/g;
14057
14482
  var CONFLICT_SENTENCE_SLOT = "CONFLICT_SENTENCE";
@@ -14192,19 +14617,19 @@ function readAttemptRepeat(input) {
14192
14617
 
14193
14618
  // src/commands/pr/resolve-loop.ts
14194
14619
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
14195
- import { join as join28 } from "path";
14196
- var RESOLVE_SUBDIR = join28(".rafa", "resolve");
14620
+ import { join as join27 } from "path";
14621
+ var RESOLVE_SUBDIR = join27(".rafa", "resolve");
14197
14622
  var RUN_PREFIX = "pr-";
14198
14623
  var ATTEMPT_PREFIX = "attempt-";
14199
14624
  var LOOP_WORDS = Object.freeze(["loop", "start"]);
14200
14625
  var CHILD_OUTPUT = "text";
14201
14626
  function resolveRunDir(home, number, attempt3) {
14202
- return join28(home, RESOLVE_SUBDIR, `${RUN_PREFIX}${number}`, `${ATTEMPT_PREFIX}${attempt3}`);
14627
+ return join27(home, RESOLVE_SUBDIR, `${RUN_PREFIX}${number}`, `${ATTEMPT_PREFIX}${attempt3}`);
14203
14628
  }
14204
14629
  function writeResolvePlan(write) {
14205
14630
  const dir = resolveRunDir(write.home, write.number, write.attempt);
14206
14631
  mkdirSync7(dir, { recursive: true });
14207
- const path = join28(dir, pinnedPlanFileName(write.triageClass));
14632
+ const path = join27(dir, pinnedPlanFileName(write.triageClass));
14208
14633
  writeFileSync6(path, write.plan, "utf8");
14209
14634
  return path;
14210
14635
  }
@@ -14563,7 +14988,7 @@ async function runAttempts(run, detail, first) {
14563
14988
  }
14564
14989
 
14565
14990
  // src/commands/pr/triage.ts
14566
- var USAGE26 = PR_USAGE.triage;
14991
+ var USAGE28 = PR_USAGE.triage;
14567
14992
  var DEFAULT_MAX_ATTEMPTS = 2;
14568
14993
  var DETACHED_HEAD2 = "HEAD";
14569
14994
  var RESOLVED = false;
@@ -14573,11 +14998,11 @@ function readMaxAttempts(flags, usage2) {
14573
14998
  if (value === undefined)
14574
14999
  return DEFAULT_MAX_ATTEMPTS;
14575
15000
  const spelled = typeof value === "boolean" ? "--max-attempts with no value" : `"${value}"`;
14576
- const count = typeof value === "string" ? Number(value) : Number.NaN;
14577
- if (!Number.isSafeInteger(count) || count < 1) {
15001
+ const count2 = typeof value === "string" ? Number(value) : Number.NaN;
15002
+ if (!Number.isSafeInteger(count2) || count2 < 1) {
14578
15003
  throw lineRefusal3(`${spelled} is no attempt count, which is a whole number from 1;` + " type the pull request number before the flags", usage2);
14579
15004
  }
14580
- return count;
15005
+ return count2;
14581
15006
  }
14582
15007
  function readBranchOrNone(pr, warn) {
14583
15008
  const fallback = "so the red pull requests are the candidates";
@@ -14619,7 +15044,7 @@ async function selectTargets(pr, warn, now, resolve13) {
14619
15044
  async function detailOf6(pr, number) {
14620
15045
  const detail = await onProvider(`read pull request #${number}`, () => pr.pulls.get(number));
14621
15046
  if (detail === null) {
14622
- throw lineRefusal3(`No pull request #${number} in the repository at ${pr.project.root}`, USAGE26);
15047
+ throw lineRefusal3(`No pull request #${number} in the repository at ${pr.project.root}`, USAGE28);
14623
15048
  }
14624
15049
  return detail;
14625
15050
  }
@@ -14714,14 +15139,14 @@ async function assessOne(options) {
14714
15139
  function refuseResolveWithoutComment(wantsResolve, wantsComment) {
14715
15140
  if (!wantsResolve || wantsComment)
14716
15141
  return;
14717
- throw lineRefusal3("--resolve writes the attempt count into the triage comment, and --no-comment writes none;" + " run one or the other", USAGE26);
15142
+ throw lineRefusal3("--resolve writes the attempt count into the triage comment, and --no-comment writes none;" + " run one or the other", USAGE28);
14718
15143
  }
14719
15144
  async function runTriage(context, seams) {
14720
- const wantsComment = readBooleanFlag(context.flags, "comment", USAGE26, true);
14721
- const wantsResolve = readBooleanFlag(context.flags, "resolve", USAGE26, false);
14722
- const maxAttempts = readMaxAttempts(context.flags, USAGE26);
15145
+ const wantsComment = readBooleanFlag(context.flags, "comment", USAGE28, true);
15146
+ const wantsResolve = readBooleanFlag(context.flags, "resolve", USAGE28, false);
15147
+ const maxAttempts = readMaxAttempts(context.flags, USAGE28);
14723
15148
  refuseResolveWithoutComment(wantsResolve, wantsComment);
14724
- const asked = readPullArgument(context.args, USAGE26);
15149
+ const asked = readPullArgument(context.args, USAGE28);
14725
15150
  const pr = openPrContext(context, seams);
14726
15151
  const git = (seams.git ?? createGitRunner)(pr.project.root);
14727
15152
  const permissions = (seams.permissions ?? ghPermissionsIn)(pr.project.root);
@@ -14854,7 +15279,7 @@ function createPrTriageCommand(seams = DEFAULT_TRIAGE_SEAMS) {
14854
15279
  var triage_default = createPrTriageCommand();
14855
15280
 
14856
15281
  // src/commands/pr/view.ts
14857
- var USAGE27 = PR_USAGE.view;
15282
+ var USAGE29 = PR_USAGE.view;
14858
15283
  function trimmedOrNull3(value) {
14859
15284
  const trimmed = value.trim();
14860
15285
  return trimmed === "" ? null : trimmed;
@@ -14864,9 +15289,9 @@ function renderView(number, url) {
14864
15289
  return url === null ? opened : `${opened}${SEPARATOR}${url}`;
14865
15290
  }
14866
15291
  async function runView2(context, seams) {
14867
- const asked = readPullArgument(context.args, USAGE27);
15292
+ const asked = readPullArgument(context.args, USAGE29);
14868
15293
  const pr = openPrContext(context, seams);
14869
- const pick = await pickPullRequest(pr, asked, USAGE27);
15294
+ const pick = await pickPullRequest(pr, asked, USAGE29);
14870
15295
  await onProvider(`open pull request #${pick.number} in the browser`, () => pr.pulls.browse(pick.number));
14871
15296
  const url = trimmedOrNull3(pick.summary?.url ?? "");
14872
15297
  return {
@@ -14921,7 +15346,7 @@ function createPrViewCommand(seams = DEFAULT_PR_SEAMS) {
14921
15346
  var view_default = createPrViewCommand();
14922
15347
 
14923
15348
  // src/commands/pr/wait.ts
14924
- var USAGE28 = PR_USAGE.wait;
15349
+ var USAGE30 = PR_USAGE.wait;
14925
15350
  var TIMEOUT_FLAG = "timeout";
14926
15351
  var DEFAULT_WAIT_TIMEOUT_MIN = DEFAULT_CI_TIMEOUT_MIN;
14927
15352
  var MS_PER_MIN = 60000;
@@ -14987,10 +15412,10 @@ function renderWait(reading) {
14987
15412
  `);
14988
15413
  }
14989
15414
  async function runWait(context, seams) {
14990
- const minutes = readTimeoutMinutes(context.flags, USAGE28);
14991
- const asked = readPullArgument(context.args, USAGE28);
15415
+ const minutes = readTimeoutMinutes(context.flags, USAGE30);
15416
+ const asked = readPullArgument(context.args, USAGE30);
14992
15417
  const pr = openPrContext(context, seams);
14993
- const pick = await pickPullRequest(pr, asked, USAGE28);
15418
+ const pick = await pickPullRequest(pr, asked, USAGE30);
14994
15419
  const timeoutMs = minutes * MS_PER_MIN;
14995
15420
  context.output.info(`Waiting for the checks of #${pick.number}, up to ${minutes} min.`);
14996
15421
  const waited = await waitForChecks({
@@ -15069,8 +15494,8 @@ function createPrWaitCommand(seams = DEFAULT_WAIT_SEAMS) {
15069
15494
  var wait_default = createPrWaitCommand();
15070
15495
 
15071
15496
  // src/commands/release/status.ts
15072
- import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync23 } from "fs";
15073
- import { join as join29 } from "path";
15497
+ import { existsSync as existsSync12, readdirSync as readdirSync6, readFileSync as readFileSync21 } from "fs";
15498
+ import { join as join28 } from "path";
15074
15499
  var RELEASE_STATUS_USAGE = "rafa release status [--plan=<stub>]";
15075
15500
  var UNREADABLE3 = "?";
15076
15501
  var NOTHING = "none";
@@ -15171,13 +15596,13 @@ function untaggedVersions(released, tags) {
15171
15596
  }
15172
15597
  function textOf2(path) {
15173
15598
  try {
15174
- return readFileSync23(path, "utf8");
15599
+ return readFileSync21(path, "utf8");
15175
15600
  } catch {
15176
15601
  return null;
15177
15602
  }
15178
15603
  }
15179
15604
  function readVersionFile(root, configured) {
15180
- const resolved = join29(root, configured);
15605
+ const resolved = join28(root, configured);
15181
15606
  const text = textOf2(resolved);
15182
15607
  if (text === null) {
15183
15608
  return { path: configured, version: null, problem: `the version file could not be read at ${resolved}` };
@@ -15194,7 +15619,7 @@ function readTags(git) {
15194
15619
  return { tags, latest: tags[0] ?? null, problem: null };
15195
15620
  }
15196
15621
  function readUntagged(root, configured, tags) {
15197
- const resolved = join29(root, configured);
15622
+ const resolved = join28(root, configured);
15198
15623
  const text = textOf2(resolved);
15199
15624
  if (text === null) {
15200
15625
  return {
@@ -15213,11 +15638,11 @@ function readBranch2(git) {
15213
15638
  return result.ok && branch !== "" && branch !== "HEAD" ? branch : null;
15214
15639
  }
15215
15640
  function planStubsUnder(root, planDir) {
15216
- const resolved = join29(root, planDir);
15217
- if (!existsSync11(resolved))
15641
+ const resolved = join28(root, planDir);
15642
+ if (!existsSync12(resolved))
15218
15643
  return [];
15219
15644
  try {
15220
- return planStubsFromFileNames(readdirSync7(resolved));
15645
+ return planStubsFromFileNames(readdirSync6(resolved));
15221
15646
  } catch {
15222
15647
  return [];
15223
15648
  }
@@ -15285,10 +15710,10 @@ function levelPhrase(level) {
15285
15710
  function pendingCell(reading) {
15286
15711
  if (reading.stub === null)
15287
15712
  return `${NOTHING}: no current plan`;
15288
- const count = reading.notes.length === 1 ? "1 note" : `${reading.notes.length} notes`;
15713
+ const count2 = reading.notes.length === 1 ? "1 note" : `${reading.notes.length} notes`;
15289
15714
  if (reading.notes.length === 0)
15290
15715
  return `${NOTHING} for ${reading.stub}`;
15291
- return `${count} for ${reading.stub}, ${levelPhrase(reading.level ?? "none")}`;
15716
+ return `${count2} for ${reading.stub}, ${levelPhrase(reading.level ?? "none")}`;
15292
15717
  }
15293
15718
  function pendingLines(reading) {
15294
15719
  return renderNoteLines(groupChangeNotes(reading.notes));
@@ -15415,8 +15840,8 @@ function createReleaseStatusCommand(seams = DEFAULT_RELEASE_SEAMS) {
15415
15840
  var status_default2 = createReleaseStatusCommand();
15416
15841
 
15417
15842
  // src/commands/release/tag.ts
15418
- import { readFileSync as readFileSync24 } from "fs";
15419
- import { join as join30 } from "path";
15843
+ import { readFileSync as readFileSync22 } from "fs";
15844
+ import { join as join29 } from "path";
15420
15845
  var RELEASE_TAG_USAGE = "rafa release tag";
15421
15846
  var DEFAULT_RELEASE_BRANCH = "main";
15422
15847
  var DEFAULT_REGISTRY = "https://registry.npmjs.org";
@@ -15435,13 +15860,13 @@ function readBranch3(git) {
15435
15860
  }
15436
15861
  function textOf3(path) {
15437
15862
  try {
15438
- return readFileSync24(path, "utf8");
15863
+ return readFileSync22(path, "utf8");
15439
15864
  } catch {
15440
15865
  return null;
15441
15866
  }
15442
15867
  }
15443
15868
  function readVersion(root, configured) {
15444
- const resolved = join30(root, configured);
15869
+ const resolved = join29(root, configured);
15445
15870
  const text = textOf3(resolved);
15446
15871
  if (text === null) {
15447
15872
  return {
@@ -15455,7 +15880,7 @@ function readVersion(root, configured) {
15455
15880
  return version2 === null ? { path: configured, text, version: null, problem: `${resolved} declares no version this can read` } : { path: configured, text, version: version2, problem: null };
15456
15881
  }
15457
15882
  function readNewestRelease(root, configured) {
15458
- const resolved = join30(root, configured);
15883
+ const resolved = join29(root, configured);
15459
15884
  const text = textOf3(resolved);
15460
15885
  if (text === null) {
15461
15886
  return { path: configured, version: null, problem: `the changelog could not be read at ${resolved}` };
@@ -15676,14 +16101,14 @@ var roadmap_default = createRoadmapCommand();
15676
16101
 
15677
16102
  // src/commands/self-update.ts
15678
16103
  var DEFAULT_SELF_UPDATE_SEAMS = Object.freeze({ build: runBuild });
15679
- var USAGE29 = "rafa self-update [--force]";
16104
+ var USAGE31 = "rafa self-update [--force]";
15680
16105
  function readForceFlag(value) {
15681
16106
  if (value === undefined || value === false || value === "false")
15682
16107
  return false;
15683
16108
  if (value === true || value === "true")
15684
16109
  return true;
15685
16110
  throw new CommandExit(1, `\u274C --force takes no value, and read "${value}" as one
15686
- Usage: ${USAGE29}`);
16111
+ Usage: ${USAGE31}`);
15687
16112
  }
15688
16113
  function projectOf11(context) {
15689
16114
  if (context.project === null)
@@ -15691,7 +16116,7 @@ function projectOf11(context) {
15691
16116
  return context.project;
15692
16117
  }
15693
16118
  async function runSelfUpdate(context, seams) {
15694
- expectNoArgument(context.args, USAGE29);
16119
+ expectNoArgument(context.args, USAGE31);
15695
16120
  const force = readForceFlag(context.flags["force"]);
15696
16121
  const project = projectOf11(context);
15697
16122
  const info = (line) => context.output.info(line);
@@ -15749,17 +16174,17 @@ function createSelfUpdateCommand(seams = DEFAULT_SELF_UPDATE_SEAMS) {
15749
16174
  var self_update_default = createSelfUpdateCommand();
15750
16175
 
15751
16176
  // src/commands/skill/backfill.ts
15752
- import { statSync as statSync15 } from "fs";
15753
- import { join as join35, resolve as resolve15 } from "path";
16177
+ import { statSync as statSync14 } from "fs";
16178
+ import { join as join34, resolve as resolve15 } from "path";
15754
16179
 
15755
16180
  // src/backfill/backup.ts
15756
- import { copyFileSync as copyFileSync4, existsSync as existsSync12, mkdirSync as mkdirSync8 } from "fs";
15757
- import { dirname as dirname6, isAbsolute as isAbsolute8, join as join32, relative as relative8, resolve as resolve13, sep as sep5 } from "path";
16181
+ import { copyFileSync as copyFileSync4, existsSync as existsSync13, mkdirSync as mkdirSync8 } from "fs";
16182
+ import { dirname as dirname6, isAbsolute as isAbsolute8, join as join31, relative as relative8, resolve as resolve13, sep as sep5 } from "path";
15758
16183
 
15759
16184
  // src/backfill/proposal-file.ts
15760
- import { readdirSync as readdirSync8, readFileSync as readFileSync25 } from "fs";
15761
- import { join as join31 } from "path";
15762
- var BACKFILL_PATH = join31(".rafa", "backfill");
16185
+ import { readdirSync as readdirSync7, readFileSync as readFileSync23 } from "fs";
16186
+ import { join as join30 } from "path";
16187
+ var BACKFILL_PATH = join30(".rafa", "backfill");
15763
16188
  var PROPOSAL_FILE_PREFIX = "proposals-";
15764
16189
  var PROPOSAL_FILE_EXTENSION = ".yaml";
15765
16190
  var SHA256_PATTERN = /^[0-9a-f]{64}$/;
@@ -15785,7 +16210,7 @@ var PROPOSAL_FILE_HEADER = [
15785
16210
  ].join(`
15786
16211
  `);
15787
16212
  function proposalPath(dir, batch) {
15788
- return join31(dir, `${PROPOSAL_FILE_PREFIX}${String(batch).padStart(2, "0")}${PROPOSAL_FILE_EXTENSION}`);
16213
+ return join30(dir, `${PROPOSAL_FILE_PREFIX}${String(batch).padStart(2, "0")}${PROPOSAL_FILE_EXTENSION}`);
15789
16214
  }
15790
16215
  function isProposalFileName(name2) {
15791
16216
  return name2.startsWith(PROPOSAL_FILE_PREFIX) && name2.endsWith(PROPOSAL_FILE_EXTENSION);
@@ -15916,14 +16341,14 @@ function parseProposalFile(text) {
15916
16341
  function readProposalFiles(dir) {
15917
16342
  let names;
15918
16343
  try {
15919
- names = readdirSync8(dir);
16344
+ names = readdirSync7(dir);
15920
16345
  } catch {
15921
16346
  return [];
15922
16347
  }
15923
16348
  return names.filter((name2) => isProposalFileName(name2)).sort((left, right) => left.localeCompare(right)).map((name2) => {
15924
- const path = join31(dir, name2);
16349
+ const path = join30(dir, name2);
15925
16350
  try {
15926
- return { path, result: parseProposalFile(readFileSync25(path, "utf8")) };
16351
+ return { path, result: parseProposalFile(readFileSync23(path, "utf8")) };
15927
16352
  } catch (error) {
15928
16353
  return { path, result: unreadable(`the file cannot be read (${error instanceof Error ? error.message : String(error)})`) };
15929
16354
  }
@@ -15931,10 +16356,10 @@ function readProposalFiles(dir) {
15931
16356
  }
15932
16357
 
15933
16358
  // src/backfill/backup.ts
15934
- var BACKUP_PATH = join32(BACKFILL_PATH, "backup");
16359
+ var BACKUP_PATH = join31(BACKFILL_PATH, "backup");
15935
16360
  var BACKUP_KINDS = ["copied", "kept", "tracked", "outside", "missing"];
15936
16361
  function backupDirectory(base) {
15937
- return join32(base, BACKUP_PATH);
16362
+ return join31(base, BACKUP_PATH);
15938
16363
  }
15939
16364
  function isUnder(root, path) {
15940
16365
  const step = relative8(resolve13(root), resolve13(path));
@@ -15943,7 +16368,7 @@ function isUnder(root, path) {
15943
16368
  function backupPathFor(path, root, backupDir) {
15944
16369
  if (!isUnder(root, path))
15945
16370
  return null;
15946
- return join32(backupDir, relative8(resolve13(root), resolve13(path)));
16371
+ return join31(backupDir, relative8(resolve13(root), resolve13(path)));
15947
16372
  }
15948
16373
  function backupFile(path, options) {
15949
16374
  if (options.repoRoot !== null && isUnder(options.repoRoot, path)) {
@@ -15952,9 +16377,9 @@ function backupFile(path, options) {
15952
16377
  const backup = backupPathFor(path, options.root, options.backupDir);
15953
16378
  if (backup === null)
15954
16379
  return { path, kind: "outside", backup: null };
15955
- if (!existsSync12(path))
16380
+ if (!existsSync13(path))
15956
16381
  return { path, kind: "missing", backup: null };
15957
- if (existsSync12(backup))
16382
+ if (existsSync13(backup))
15958
16383
  return { path, kind: "kept", backup };
15959
16384
  mkdirSync8(dirname6(backup), { recursive: true });
15960
16385
  copyFileSync4(path, backup);
@@ -15979,348 +16404,8 @@ function countBackups(results) {
15979
16404
  }
15980
16405
 
15981
16406
  // src/backfill/derive.ts
15982
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync7 } from "fs";
16407
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync7 } from "fs";
15983
16408
  import { basename as basename8 } from "path";
15984
-
15985
- // src/demote/classify.ts
15986
- var LEARNED_DIRECTORY = "learned";
15987
- var ORIGIN_FIELD = "origin";
15988
- var DEMOTION_VERDICTS = [
15989
- "observation",
15990
- "procedure",
15991
- "unclassified"
15992
- ];
15993
- var RULE_VERDICTS = Object.freeze({
15994
- "no-frontmatter": "unclassified",
15995
- "learned-without-origin": "unclassified",
15996
- "no-section-pair": "unclassified",
15997
- "repeated-section": "procedure",
15998
- "numbered-procedure": "procedure",
15999
- "referenced-script": "procedure",
16000
- "observation-shape": "observation"
16001
- });
16002
- var PROCEDURE_STEP_MINIMUM = 3;
16003
- var PROBLEM_HEADING = /^(?:the\s+)?problem\b/i;
16004
- var SOLUTION_HEADING = /^(?:the\s+)?solution\b/i;
16005
- var WHEN_TO_USE_HEADING = /^when\s+to\s+use\b/i;
16006
- var EXTRACTED_LINE = /^\s*\*\*Extracted:\*\*\s*(\S+)/m;
16007
- var SCRIPT_EXTENSIONS = [
16008
- ".sh",
16009
- ".bash",
16010
- ".zsh",
16011
- ".py",
16012
- ".rb",
16013
- ".pl",
16014
- ".js",
16015
- ".mjs",
16016
- ".cjs",
16017
- ".ts"
16018
- ];
16019
- var FENCE_LINE = /^ {0,3}(?:```|~~~)/;
16020
- var HEADING_LINE = /^ {0,3}(#{1,6})\s+(.*)$/;
16021
- var NUMBERED_ITEM = /^ {0,3}\d+[.)]\s+\S/;
16022
- var CONTINUATION = /^ {2,}\S/;
16023
- var DEMOTED_SOURCE = "demoted";
16024
- var DEMOTED_CONFIDENCE = 0.5;
16025
- var DEMOTED_KIND = "gotcha";
16026
- var DEMOTED_SIGNAL = "silent";
16027
- var DEMOTED_USAGE_COUNT = 1;
16028
- var EVIDENCE_PATH_KEY = "path";
16029
- var EVIDENCE_EXTRACTED_KEY = "extracted";
16030
- var DEFAULT_DOMAIN = "general-best-practices";
16031
- var DOMAIN_MARKERS = [
16032
- ["security", /\b(?:security|secret|credential|token|auth|csrf|xss|injection)\b/i],
16033
- ["testing", /\b(?:test|tests|testing|spec|assertion|assert|mock|stub|fixture|coverage)\b/i],
16034
- ["git", /\b(?:git|commit|rebase|worktree|branch|merge|checkout)\b/i],
16035
- ["debugging", /\b(?:debug|debugging|traceback|reproduce|bisect)\b/i],
16036
- ["code-style", /\b(?:lint|eslint|format|formatter|prettier|naming)\b/i],
16037
- ["workflow", /\b(?:workflow|pipeline|release|deploy|build|ci|loop|dispatch)\b/i]
16038
- ];
16039
- var ERROR_WORDS = /\b(?:error|exception|traceback|panic|fatal|refused|denied|not found|no such|cannot|could not|failed|failure|unexpected|undefined)\b/i;
16040
- var SENTENCE_ABBREVIATIONS = ["e.g", "i.e", "vs", "cf", "etc"];
16041
- function isFilled(value) {
16042
- return typeof value === "string" && value.trim() !== "";
16043
- }
16044
- function bodyLines2(body) {
16045
- return body.split(`
16046
- `).map((line) => line.replace(/\r$/, ""));
16047
- }
16048
- function bodySections(body) {
16049
- const lines2 = bodyLines2(body);
16050
- const headings = [];
16051
- let fenced = false;
16052
- lines2.forEach((line, index) => {
16053
- if (FENCE_LINE.test(line)) {
16054
- fenced = !fenced;
16055
- return;
16056
- }
16057
- if (fenced)
16058
- return;
16059
- const match = HEADING_LINE.exec(line);
16060
- if (match === null)
16061
- return;
16062
- const [, hashes = "", title = ""] = match;
16063
- headings.push({
16064
- level: hashes.length,
16065
- title: title.replace(/\s+#+\s*$/, "").trim(),
16066
- index
16067
- });
16068
- });
16069
- return headings.map((heading, position) => {
16070
- const next = headings.slice(position + 1).find((other) => other.level <= heading.level);
16071
- const end = next === undefined ? lines2.length : next.index;
16072
- return {
16073
- level: heading.level,
16074
- title: heading.title,
16075
- line: heading.index + 1,
16076
- text: lines2.slice(heading.index + 1, end).join(`
16077
- `).trim()
16078
- };
16079
- });
16080
- }
16081
- function numberedRuns(body) {
16082
- const runs = [];
16083
- let fenced = false;
16084
- let steps = 0;
16085
- let line = 0;
16086
- const close = () => {
16087
- if (steps > 0)
16088
- runs.push({ steps, line });
16089
- steps = 0;
16090
- };
16091
- bodyLines2(body).forEach((text, index) => {
16092
- if (FENCE_LINE.test(text)) {
16093
- fenced = !fenced;
16094
- return;
16095
- }
16096
- if (fenced || text.trim() === "")
16097
- return;
16098
- if (NUMBERED_ITEM.test(text)) {
16099
- if (steps === 0)
16100
- line = index + 1;
16101
- steps += 1;
16102
- return;
16103
- }
16104
- if (CONTINUATION.test(text))
16105
- return;
16106
- close();
16107
- });
16108
- close();
16109
- return runs;
16110
- }
16111
- function isScriptPath(token) {
16112
- if (token.startsWith("/"))
16113
- return false;
16114
- const last = token.split("/").at(-1) ?? "";
16115
- return SCRIPT_EXTENSIONS.some((extension) => last.endsWith(extension));
16116
- }
16117
- function referencedScript(body, entries = []) {
16118
- const owned = new Set(entries.map((entry) => entry.replace(/^\.\//, "")));
16119
- for (const reference of collectReferences(body)) {
16120
- if (reference.kind !== "path")
16121
- continue;
16122
- const token = reference.text.replace(/^\.\//, "");
16123
- const [first = ""] = token.split("/");
16124
- if (owned.has(first) && isScriptPath(token))
16125
- return reference;
16126
- }
16127
- return null;
16128
- }
16129
- function isLearnedFile(path) {
16130
- const [first] = path.split(/[\\/]/);
16131
- return first === LEARNED_DIRECTORY;
16132
- }
16133
- function decide2(rule, reason) {
16134
- return { verdict: RULE_VERDICTS[rule], rule, reason };
16135
- }
16136
- function pairReason(problems, solutions) {
16137
- if (problems === 0 && solutions === 0) {
16138
- return "the body carries no Problem section and no Solution section";
16139
- }
16140
- return problems === 0 ? "the body carries a Solution section and no Problem section, so there is no pair" : "the body carries a Problem section and no Solution section, so there is no pair";
16141
- }
16142
- function repeatReason(problems, solutions) {
16143
- const counted3 = problems > 1 ? `${problems} Problem sections` : `${solutions} Solution sections`;
16144
- return `the body carries ${counted3}, and an observation carries exactly one of each`;
16145
- }
16146
- function classifySkill(source) {
16147
- const document = readFrontmatterDocument(source.text);
16148
- if (document === null) {
16149
- return decide2("no-frontmatter", "the file opens with no --- block holding a YAML mapping");
16150
- }
16151
- if (isLearnedFile(source.path) && !isFilled(document.data[ORIGIN_FIELD])) {
16152
- return decide2("learned-without-origin", `a ${LEARNED_DIRECTORY}/ file whose frontmatter carries no ${ORIGIN_FIELD}`);
16153
- }
16154
- const sections = bodySections(document.body);
16155
- const problems = sections.filter((section) => PROBLEM_HEADING.test(section.title));
16156
- const solutions = sections.filter((section) => SOLUTION_HEADING.test(section.title));
16157
- if (problems.length === 0 || solutions.length === 0) {
16158
- return decide2("no-section-pair", pairReason(problems.length, solutions.length));
16159
- }
16160
- if (problems.length > 1 || solutions.length > 1) {
16161
- return decide2("repeated-section", repeatReason(problems.length, solutions.length));
16162
- }
16163
- const run = numberedRuns(document.body).find((each) => each.steps >= PROCEDURE_STEP_MINIMUM);
16164
- if (run !== undefined) {
16165
- return decide2("numbered-procedure", `a numbered procedure of ${run.steps} consecutive steps at line ${run.line}`);
16166
- }
16167
- const script = referencedScript(document.body, source.entries ?? []);
16168
- if (script !== null) {
16169
- return decide2("referenced-script", `the body names the script ${script.text} at line ${script.line}`);
16170
- }
16171
- return decide2("observation-shape", "one Problem section and one Solution section, no numbered procedure of " + `${PROCEDURE_STEP_MINIMUM} or more consecutive steps, and no referenced script`);
16172
- }
16173
- function firstSection(sections, heading) {
16174
- return sections.find((section) => heading.test(section.title));
16175
- }
16176
- function withoutFences(text) {
16177
- const kept = [];
16178
- let fenced = false;
16179
- for (const line of bodyLines2(text)) {
16180
- if (FENCE_LINE.test(line)) {
16181
- fenced = !fenced;
16182
- continue;
16183
- }
16184
- if (!fenced)
16185
- kept.push(line);
16186
- }
16187
- return kept;
16188
- }
16189
- function stripMarkers(line) {
16190
- return line.replace(/^\s*(?:[-*+]|\d+[.)]|>)\s+/, "").replace(/\*\*|__|\*|`/g, "").trim();
16191
- }
16192
- function isAbbreviation(text, index) {
16193
- const before = text.slice(0, index);
16194
- return SENTENCE_ABBREVIATIONS.some((word) => before.toLowerCase().endsWith(word));
16195
- }
16196
- function firstSentence(text) {
16197
- const lines2 = withoutFences(text);
16198
- const start2 = lines2.findIndex((line) => line.trim() !== "");
16199
- if (start2 === -1)
16200
- return "";
16201
- const collected = [lines2[start2] ?? ""];
16202
- for (const line of lines2.slice(start2 + 1)) {
16203
- if (line.trim() === "" || /^\s*(?:[-*+]|\d+[.)]|#)/.test(line))
16204
- break;
16205
- collected.push(line);
16206
- }
16207
- const joined2 = stripMarkers(collected.join(" ")).replace(/\s+/g, " ");
16208
- for (let index = 0;index < joined2.length; index += 1) {
16209
- if (!".!?".includes(joined2[index] ?? ""))
16210
- continue;
16211
- if (isAbbreviation(joined2, index))
16212
- continue;
16213
- const next = joined2[index + 1];
16214
- if (next === undefined)
16215
- return joined2.slice(0, index + 1).trim();
16216
- if (next === " ")
16217
- return joined2.slice(0, index + 1).trim();
16218
- }
16219
- return joined2.trim();
16220
- }
16221
- function demotedTrigger(sections, data) {
16222
- const whenToUse = firstSection(sections, WHEN_TO_USE_HEADING);
16223
- const fromSection = whenToUse === undefined ? "" : firstSentence(whenToUse.text);
16224
- if (fromSection !== "")
16225
- return fromSection;
16226
- const description = data["description"];
16227
- if (isFilled(description))
16228
- return description.trim();
16229
- const problem2 = firstSection(sections, PROBLEM_HEADING);
16230
- return problem2 === undefined ? "" : firstSentence(problem2.text);
16231
- }
16232
- function extractedDate(body) {
16233
- const match = EXTRACTED_LINE.exec(body);
16234
- return match?.[1] ?? null;
16235
- }
16236
- function errorString(body) {
16237
- let fenced = false;
16238
- for (const line of bodyLines2(body)) {
16239
- if (FENCE_LINE.test(line)) {
16240
- fenced = !fenced;
16241
- continue;
16242
- }
16243
- if (fenced) {
16244
- if (ERROR_WORDS.test(line))
16245
- return line.trim();
16246
- continue;
16247
- }
16248
- for (const span of line.matchAll(/`([^`\n]+)`/g)) {
16249
- const inner = span[1] ?? "";
16250
- if (ERROR_WORDS.test(inner))
16251
- return inner.trim();
16252
- }
16253
- }
16254
- return null;
16255
- }
16256
- function inferDomain(name2, body) {
16257
- for (const [domain, pattern] of DOMAIN_MARKERS) {
16258
- if (pattern.test(name2))
16259
- return domain;
16260
- }
16261
- for (const [domain, pattern] of DOMAIN_MARKERS) {
16262
- if (pattern.test(body))
16263
- return domain;
16264
- }
16265
- return DEFAULT_DOMAIN;
16266
- }
16267
- function slugifyId(value) {
16268
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
16269
- }
16270
- function uniqueInstinctId(base, taken) {
16271
- const used = new Set(taken);
16272
- if (!used.has(base))
16273
- return base;
16274
- let suffix = 2;
16275
- while (used.has(`${base}-${suffix}`))
16276
- suffix += 1;
16277
- return `${base}-${suffix}`;
16278
- }
16279
- function sourceName(source, data) {
16280
- const declared = data["name"];
16281
- if (isFilled(declared))
16282
- return slugifyId(declared);
16283
- const segments = source.path.split(/[\\/]/).filter((segment) => segment !== "");
16284
- const last = segments.at(-1) ?? "";
16285
- const stem = last.toUpperCase() === "SKILL.MD" ? segments.at(-2) ?? "" : last.replace(/\.md$/i, "");
16286
- return slugifyId(stem);
16287
- }
16288
- function convertToInstinct(source, options) {
16289
- const document = readFrontmatterDocument(source.text);
16290
- const data = document?.data ?? {};
16291
- const body = document?.body ?? source.text;
16292
- const sections = bodySections(body);
16293
- const action = firstSection(sections, SOLUTION_HEADING)?.text ?? "";
16294
- const named3 = errorString(body);
16295
- const name2 = sourceName(source, data);
16296
- const draft = {
16297
- id: uniqueInstinctId(name2, options.takenIds ?? []),
16298
- trigger: demotedTrigger(sections, data),
16299
- kind: DEMOTED_KIND,
16300
- domain: inferDomain(name2, body),
16301
- confidence: DEMOTED_CONFIDENCE,
16302
- usageCount: DEMOTED_USAGE_COUNT,
16303
- artifact: null,
16304
- signal: named3 === null ? DEMOTED_SIGNAL : "loud",
16305
- scope: options.scope,
16306
- projectId: options.projectId ?? null,
16307
- source: DEMOTED_SOURCE,
16308
- evidence: [{
16309
- [EVIDENCE_PATH_KEY]: source.path,
16310
- [EVIDENCE_EXTRACTED_KEY]: extractedDate(body) ?? options.mtime
16311
- }],
16312
- createdAt: options.now,
16313
- updatedAt: options.now,
16314
- action,
16315
- cause: firstSection(sections, PROBLEM_HEADING)?.text ?? "",
16316
- actionHash: actionHash(action)
16317
- };
16318
- const text = writeInstinct(draft);
16319
- const parsed = parseInstinct(text);
16320
- return parsed.instinct === null ? { instinct: null, text: null, issues: parsed.issues } : { instinct: parsed.instinct, text, issues: parsed.issues };
16321
- }
16322
-
16323
- // src/backfill/derive.ts
16324
16409
  var DERIVED_FIELDS = ["stack", "paths", "when_to_use"];
16325
16410
  function renderWhenToUse(trigger, prevents) {
16326
16411
  return `${sentenceEnded(trigger)} Prevents: ${prevents}`;
@@ -16445,7 +16530,7 @@ function planFile(entry, options) {
16445
16530
  }
16446
16531
  let original;
16447
16532
  try {
16448
- original = readFileSync26(entry.path, "utf8");
16533
+ original = readFileSync24(entry.path, "utf8");
16449
16534
  } catch (error) {
16450
16535
  return inert(entry, "skipped", `the file cannot be read (${error instanceof Error ? error.message : String(error)})`);
16451
16536
  }
@@ -16489,7 +16574,7 @@ function planDerivation(root, options) {
16489
16574
  function applyFile(action, options) {
16490
16575
  if (action.text === null || action.original === null)
16491
16576
  return action;
16492
- const current = readFileSync26(action.path, "utf8");
16577
+ const current = readFileSync24(action.path, "utf8");
16493
16578
  if (current !== action.original) {
16494
16579
  return {
16495
16580
  ...action,
@@ -16520,7 +16605,7 @@ function applyDerivation(plan2, options) {
16520
16605
  }
16521
16606
 
16522
16607
  // src/backfill/proposal-batch.ts
16523
- import { readFileSync as readFileSync27 } from "fs";
16608
+ import { readFileSync as readFileSync25 } from "fs";
16524
16609
  import { relative as relative9 } from "path";
16525
16610
 
16526
16611
  // src/demote/report.ts
@@ -16819,7 +16904,7 @@ function readCandidate(root, entry) {
16819
16904
  return null;
16820
16905
  let text;
16821
16906
  try {
16822
- text = readFileSync27(entry.path, "utf8");
16907
+ text = readFileSync25(entry.path, "utf8");
16823
16908
  } catch {
16824
16909
  return null;
16825
16910
  }
@@ -16925,8 +17010,8 @@ function parseSessionAnswer(stdout) {
16925
17010
  }
16926
17011
 
16927
17012
  // src/backfill/propose.ts
16928
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync28, writeFileSync as writeFileSync8 } from "fs";
16929
- import { join as join33, resolve as resolve14 } from "path";
17013
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync26, writeFileSync as writeFileSync8 } from "fs";
17014
+ import { join as join32, resolve as resolve14 } from "path";
16930
17015
  var PROPOSAL_ACTION_KINDS = [
16931
17016
  "applied",
16932
17017
  "unchanged",
@@ -16947,47 +17032,47 @@ function unanswered(candidate, note) {
16947
17032
  note
16948
17033
  };
16949
17034
  }
16950
- function answerProblem(needs, answer) {
17035
+ function answerProblem(needs, answer2) {
16951
17036
  if (needs.includes("prevents")) {
16952
- if (answer.prevents === null)
17037
+ if (answer2.prevents === null)
16953
17038
  return "the answer carries no prevents";
16954
- if (answer.signal === null)
17039
+ if (answer2.signal === null)
16955
17040
  return "the answer carries prevents with no signal";
16956
- if (!isSkillSignal(answer.signal)) {
16957
- return `the answer signal ${answer.signal} is neither ${SKILL_SIGNALS.join(" nor ")}`;
17041
+ if (!isSkillSignal(answer2.signal)) {
17042
+ return `the answer signal ${answer2.signal} is neither ${SKILL_SIGNALS.join(" nor ")}`;
16958
17043
  }
16959
17044
  }
16960
- if (needs.includes("trigger") && answer.trigger === null) {
17045
+ if (needs.includes("trigger") && answer2.trigger === null) {
16961
17046
  return "the answer carries no trigger sentence";
16962
17047
  }
16963
17048
  if (needs.includes("description")) {
16964
- if (answer.description === null)
17049
+ if (answer2.description === null)
16965
17050
  return "the answer carries no description";
16966
- if (countCharacters(answer.description) >= DESCRIPTION_LIMIT) {
16967
- return `the answer description is ${countCharacters(answer.description)} characters, at or over the ${DESCRIPTION_LIMIT} cap`;
17051
+ if (countCharacters(answer2.description) >= DESCRIPTION_LIMIT) {
17052
+ return `the answer description is ${countCharacters(answer2.description)} characters, at or over the ${DESCRIPTION_LIMIT} cap`;
16968
17053
  }
16969
17054
  }
16970
17055
  return null;
16971
17056
  }
16972
- function proposalRow(candidate, answer) {
16973
- if (answer === undefined) {
17057
+ function proposalRow(candidate, answer2) {
17058
+ if (answer2 === undefined) {
16974
17059
  return unanswered(candidate, "the session answered nothing about this file");
16975
17060
  }
16976
- const problem2 = answerProblem(candidate.needs, answer);
17061
+ const problem2 = answerProblem(candidate.needs, answer2);
16977
17062
  if (problem2 !== null)
16978
17063
  return unanswered(candidate, problem2);
16979
17064
  const wants = (need) => candidate.needs.includes(need);
16980
- const signal = answer.signal;
17065
+ const signal = answer2.signal;
16981
17066
  return {
16982
17067
  path: candidate.relative,
16983
17068
  name: candidate.name,
16984
17069
  hash: candidate.hash,
16985
17070
  needs: candidate.needs,
16986
17071
  status: ANSWERED_ROW,
16987
- prevents: wants("prevents") ? answer.prevents : null,
17072
+ prevents: wants("prevents") ? answer2.prevents : null,
16988
17073
  signal: wants("prevents") && signal !== null && isSkillSignal(signal) ? signal : null,
16989
- trigger: wants("trigger") ? answer.trigger : null,
16990
- description: wants("description") ? answer.description : null,
17074
+ trigger: wants("trigger") ? answer2.trigger : null,
17075
+ description: wants("description") ? answer2.description : null,
16991
17076
  note: null
16992
17077
  };
16993
17078
  }
@@ -17075,7 +17160,7 @@ function writeRow(path, row2, original, options) {
17075
17160
  };
17076
17161
  }
17077
17162
  function applyRow(root, row2, options) {
17078
- const path = join33(root, ...row2.path.split("/"));
17163
+ const path = join32(root, ...row2.path.split("/"));
17079
17164
  if (row2.status === UNANSWERED_ROW) {
17080
17165
  return inert2(path, row2, "unanswered", row2.note ?? "the row carries no answer");
17081
17166
  }
@@ -17084,7 +17169,7 @@ function applyRow(root, row2, options) {
17084
17169
  }
17085
17170
  let original;
17086
17171
  try {
17087
- original = readFileSync28(path, "utf8");
17172
+ original = readFileSync26(path, "utf8");
17088
17173
  } catch {
17089
17174
  return inert2(path, row2, "refused", "the file the row names is gone");
17090
17175
  }
@@ -17112,7 +17197,7 @@ function applyProposals(files, root, options) {
17112
17197
  for (const file of files) {
17113
17198
  const refusal7 = fileRefusal(file, root);
17114
17199
  for (const row2 of file.rows) {
17115
- const action = refusal7 === null ? applyRow(root, row2, options) : inert2(join33(root, ...row2.path.split("/")), row2, "refused", refusal7);
17200
+ const action = refusal7 === null ? applyRow(root, row2, options) : inert2(join32(root, ...row2.path.split("/")), row2, "refused", refusal7);
17116
17201
  actions.push(action);
17117
17202
  if (row2.trigger !== null && action.kind !== "refused" && action.kind !== "unanswered") {
17118
17203
  triggers[row2.name] = row2.trigger;
@@ -17123,13 +17208,13 @@ function applyProposals(files, root, options) {
17123
17208
  }
17124
17209
 
17125
17210
  // src/demote/select.ts
17126
- import { readdirSync as readdirSync9, readFileSync as readFileSync29, realpathSync as realpathSync6, statSync as statSync14 } from "fs";
17127
- import { basename as basename9, dirname as dirname7, join as join34 } from "path";
17211
+ import { readdirSync as readdirSync8, readFileSync as readFileSync27, realpathSync as realpathSync6, statSync as statSync13 } from "fs";
17212
+ import { basename as basename9, dirname as dirname7, join as join33 } from "path";
17128
17213
  var SKILLS_DIRECTORY = "skills";
17129
17214
  var CLAUDE_DIRECTORY = ".claude";
17130
17215
  var AUTO_EXTRACTED_ORIGIN = "auto-extracted";
17131
- var DEMOTED_PATH = join34(".rafa", "demoted");
17132
- var INSTINCTS_PATH = join34(".rafa", "instincts");
17216
+ var DEMOTED_PATH = join33(".rafa", "demoted");
17217
+ var INSTINCTS_PATH = join33(".rafa", "instincts");
17133
17218
  var REPORT_FILE = "report.md";
17134
17219
  function realOrSelf(path) {
17135
17220
  try {
@@ -17152,19 +17237,19 @@ function resolveDemotionScope(dir, home) {
17152
17237
  if (basename9(claude) !== CLAUDE_DIRECTORY)
17153
17238
  return null;
17154
17239
  const base = dirname7(claude);
17155
- const demotedDir = join34(base, DEMOTED_PATH);
17240
+ const demotedDir = join33(base, DEMOTED_PATH);
17156
17241
  return {
17157
17242
  scope: samePath(base, home) ? "user" : "project",
17158
17243
  dir,
17159
17244
  base,
17160
17245
  demotedDir,
17161
- instinctsDir: join34(base, INSTINCTS_PATH),
17162
- reportPath: join34(demotedDir, REPORT_FILE)
17246
+ instinctsDir: join33(base, INSTINCTS_PATH),
17247
+ reportPath: join33(demotedDir, REPORT_FILE)
17163
17248
  };
17164
17249
  }
17165
17250
  function entryKind(path) {
17166
17251
  try {
17167
- const stats = statSync14(path);
17252
+ const stats = statSync13(path);
17168
17253
  if (stats.isFile())
17169
17254
  return "file";
17170
17255
  if (stats.isDirectory())
@@ -17176,7 +17261,7 @@ function entryKind(path) {
17176
17261
  }
17177
17262
  function visibleNames(dir) {
17178
17263
  try {
17179
- return readdirSync9(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
17264
+ return readdirSync8(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
17180
17265
  } catch {
17181
17266
  return [];
17182
17267
  }
@@ -17185,8 +17270,8 @@ function readSelected(absolute, path, entries) {
17185
17270
  let text;
17186
17271
  let mtime;
17187
17272
  try {
17188
- text = readFileSync29(absolute, "utf8");
17189
- mtime = statSync14(absolute).mtime.toISOString();
17273
+ text = readFileSync27(absolute, "utf8");
17274
+ mtime = statSync13(absolute).mtime.toISOString();
17190
17275
  } catch {
17191
17276
  return null;
17192
17277
  }
@@ -17201,14 +17286,14 @@ function selectsLearned(text, scope) {
17201
17286
  return origin === AUTO_EXTRACTED_ORIGIN;
17202
17287
  }
17203
17288
  function selectLearned(scope) {
17204
- const dir = join34(scope.dir, LEARNED_DIRECTORY);
17289
+ const dir = join33(scope.dir, LEARNED_DIRECTORY);
17205
17290
  if (entryKind(dir) !== "directory")
17206
17291
  return [];
17207
17292
  const selected = [];
17208
17293
  for (const name2 of visibleNames(dir)) {
17209
17294
  if (!name2.endsWith(MARKDOWN_EXTENSION) || name2 === MARKDOWN_EXTENSION)
17210
17295
  continue;
17211
- const absolute = join34(dir, name2);
17296
+ const absolute = join33(dir, name2);
17212
17297
  if (entryKind(absolute) !== "file")
17213
17298
  continue;
17214
17299
  const file = readSelected(absolute, `${LEARNED_DIRECTORY}/${name2}`, undefined);
@@ -17222,10 +17307,10 @@ function selectSkillFiles(scope) {
17222
17307
  for (const name2 of visibleNames(scope.dir)) {
17223
17308
  if (name2 === LEARNED_DIRECTORY)
17224
17309
  continue;
17225
- const skillDir = join34(scope.dir, name2);
17310
+ const skillDir = join33(scope.dir, name2);
17226
17311
  if (entryKind(skillDir) !== "directory")
17227
17312
  continue;
17228
- const absolute = join34(skillDir, SKILL_FILE);
17313
+ const absolute = join33(skillDir, SKILL_FILE);
17229
17314
  if (entryKind(absolute) !== "file")
17230
17315
  continue;
17231
17316
  const file = readSelected(absolute, `${name2}/${SKILL_FILE}`, visibleNames(skillDir));
@@ -17286,7 +17371,7 @@ Usage: ${BACKFILL_USAGE}`);
17286
17371
  }
17287
17372
  function isDirectory3(path) {
17288
17373
  try {
17289
- return statSync15(path).isDirectory();
17374
+ return statSync14(path).isDirectory();
17290
17375
  } catch {
17291
17376
  return false;
17292
17377
  }
@@ -17410,7 +17495,7 @@ function reviewedProposals(dir) {
17410
17495
  return read2.flatMap((entry) => entry.result.file === null ? [] : [entry.result.file]);
17411
17496
  }
17412
17497
  function rowPaths(files, root) {
17413
- return files.flatMap((file) => file.status !== REVIEWED_FILE ? [] : file.rows.filter((row2) => row2.status === ANSWERED_ROW).map((row2) => join35(root, ...row2.path.split("/"))));
17498
+ return files.flatMap((file) => file.status !== REVIEWED_FILE ? [] : file.rows.filter((row2) => row2.status === ANSWERED_ROW).map((row2) => join34(root, ...row2.path.split("/"))));
17414
17499
  }
17415
17500
  function runApply(context, scope, backfillDir, projectRoot3) {
17416
17501
  const options = checkOptions(context, projectRoot3);
@@ -17456,7 +17541,7 @@ async function runBackfill(context, seams) {
17456
17541
  const dir = readBackfillDirectory(context.args, seams.cwd);
17457
17542
  const projectRoot3 = readConsumerRoot(context.flags["project"], seams.cwd);
17458
17543
  const scope = backfillScopeOf(dir, projectOf12(context).home);
17459
- const backfillDir = join35(scope.base, BACKFILL_PATH);
17544
+ const backfillDir = join34(scope.base, BACKFILL_PATH);
17460
17545
  if (mode === "propose") {
17461
17546
  await runPropose(context, scope, backfillDir, seams);
17462
17547
  return;
@@ -17570,13 +17655,13 @@ function createSkillCheckCommand(seams = DEFAULT_CHECK_SEAMS) {
17570
17655
  var check_default3 = createSkillCheckCommand();
17571
17656
 
17572
17657
  // src/commands/skill/demote.ts
17573
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync31, statSync as statSync17, writeFileSync as writeFileSync10 } from "fs";
17658
+ import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync29, statSync as statSync16, writeFileSync as writeFileSync10 } from "fs";
17574
17659
  import { dirname as dirname9, resolve as resolve16 } from "path";
17575
17660
 
17576
17661
  // src/demote/apply.ts
17577
- import { copyFileSync as copyFileSync5, existsSync as existsSync13, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readdirSync as readdirSync10, readFileSync as readFileSync30, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync16, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
17662
+ import { copyFileSync as copyFileSync5, existsSync as existsSync14, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readdirSync as readdirSync9, readFileSync as readFileSync28, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync15, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
17578
17663
  import { tmpdir as tmpdir2 } from "os";
17579
- import { dirname as dirname8, join as join36 } from "path";
17664
+ import { dirname as dirname8, join as join35 } from "path";
17580
17665
  var DEMOTION_ACTION_KINDS = [
17581
17666
  "demoted",
17582
17667
  "kept",
@@ -17597,18 +17682,18 @@ function learnedSkillName(path) {
17597
17682
  return base.slice(0, -MARKDOWN_EXTENSION.length);
17598
17683
  }
17599
17684
  function sourcePath(scope, path) {
17600
- return join36(scope.dir, ...path.split("/"));
17685
+ return join35(scope.dir, ...path.split("/"));
17601
17686
  }
17602
17687
  function demotedPath(scope, path) {
17603
- return join36(scope.demotedDir, ...path.split("/"));
17688
+ return join35(scope.demotedDir, ...path.split("/"));
17604
17689
  }
17605
17690
  function promotedPath(scope, path) {
17606
- return join36(scope.dir, learnedSkillName(path), SKILL_FILE);
17691
+ return join35(scope.dir, learnedSkillName(path), SKILL_FILE);
17607
17692
  }
17608
17693
  function takenInstinctIds(dir) {
17609
17694
  let names;
17610
17695
  try {
17611
- names = readdirSync10(dir);
17696
+ names = readdirSync9(dir);
17612
17697
  } catch {
17613
17698
  return [];
17614
17699
  }
@@ -17616,7 +17701,7 @@ function takenInstinctIds(dir) {
17616
17701
  }
17617
17702
  function readText4(path) {
17618
17703
  try {
17619
- return statSync16(path).isFile() ? readFileSync30(path, "utf8") : null;
17704
+ return statSync15(path).isFile() ? readFileSync28(path, "utf8") : null;
17620
17705
  } catch {
17621
17706
  return null;
17622
17707
  }
@@ -17644,7 +17729,7 @@ function planKept(scope, row2, file) {
17644
17729
  return inert3(row2.path, "procedure", "kept", "procedure-shaped: left where it is, for the backfill");
17645
17730
  }
17646
17731
  const to = promotedPath(scope, row2.path);
17647
- if (existsSync13(to) || existsSync13(dirname8(to))) {
17732
+ if (existsSync14(to) || existsSync14(dirname8(to))) {
17648
17733
  return inert3(row2.path, "procedure", "refused", `kept as a skill, but ${to} is already there`);
17649
17734
  }
17650
17735
  return {
@@ -17658,7 +17743,7 @@ function planKept(scope, row2, file) {
17658
17743
  };
17659
17744
  }
17660
17745
  function checkCandidate(dir, id, text, pathDirs) {
17661
- const path = join36(dir, `${id}${MARKDOWN_EXTENSION}`);
17746
+ const path = join35(dir, `${id}${MARKDOWN_EXTENSION}`);
17662
17747
  writeFileSync9(path, text, "utf8");
17663
17748
  const report3 = checkFile(path, "instinct", { projectRoot: null, pathDirs });
17664
17749
  return failureLines2(report3.issues);
@@ -17679,11 +17764,11 @@ function planDemoted(scope, row2, file, context) {
17679
17764
  if (failures.length > 0) {
17680
17765
  return inert3(row2.path, "observation", "refused", `the record ${id} fails the checker \u2014 ${failures.join("; ")}`);
17681
17766
  }
17682
- const destination = join36(scope.instinctsDir, `${id}${MARKDOWN_EXTENSION}`);
17767
+ const destination = join35(scope.instinctsDir, `${id}${MARKDOWN_EXTENSION}`);
17683
17768
  const kept = demotedPath(scope, row2.path);
17684
- if (existsSync13(destination))
17769
+ if (existsSync14(destination))
17685
17770
  return inert3(row2.path, "observation", "refused", `${destination} is already there`);
17686
- if (existsSync13(kept))
17771
+ if (existsSync14(kept))
17687
17772
  return inert3(row2.path, "observation", "refused", `${kept} is already there`);
17688
17773
  context.taken.push(id);
17689
17774
  return {
@@ -17715,7 +17800,7 @@ function planRow(scope, row2, context) {
17715
17800
  entries: undefined,
17716
17801
  absolute,
17717
17802
  hash,
17718
- mtime: statSync16(absolute).mtime.toISOString()
17803
+ mtime: statSync15(absolute).mtime.toISOString()
17719
17804
  };
17720
17805
  return verdict === "procedure" ? planKept(scope, row2, file) : planDemoted(scope, row2, file, context);
17721
17806
  }
@@ -17726,19 +17811,19 @@ function countActions(actions) {
17726
17811
  return counts;
17727
17812
  }
17728
17813
  function planDemotion(report3, scope, seams = DEFAULT_APPLY_SEAMS) {
17729
- const temp = mkdtempSync2(join36(tmpdir2(), "rafa-demote-"));
17814
+ const temp = mkdtempSync2(join35(tmpdir2(), "rafa-demote-"));
17730
17815
  const taken = [...takenInstinctIds(scope.instinctsDir)];
17731
17816
  try {
17732
17817
  const actions = report3.rows.map((row2) => planRow(scope, row2, { temp, taken, seams }));
17733
17818
  return { scope, actions, counts: countActions(actions) };
17734
17819
  } finally {
17735
- rmSync3(temp, { recursive: true, force: true });
17820
+ rmSync4(temp, { recursive: true, force: true });
17736
17821
  }
17737
17822
  }
17738
17823
  function moveFile(move3) {
17739
17824
  mkdirSync10(dirname8(move3.to), { recursive: true });
17740
17825
  try {
17741
- renameSync2(move3.from, move3.to);
17826
+ renameSync3(move3.from, move3.to);
17742
17827
  } catch {
17743
17828
  copyFileSync5(move3.from, move3.to);
17744
17829
  unlinkSync(move3.from);
@@ -17817,7 +17902,7 @@ Usage: ${DEMOTE_USAGE}`);
17817
17902
  }
17818
17903
  function isDirectory4(path) {
17819
17904
  try {
17820
- return statSync17(path).isDirectory();
17905
+ return statSync16(path).isDirectory();
17821
17906
  } catch {
17822
17907
  return false;
17823
17908
  }
@@ -17845,9 +17930,9 @@ function verdictLine(report3) {
17845
17930
  return `${String(report3.rows.length)} file(s): ${parts.join(", ")}`;
17846
17931
  }
17847
17932
  function previousReport(path, context) {
17848
- if (!existsSync14(path))
17933
+ if (!existsSync15(path))
17849
17934
  return null;
17850
- const parsed = parseDemotionReport(readFileSync31(path, "utf8"));
17935
+ const parsed = parseDemotionReport(readFileSync29(path, "utf8"));
17851
17936
  if (parsed.report !== null)
17852
17937
  return parsed.report;
17853
17938
  context.output.warn(`the report already at ${path} does not parse, so no override in it is carried forward:` + ` ${parsed.issues.map((issue2) => `line ${String(issue2.line)} ${issue2.code}`).join(", ")}`);
@@ -17880,10 +17965,10 @@ function runWrite(context, scope) {
17880
17965
  context.output.info(line);
17881
17966
  }
17882
17967
  function reviewedReport(scope) {
17883
- if (!existsSync14(scope.reportPath)) {
17968
+ if (!existsSync15(scope.reportPath)) {
17884
17969
  throw new CommandExit(1, `\u274C No report at ${scope.reportPath}; run "rafa skill demote ${scope.dir}" first, then review it`);
17885
17970
  }
17886
- const parsed = parseDemotionReport(readFileSync31(scope.reportPath, "utf8"));
17971
+ const parsed = parseDemotionReport(readFileSync29(scope.reportPath, "utf8"));
17887
17972
  if (parsed.report === null) {
17888
17973
  const lines2 = parsed.issues.map((issue2) => ` line ${String(issue2.line)} ${issue2.code}: ${issue2.message}`);
17889
17974
  throw new CommandExit(1, [`\u274C ${scope.reportPath} does not parse:`, ...lines2].join(`
@@ -17989,8 +18074,8 @@ var demote_default = createSkillDemoteCommand();
17989
18074
 
17990
18075
  // src/commands/skill/show.ts
17991
18076
  var DEFAULT_SKILL_SHOW_SEAMS = DEFAULT_SKILL_LIST_SEAMS;
17992
- var COMMAND_NAME5 = "rafa skill show";
17993
- var USAGE30 = "rafa skill show <name> [--full]";
18077
+ var COMMAND_NAME6 = "rafa skill show";
18078
+ var USAGE32 = "rafa skill show <name> [--full]";
17994
18079
  function unknownSkillMessage(name2, inventory) {
17995
18080
  const agent = findShown(inventory.records, "agent", name2);
17996
18081
  const hint = agent === null ? [] : [`An agent is named "${name2}" (${agent.source}): rafa agent show ${name2}`];
@@ -17998,7 +18083,7 @@ function unknownSkillMessage(name2, inventory) {
17998
18083
  `\u274C No skill is named "${name2}".`,
17999
18084
  ...hint,
18000
18085
  "Run `rafa skill list` to see every skill and where it comes from.",
18001
- `Usage: ${USAGE30}`
18086
+ `Usage: ${USAGE32}`
18002
18087
  ].join(`
18003
18088
  `);
18004
18089
  }
@@ -18014,10 +18099,10 @@ function projectOf14(context) {
18014
18099
  return context.project;
18015
18100
  }
18016
18101
  async function runShow3(context, seams) {
18017
- const full = readSwitch("full", context.flags["full"], `Type the name ahead of it: ${USAGE30}`);
18018
- const name2 = expectOneArgument(context.args, USAGE30);
18102
+ const full = readSwitch("full", context.flags["full"], `Type the name ahead of it: ${USAGE32}`);
18103
+ const name2 = expectOneArgument(context.args, USAGE32);
18019
18104
  const project = projectOf14(context);
18020
- const { inventory, settingSources } = await projectInventory(project, context, seams, COMMAND_NAME5);
18105
+ const { inventory, settingSources } = await projectInventory(project, context, seams, COMMAND_NAME6);
18021
18106
  const warnings = warningLines(inventory);
18022
18107
  for (const warning of warnings)
18023
18108
  context.output.warn(warning);
@@ -18095,8 +18180,8 @@ var VERDICT_WORDS = Object.freeze({
18095
18180
  pending: "checks pending",
18096
18181
  none: "no checks"
18097
18182
  });
18098
- function counted3(count, noun, plural5 = `${noun}s`) {
18099
- return `${String(count)} ${count === 1 ? noun : plural5}`;
18183
+ function counted3(count2, noun, plural5 = `${noun}s`) {
18184
+ return `${String(count2)} ${count2 === 1 ? noun : plural5}`;
18100
18185
  }
18101
18186
  function info(text) {
18102
18187
  return { level: "info", text };
@@ -18344,7 +18429,7 @@ async function readStatusSections(input, seams = {}) {
18344
18429
  }
18345
18430
 
18346
18431
  // src/commands/status.ts
18347
- var COMMAND_NAME6 = "rafa status";
18432
+ var COMMAND_NAME7 = "rafa status";
18348
18433
  var STATUS_USAGE = "rafa status";
18349
18434
  var STATUS_ARGUMENT_EXIT = 2;
18350
18435
  var DEFAULT_STATUS_SEAMS = Object.freeze({});
@@ -18356,13 +18441,13 @@ function projectOf15(context) {
18356
18441
  function expectNoWord(args) {
18357
18442
  if (args.length === 0)
18358
18443
  return;
18359
- throw new CommandExit(STATUS_ARGUMENT_EXIT, `\u274C ${COMMAND_NAME6}: expected no argument, got ${String(args.length)}: ${args.join(" ")}
18444
+ throw new CommandExit(STATUS_ARGUMENT_EXIT, `\u274C ${COMMAND_NAME7}: expected no argument, got ${String(args.length)}: ${args.join(" ")}
18360
18445
  Usage: ${STATUS_USAGE}`);
18361
18446
  }
18362
18447
  async function runStatus2(context, seams) {
18363
18448
  expectNoWord(context.args);
18364
18449
  const project = projectOf15(context);
18365
- const config = resolveProjectConfig(project, COMMAND_NAME6, (message) => {
18450
+ const config = resolveProjectConfig(project, COMMAND_NAME7, (message) => {
18366
18451
  context.output.warn(message);
18367
18452
  });
18368
18453
  const read3 = seams.read ?? ((input) => readStatusSections(input));
@@ -18428,11 +18513,11 @@ var CORE_SUBJECTS = Object.freeze([
18428
18513
  { name: "loop", summary: "start a plan; stop, pause, resume, show and list its sessions" },
18429
18514
  { name: "issue", summary: "the tracker: list, show, create, comment on and move issues; mark one ready, unblock it and check its references" },
18430
18515
  { name: "pr", summary: "the pull request of a branch: one line, in full or in the browser; list, wait on, merge and triage them" },
18431
- { name: "effort", summary: "collect session and commit rows; report per plan" },
18516
+ { name: "effort", summary: "collect session and commit rows; report per plan; repair a store a newer rafa migrated" },
18432
18517
  { name: "module", summary: "list the configured modules; run an action a module provides" },
18433
18518
  { name: "agent", summary: "copy an agent definition into the project; list what a session sees" },
18434
18519
  { name: "skill", summary: "check a skills directory; list each tier; demote and backfill it" },
18435
- { name: "instinct", summary: "check an instincts directory; list and show its records" },
18520
+ { name: "instinct", summary: "check an instincts directory; list, show, flag and promote its records" },
18436
18521
  { name: "release", summary: "read the release state of the project; tag the release branch's HEAD" }
18437
18522
  ]);
18438
18523
  var CORE_COMMANDS = Object.freeze([
@@ -18465,6 +18550,7 @@ var CORE_COMMANDS = Object.freeze([
18465
18550
  triage_default,
18466
18551
  collect_default,
18467
18552
  report_default,
18553
+ fix_schema_default,
18468
18554
  list_default7,
18469
18555
  exec_default,
18470
18556
  vendor_default,
@@ -18480,6 +18566,8 @@ var CORE_COMMANDS = Object.freeze([
18480
18566
  check_default,
18481
18567
  list_default4,
18482
18568
  show_default2,
18569
+ flag_default,
18570
+ promote_default,
18483
18571
  status_default2,
18484
18572
  tag_default,
18485
18573
  status_default3,