@open-tomato/rafa 0.18.0 → 0.19.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,8 +32,7 @@ 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,
38
37
  SPEC_BLOCKED_LABEL,
39
38
  SPEC_EXTENSION,
@@ -46,7 +45,7 @@ import {
46
45
  UNREADABLE,
47
46
  VENDOR_COMMAND,
48
47
  VERSION_SHAPE,
49
- actionHash,
48
+ WHEN_TO_USE_HEADING,
50
49
  actionInvocation,
51
50
  actionOutput,
52
51
  announceRiskTotal,
@@ -54,6 +53,7 @@ import {
54
53
  blockedFaultMessage,
55
54
  blockedLineSentence,
56
55
  boardId,
56
+ bodySections,
57
57
  branchClaims,
58
58
  bundledAgentsDirectory,
59
59
  byName,
@@ -62,13 +62,14 @@ import {
62
62
  checkReferences,
63
63
  checkbox,
64
64
  checkboxAt,
65
+ classifySkill,
65
66
  cleanUpSteps,
66
67
  closedIssuesIn,
67
68
  collect,
68
- collectReferences,
69
69
  collectSessionRow,
70
70
  commandLine,
71
71
  commandWords,
72
+ convertToInstinct,
72
73
  coreRoster,
73
74
  countCharacters,
74
75
  countPreviousCopies,
@@ -95,6 +96,7 @@ import {
95
96
  failingRows,
96
97
  findReadinessGaps,
97
98
  fingerprintText,
99
+ firstSentence,
98
100
  formatCounts,
99
101
  formatRows,
100
102
  ghHostOf,
@@ -104,7 +106,6 @@ import {
104
106
  ghPreflightItems,
105
107
  ghPullRequestsIn,
106
108
  ghUnauthenticatedMessage,
107
- gitRemoteUrl,
108
109
  gitSaid,
109
110
  groupChangeNotes,
110
111
  hasDiverged,
@@ -125,16 +126,13 @@ import {
125
126
  list_default,
126
127
  loadConfig,
127
128
  memoiseVerifier,
128
- mergeFrontmatter,
129
129
  missingPlanAgents,
130
130
  name,
131
131
  nextQuestion,
132
- normalizeRemote,
133
132
  notesFileName,
134
133
  onTracker,
135
134
  openNextSources,
136
135
  parseBaseStanding,
137
- parseInstinct,
138
136
  parseRoadmapBody,
139
137
  parseSemanticVersion,
140
138
  parseWorkingTree,
@@ -158,8 +156,6 @@ import {
158
156
  readChoice,
159
157
  readChoiceFlag,
160
158
  readCopyRefs,
161
- readFrontmatter,
162
- readFrontmatterDocument,
163
159
  readInventoryFrontmatter,
164
160
  readManifestVersion,
165
161
  readMergeRefusal,
@@ -182,7 +178,6 @@ import {
182
178
  refusal,
183
179
  refuseMisplacedRuntime,
184
180
  remainingFrom,
185
- renderFrontmatter,
186
181
  renderNoteLines,
187
182
  renderRiskText,
188
183
  report,
@@ -204,7 +199,6 @@ import {
204
199
  runAction,
205
200
  runsDir,
206
201
  scanClaimBranches,
207
- scanLayout,
208
202
  scopeAt,
209
203
  selfAndAncestors,
210
204
  serveVerdict,
@@ -230,10 +224,8 @@ import {
230
224
  version,
231
225
  versionLine,
232
226
  waitForChecks,
233
- writeFrontmatter,
234
- writeInstinct,
235
227
  writeSession
236
- } from "./index-6vkd153j.js";
228
+ } from "./index-ca0fccvr.js";
237
229
  import {
238
230
  PROBE_TIMEOUT_MS,
239
231
  findNextTask,
@@ -247,8 +239,10 @@ import {
247
239
  runPreflight,
248
240
  splitBlockerComment,
249
241
  trackerPathFor
250
- } from "./index-0pdsq2hy.js";
242
+ } from "./index-09p41s0n.js";
251
243
  import {
244
+ ACTION_HEADING,
245
+ CAUSE_HEADING,
252
246
  CLAUDE_BIN,
253
247
  CORE_ADAPTER_REGISTRY,
254
248
  EFFORT_STORE_DIR,
@@ -256,17 +250,32 @@ import {
256
250
  ISSUE_PRIORITIES,
257
251
  ISSUE_STATES,
258
252
  ISSUE_TYPES,
253
+ MARKDOWN_EXTENSION,
254
+ SKILL_FILE,
255
+ allRecords,
259
256
  claudeArgs,
260
257
  createGhRunner,
261
258
  effortStorePath,
259
+ findRecords,
260
+ gitRemoteUrl,
261
+ instinctProject,
262
+ mergeFrontmatter,
262
263
  moduleOfLabels,
264
+ normalizeRemote,
265
+ readFrontmatter,
266
+ readFrontmatterDocument,
267
+ readScopes,
268
+ renderFrontmatter,
263
269
  runClaudeCaptured,
270
+ scanLayout,
264
271
  selectEffortStore,
265
272
  sessionSpawnEnv,
266
273
  spawnClaudeCaptured,
267
274
  sqliteStorePath,
268
- typeOfLabels
269
- } from "./index-at9f1z2z.js";
275
+ toHeldRecords,
276
+ typeOfLabels,
277
+ writeFrontmatter
278
+ } from "./index-gb51x34c.js";
270
279
  import {
271
280
  CONFIG_DEFAULTS,
272
281
  CONFIG_FILE,
@@ -280,15 +289,18 @@ import {
280
289
  readItemBytes,
281
290
  readRafaBlocks,
282
291
  resolveTiers
283
- } from "./index-jva32qe6.js";
292
+ } from "./index-pqrpcfaz.js";
293
+ import {
294
+ promotable
295
+ } from "./index-d6d0942q.js";
284
296
  import {
285
297
  createCommandRegistry,
286
298
  describeRegistry,
287
299
  mountKey
288
- } from "./index-kvnggvyk.js";
300
+ } from "./index-c5cecsga.js";
289
301
  import {
290
302
  CommandExit
291
- } from "./index-ddf85qac.js";
303
+ } from "./index-vg7ycs94.js";
292
304
  import {
293
305
  MERGE_METHODS,
294
306
  RELEASE_AUTO,
@@ -299,10 +311,11 @@ import {
299
311
  isMergeMethod,
300
312
  isSkillTier,
301
313
  messageOf,
302
- parseBudgetUsd,
303
- resolveInstinctScopes,
304
- tierExists
305
- } from "./index-944pncd8.js";
314
+ parseBudgetUsd
315
+ } from "./index-cedghpva.js";
316
+ import {
317
+ triggerKey
318
+ } from "./index-wp8c28fd.js";
306
319
 
307
320
  // src/inventory/disabled.ts
308
321
  import { readFileSync } from "fs";
@@ -4956,7 +4969,7 @@ function readScope2(scope, path, loaded) {
4956
4969
  }
4957
4970
  return { read: { scope, path, loaded, entries }, warnings };
4958
4971
  }
4959
- function readScopes(seams) {
4972
+ function readScopes2(seams) {
4960
4973
  const read = OVERRIDE_SCOPES.flatMap((scope) => {
4961
4974
  const path = overrideSettingsPath(scope, { home: seams.home, projectRoot: seams.projectRoot });
4962
4975
  return path === null ? [] : [readScope2(scope, path, seams.settingSources.includes(scope))];
@@ -5009,7 +5022,7 @@ function pathDifference(shell, session, layer) {
5009
5022
  return Object.freeze({ layer, added: Object.freeze(added), removed: Object.freeze(removed), reordered });
5010
5023
  }
5011
5024
  function readSessionEnv(seams) {
5012
- const { scopes, warnings } = readScopes(seams);
5025
+ const { scopes, warnings } = readScopes2(seams);
5013
5026
  const { env, layers } = overlay(sessionSpawnEnv(seams.env), seams.env, scopes);
5014
5027
  return Object.freeze({
5015
5028
  env: Object.freeze(env),
@@ -7799,6 +7812,11 @@ var CONFIG_SETTINGS_LINES = Object.freeze([
7799
7812
  `# fallback: [${CONFIG_DEFAULTS.trackerFallback.join(", ")}]`,
7800
7813
  "# learning:",
7801
7814
  `# adapter: ${CONFIG_DEFAULTS.learningAdapter}`,
7815
+ "# bless:",
7816
+ `# minConfidence: ${String(CONFIG_DEFAULTS.learningBlessMinConfidence)} # 0.3..0.9, the least confidence of a lesson tasks may use`,
7817
+ "# promote:",
7818
+ `# after: ${String(CONFIG_DEFAULTS.learningPromoteAfter)} # distinct sources a lesson needs before the wrap-up promotes it`,
7819
+ `# minConfidence: ${String(CONFIG_DEFAULTS.learningPromoteMinConfidence)} # 0.3..0.9, the least confidence of a lesson to promote`,
7802
7820
  "# output:",
7803
7821
  `# mode: ${CONFIG_DEFAULTS.outputMode} # text | json`,
7804
7822
  "# prerequisites:",
@@ -8558,72 +8576,196 @@ function createInstinctCheckCommand(seams = DEFAULT_CHECK_SEAMS) {
8558
8576
  }
8559
8577
  var check_default = createInstinctCheckCommand();
8560
8578
 
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);
8579
+ // src/commands/instinct/flag.ts
8580
+ var NAME = "rafa instinct flag";
8581
+ var USAGE6 = "rafa instinct flag <id> <reason>";
8582
+ function refusedFlagMessage(id, kind, reason) {
8583
+ return [
8584
+ `\u274C ${NAME}: the \`${kind}\` learning adapter did not flag "${id}": ${reason}`,
8585
+ "Run `rafa instinct list` to see the ids the project holds."
8586
+ ].join(`
8587
+ `);
8569
8588
  }
8570
- function unreadableIssue(message) {
8571
- return { code: "missing-frontmatter", field: "file", message: `the file could not be read: ${message}` };
8589
+ function blankReasonMessage(id) {
8590
+ return `\u274C ${NAME}: the reason to flag "${id}" is blank; say why the lesson is wrong.
8591
+ Usage: ${USAGE6}`;
8572
8592
  }
8573
- function readRecord(path, scope, id) {
8574
- let text;
8593
+ function makeAdapter(registry, kind, context) {
8575
8594
  try {
8576
- text = readFileSync16(path, "utf8");
8595
+ return registry.resolve("learning", kind).create({
8596
+ repoRoot: context.repoRoot,
8597
+ home: context.home,
8598
+ learningBlessMinConfidence: context.minConfidence
8599
+ });
8577
8600
  } catch (error) {
8578
- const message = error instanceof Error ? error.message : String(error);
8579
- return { scope, path, id, instinct: null, issues: [unreadableIssue(message)] };
8601
+ throw new CommandExit(1, `\u274C ${NAME}: the \`${kind}\` learning adapter cannot be made: ${messageOf(error)}`);
8580
8602
  }
8581
- const parsed = parseInstinct(text);
8582
- return { scope, path, id, instinct: parsed.instinct, issues: parsed.issues };
8583
8603
  }
8584
- function isFile2(path) {
8604
+ async function flagInstinct(context, seams) {
8605
+ const [id, reason] = expectTwoArguments(context.args, USAGE6);
8606
+ if (reason.trim() === "")
8607
+ throw new CommandExit(1, blankReasonMessage(id));
8608
+ const project = requireProject(context, NAME);
8609
+ const config = resolveProjectConfig(project, NAME, (message) => {
8610
+ context.output.warn(message);
8611
+ });
8612
+ const kind = config.learningAdapter;
8613
+ const adapter = makeAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, {
8614
+ repoRoot: project.root,
8615
+ home: project.home,
8616
+ minConfidence: config.learningBlessMinConfidence
8617
+ });
8585
8618
  try {
8586
- return statSync11(path).isFile();
8587
- } catch {
8588
- return false;
8619
+ await adapter.flag(id, reason);
8620
+ } catch (error) {
8621
+ throw new CommandExit(1, refusedFlagMessage(id, kind, messageOf(error)));
8589
8622
  }
8623
+ return { id, reason, adapter: kind };
8590
8624
  }
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)))
8625
+ function createInstinctFlagCommand(seams = {}) {
8626
+ const command = {
8627
+ name: "instinct flag",
8628
+ subject: "instinct",
8629
+ action: "flag",
8630
+ summary: "flag one held lesson as wrong, so no later bundle blesses it",
8631
+ 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.",
8632
+ args: [
8633
+ {
8634
+ name: "id",
8635
+ description: "The id of a lesson the project holds, as `rafa instinct list` prints it.",
8636
+ type: "string",
8637
+ required: true
8638
+ },
8639
+ {
8640
+ name: "reason",
8641
+ description: "Why the lesson is wrong, quoted as one word; stored beside the flag.",
8642
+ type: "string",
8643
+ required: true
8644
+ }
8645
+ ],
8646
+ flags: [],
8647
+ examples: [
8648
+ {
8649
+ cmd: 'rafa instinct flag worktree-missing-node-modules "bun install runs on fork since 0.9"',
8650
+ note: "Keeps that lesson out of every bundle the loop pulls from now on."
8651
+ },
8652
+ {
8653
+ cmd: 'rafa instinct flag worktree-missing-node-modules "stale" --output=json',
8654
+ note: "Gives the id, the reason and the adapter kind as the data of the terminal result event."
8655
+ }
8656
+ ],
8657
+ outputs: ["text", "json"],
8658
+ run: async (context) => {
8659
+ const result = await flagInstinct(context, seams);
8660
+ if (context.outputMode === "json") {
8661
+ context.output.result(result);
8662
+ return;
8663
+ }
8664
+ context.output.info(`\uD83D\uDEA9 Flagged ${result.id}: ${result.reason}`);
8665
+ context.output.info(` The \`${result.adapter}\` learning adapter leaves it out of every later bundle.`);
8666
+ }
8602
8667
  };
8668
+ return Object.freeze(command);
8603
8669
  }
8604
- function readScopes2(seams) {
8605
- return resolveInstinctScopes(seams).map((location) => readScope3(location.scope, location.dir));
8670
+ var flag_default = createInstinctFlagCommand();
8671
+
8672
+ // src/commands/instinct/promote.ts
8673
+ var NAME2 = "rafa instinct promote";
8674
+ var USAGE7 = "rafa instinct promote";
8675
+ var CONFIDENCE_DIGITS = 2;
8676
+ function refusedPullMessage(kind, reason, name2 = NAME2) {
8677
+ return `\u274C ${name2}: the \`${kind}\` learning adapter answered no blessed set: ${reason}`;
8606
8678
  }
8607
- function allRecords(listings) {
8608
- return listings.flatMap((listing) => listing.records);
8679
+ function makeLearningAdapter(registry, kind, context, name2 = NAME2) {
8680
+ try {
8681
+ return registry.resolve("learning", kind).create({
8682
+ repoRoot: context.repoRoot,
8683
+ home: context.home,
8684
+ learningBlessMinConfidence: context.minConfidence
8685
+ });
8686
+ } catch (error) {
8687
+ throw new CommandExit(1, `\u274C ${name2}: the \`${kind}\` learning adapter cannot be made: ${messageOf(error)}`);
8688
+ }
8609
8689
  }
8610
- function findRecords(listings, id) {
8611
- return allRecords(listings).filter((entry) => entry.id === id);
8690
+ async function promotableLessons(context, seams) {
8691
+ expectNoArgument(context.args, USAGE7);
8692
+ const project = requireProject(context, NAME2);
8693
+ const config = resolveProjectConfig(project, NAME2, (message) => {
8694
+ context.output.warn(message);
8695
+ });
8696
+ const kind = config.learningAdapter;
8697
+ const adapter = makeLearningAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, {
8698
+ repoRoot: project.root,
8699
+ home: project.home,
8700
+ minConfidence: config.learningBlessMinConfidence
8701
+ });
8702
+ const after = config.learningPromoteAfter;
8703
+ const minConfidence = config.learningPromoteMinConfidence;
8704
+ let blessed;
8705
+ try {
8706
+ blessed = (await adapter.pullBlessed()).instincts;
8707
+ } catch (error) {
8708
+ throw new CommandExit(1, refusedPullMessage(kind, messageOf(error)));
8709
+ }
8710
+ return { adapter: kind, after, minConfidence, lessons: promotable(blessed, { after, minConfidence }) };
8612
8711
  }
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;
8712
+ function renderPromotable(result) {
8713
+ const keys = `learning.promote.after ${String(result.after)},` + ` learning.promote.minConfidence ${result.minConfidence.toFixed(CONFIDENCE_DIGITS)}`;
8714
+ if (result.lessons.length === 0) {
8715
+ return [`No lesson the \`${result.adapter}\` learning adapter holds is promotable at ${keys}.`];
8716
+ }
8717
+ return [
8718
+ `${String(result.lessons.length)} lesson(s) to promote from the \`${result.adapter}\` learning adapter, at ${keys}:`,
8719
+ ...result.lessons.flatMap((lesson) => [
8720
+ ` ${lesson.id} ${lesson.confidence.toFixed(CONFIDENCE_DIGITS)} used ${String(lesson.usage_count)} ${lesson.trigger}`,
8721
+ ` ${lesson.action}`
8722
+ ])
8723
+ ];
8617
8724
  }
8725
+ function createInstinctPromoteCommand(seams = {}) {
8726
+ const command = {
8727
+ name: "instinct promote",
8728
+ subject: "instinct",
8729
+ action: "promote",
8730
+ summary: "print the lessons that recurred enough to promote, writing nothing",
8731
+ 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.",
8732
+ args: [],
8733
+ flags: [],
8734
+ examples: [
8735
+ {
8736
+ cmd: "rafa instinct promote",
8737
+ note: "Lists each promotable lesson with its confidence, usage, trigger and action."
8738
+ },
8739
+ {
8740
+ cmd: "rafa instinct promote --output=json",
8741
+ note: "Gives the adapter kind, the two keys' values and the lessons as the data of the terminal result event."
8742
+ }
8743
+ ],
8744
+ outputs: ["text", "json"],
8745
+ run: async (context) => {
8746
+ const result = await promotableLessons(context, seams);
8747
+ if (context.outputMode === "json") {
8748
+ context.output.result(result);
8749
+ return;
8750
+ }
8751
+ for (const line of renderPromotable(result))
8752
+ context.output.info(line);
8753
+ }
8754
+ };
8755
+ return Object.freeze(command);
8756
+ }
8757
+ var promote_default = createInstinctPromoteCommand();
8618
8758
 
8619
8759
  // src/commands/instinct/list.ts
8620
- var USAGE6 = "rafa instinct list";
8621
- var CONFIDENCE_DIGITS = 2;
8760
+ var NAME3 = "rafa instinct list";
8761
+ var USAGE8 = "rafa instinct list [--blessed | --conflicts]";
8762
+ var CONFIDENCE_DIGITS2 = 2;
8763
+ var HUNDREDTHS = 100;
8622
8764
  function instinctRowLine(entry) {
8623
8765
  const record = entry.instinct;
8624
8766
  if (record === null)
8625
8767
  return ` \u274C ${entry.id} ${String(entry.issues.length)} issue(s)`;
8626
- const confidence = record.confidence.toFixed(CONFIDENCE_DIGITS);
8768
+ const confidence = record.confidence.toFixed(CONFIDENCE_DIGITS2);
8627
8769
  return ` \u2705 ${entry.id} ${record.kind}/${record.domain} ${record.signal}` + ` ${confidence} ${record.trigger}`;
8628
8770
  }
8629
8771
  function scopeLines(listing) {
@@ -8643,38 +8785,171 @@ function renderInstinctList(result) {
8643
8785
  `${String(result.total)} instinct(s): ${String(result.clean)} read as records,` + ` ${String(result.total - result.clean)} do not`
8644
8786
  ];
8645
8787
  }
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 });
8788
+ function readViewFlag(name2, value) {
8789
+ if (value === undefined || value === false || value === "false")
8790
+ return false;
8791
+ if (value === true || value === "true")
8792
+ return true;
8793
+ throw new CommandExit(1, `\u274C --${name2} takes no value, and read "${value}" as one
8794
+ Usage: ${USAGE8}`);
8795
+ }
8796
+ function readListView(flags) {
8797
+ const blessed = readViewFlag("blessed", flags["blessed"]);
8798
+ const conflicts = readViewFlag("conflicts", flags["conflicts"]);
8799
+ if (blessed && conflicts) {
8800
+ throw new CommandExit(1, `\u274C --blessed and --conflicts are two views; give one
8801
+ Usage: ${USAGE8}`);
8802
+ }
8803
+ if (blessed)
8804
+ return "blessed";
8805
+ return conflicts ? "conflicts" : "all";
8806
+ }
8807
+ function oneLine(text) {
8808
+ return text.trim().replace(/\s+/gu, " ");
8809
+ }
8810
+ function byConfidence(left, right) {
8811
+ const gap = Math.round(right.confidence * HUNDREDTHS) - Math.round(left.confidence * HUNDREDTHS);
8812
+ if (gap !== 0)
8813
+ return gap;
8814
+ if (left.id < right.id)
8815
+ return -1;
8816
+ return left.id > right.id ? 1 : 0;
8817
+ }
8818
+ function scopeConflicts(listing) {
8819
+ const clean = listing.records.map((entry) => entry.instinct).filter((instinct) => instinct !== null);
8820
+ const groups = new Map;
8821
+ for (const record of toHeldRecords(clean)) {
8822
+ if (record.status !== "flagged")
8823
+ continue;
8824
+ const key = triggerKey(record.trigger);
8825
+ groups.set(key, [...groups.get(key) ?? [], record]);
8826
+ }
8827
+ return [...groups.values()].map((records) => ({
8828
+ scope: listing.scope,
8829
+ trigger: records[0].trigger,
8830
+ records: [...records].sort(byConfidence)
8831
+ }));
8832
+ }
8833
+ function lessonLine(indent, record, width, tail) {
8834
+ return `${indent}${record.id.padEnd(width)} ${record.confidence.toFixed(CONFIDENCE_DIGITS2)}` + ` used ${String(record.usage_count)} ${tail}`;
8835
+ }
8836
+ function conflictLines(conflict) {
8837
+ const width = Math.max(...conflict.records.map((record) => record.id.length));
8838
+ return [
8839
+ ` ${conflict.scope} ${conflict.trigger}`,
8840
+ ...conflict.records.map((record) => lessonLine(" ", record, width, oneLine(record.action)))
8841
+ ];
8842
+ }
8843
+ function renderConflicts(result) {
8844
+ if (result.conflicts.length === 0) {
8845
+ return [`No trigger either instinct scope holds carries more than one action (project: ${result.projectRoot}).`];
8846
+ }
8847
+ return [
8848
+ `Triggers held with more than one action (project: ${result.projectRoot}):`,
8849
+ ...result.conflicts.flatMap((conflict) => conflictLines(conflict)),
8850
+ `${String(result.conflicts.length)} flagged trigger(s): no bundle blesses any of their actions`
8851
+ ];
8852
+ }
8853
+ function renderBlessed(result) {
8854
+ const floor = `learning.bless.minConfidence ${result.minConfidence.toFixed(CONFIDENCE_DIGITS2)}`;
8855
+ if (result.lessons.length === 0) {
8856
+ return [`No lesson the \`${result.adapter}\` learning adapter holds is blessed at ${floor}.`];
8857
+ }
8858
+ return [
8859
+ `${String(result.lessons.length)} lesson(s) blessed by the \`${result.adapter}\` learning adapter, at ${floor}:`,
8860
+ ...result.lessons.flatMap((lesson) => [
8861
+ lessonLine(" ", lesson, 0, lesson.trigger),
8862
+ ` ${lesson.action}`
8863
+ ])
8864
+ ];
8865
+ }
8866
+ async function blessedLessons(context, seams) {
8867
+ const project = instinctProject(context, NAME3);
8868
+ const config = resolveProjectConfig(project, NAME3, (message) => {
8869
+ context.output.warn(message);
8870
+ });
8871
+ const kind = config.learningAdapter;
8872
+ const minConfidence = config.learningBlessMinConfidence;
8873
+ const adapter = makeLearningAdapter(seams.registry ?? CORE_ADAPTER_REGISTRY, kind, { repoRoot: project.root, home: project.home, minConfidence }, NAME3);
8874
+ try {
8875
+ return { adapter: kind, minConfidence, lessons: (await adapter.pullBlessed()).instincts };
8876
+ } catch (error) {
8877
+ throw new CommandExit(1, refusedPullMessage(kind, messageOf(error), NAME3));
8878
+ }
8879
+ }
8880
+ function conflicts(context) {
8881
+ const project = instinctProject(context, NAME3);
8882
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
8883
+ return { projectRoot: project.root, conflicts: scopes.flatMap((listing) => scopeConflicts(listing)) };
8884
+ }
8885
+ function everyRecord(context) {
8886
+ const project = instinctProject(context, NAME3);
8887
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
8650
8888
  const records = allRecords(scopes);
8651
- const result = {
8889
+ return {
8652
8890
  projectRoot: project.root,
8653
8891
  scopes,
8654
8892
  total: records.length,
8655
8893
  clean: records.filter((entry) => entry.instinct !== null).length
8656
8894
  };
8895
+ }
8896
+ function answer(context, result, lines2) {
8657
8897
  if (context.outputMode === "json") {
8658
8898
  context.output.result(result);
8659
8899
  return;
8660
8900
  }
8661
- for (const line of renderInstinctList(result))
8901
+ for (const line of lines2())
8662
8902
  context.output.info(line);
8663
8903
  }
8664
- function createInstinctListCommand() {
8904
+ async function runList4(context, seams) {
8905
+ expectNoArgument(context.args, USAGE8);
8906
+ const view = readListView(context.flags);
8907
+ if (view === "blessed") {
8908
+ const result2 = await blessedLessons(context, seams);
8909
+ answer(context, result2, () => renderBlessed(result2));
8910
+ return;
8911
+ }
8912
+ if (view === "conflicts") {
8913
+ const result2 = conflicts(context);
8914
+ answer(context, result2, () => renderConflicts(result2));
8915
+ return;
8916
+ }
8917
+ const result = everyRecord(context);
8918
+ answer(context, result, () => renderInstinctList(result));
8919
+ }
8920
+ function createInstinctListCommand(seams = {}) {
8665
8921
  const command = {
8666
8922
  name: "instinct list",
8667
8923
  subject: "instinct",
8668
8924
  action: "list",
8669
8925
  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.",
8926
+ 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
8927
  args: [],
8672
- flags: [],
8928
+ flags: [
8929
+ {
8930
+ name: "blessed",
8931
+ description: "List the lessons the configured learning adapter blesses, each with its confidence, usage," + " trigger and action, instead of every record. Takes no value.",
8932
+ type: "boolean"
8933
+ },
8934
+ {
8935
+ name: "conflicts",
8936
+ 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.",
8937
+ type: "boolean"
8938
+ }
8939
+ ],
8673
8940
  examples: [
8674
8941
  {
8675
8942
  cmd: "rafa instinct list",
8676
8943
  note: "Lists both scopes, each record with what it is about."
8677
8944
  },
8945
+ {
8946
+ cmd: "rafa instinct list --blessed",
8947
+ note: "Lists the lessons a task would be handed, most trusted first."
8948
+ },
8949
+ {
8950
+ cmd: "rafa instinct list --conflicts",
8951
+ note: "Lists each flagged trigger with its actions side by side."
8952
+ },
8678
8953
  {
8679
8954
  cmd: "rafa instinct list --output=json",
8680
8955
  note: "Gives the scopes and every record parsed as the data of the terminal result event."
@@ -8682,7 +8957,7 @@ function createInstinctListCommand() {
8682
8957
  ],
8683
8958
  outputs: ["text", "json"],
8684
8959
  run: async (context) => {
8685
- runList4(context);
8960
+ await runList4(context, seams);
8686
8961
  }
8687
8962
  };
8688
8963
  return Object.freeze(command);
@@ -8690,7 +8965,7 @@ function createInstinctListCommand() {
8690
8965
  var list_default4 = createInstinctListCommand();
8691
8966
 
8692
8967
  // src/commands/instinct/show.ts
8693
- var USAGE7 = "rafa instinct show <id>";
8968
+ var USAGE9 = "rafa instinct show <id>";
8694
8969
  var FIELD_ORDER = [
8695
8970
  "trigger",
8696
8971
  "kind",
@@ -8762,13 +9037,13 @@ function unreadableMessage(entry) {
8762
9037
  }
8763
9038
  function unknownIdMessage(id, scopes) {
8764
9039
  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(`
9040
+ return [`\u274C No instinct is filed under "${id}". Looked in:`, ...looked, `Usage: ${USAGE9}`].join(`
8766
9041
  `);
8767
9042
  }
8768
9043
  function runShow2(context) {
8769
- const id = expectOneArgument(context.args, USAGE7);
9044
+ const id = expectOneArgument(context.args, USAGE9);
8770
9045
  const project = instinctProject(context, "rafa instinct show");
8771
- const scopes = readScopes2({ home: project.home, projectRoot: project.root });
9046
+ const scopes = readScopes({ home: project.home, projectRoot: project.root });
8772
9047
  const found = findRecords(scopes, id);
8773
9048
  if (found.length === 0)
8774
9049
  throw new CommandExit(1, unknownIdMessage(id, scopes));
@@ -8825,8 +9100,8 @@ function createInstinctShowCommand() {
8825
9100
  var show_default2 = createInstinctShowCommand();
8826
9101
 
8827
9102
  // 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";
9103
+ import { readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync11 } from "fs";
9104
+ import { join as join22, resolve as resolve10 } from "path";
8830
9105
  var CHECK_USAGE = "rafa issue check <n> [--stamp]";
8831
9106
  var STAMP_FLAG = "stamp";
8832
9107
  var ISSUE_NUMBER = /^[1-9]\d*$/u;
@@ -8850,7 +9125,7 @@ function missingCopyMessage(issue, specsDir) {
8850
9125
  function copyNames(dir, issue) {
8851
9126
  let names;
8852
9127
  try {
8853
- names = readdirSync4(dir);
9128
+ names = readdirSync3(dir);
8854
9129
  } catch (error) {
8855
9130
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
8856
9131
  return [];
@@ -8858,7 +9133,7 @@ function copyNames(dir, issue) {
8858
9133
  }
8859
9134
  const prefix = `${boardId(issue)}-`;
8860
9135
  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();
9136
+ 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
9137
  }
8863
9138
  function findSavedCopy(root, specsDir, issue) {
8864
9139
  const names = copyNames(resolve10(root, specsDir), issue);
@@ -8868,11 +9143,11 @@ function findSavedCopy(root, specsDir, issue) {
8868
9143
  if (names.length > 1) {
8869
9144
  throw new CommandExit(1, [
8870
9145
  `\u274C Issue #${String(issue)} has ${String(names.length)} saved copies under ${specsDir}; remove the stale one:`,
8871
- ...names.map((name2) => ` ${join23(specsDir, name2)}`)
9146
+ ...names.map((name2) => ` ${join22(specsDir, name2)}`)
8872
9147
  ].join(`
8873
9148
  `));
8874
9149
  }
8875
- const path = join23(specsDir, only);
9150
+ const path = join22(specsDir, only);
8876
9151
  return { path, absolute: resolve10(root, path) };
8877
9152
  }
8878
9153
  function liveText(live) {
@@ -8921,7 +9196,7 @@ async function readReferences(absolute, issue, verify, stamp) {
8921
9196
  return rows.map((row2) => checkedRef(row2, row2.stamp));
8922
9197
  }
8923
9198
  const once = memoiseVerifier(verify);
8924
- const before = await readRefsText({ copy: readFileSync17(absolute, "utf8"), issue, verify: once });
9199
+ const before = await readRefsText({ copy: readFileSync16(absolute, "utf8"), issue, verify: once });
8925
9200
  const after = await restampCopyRefs({ path: absolute, issue, verify: once });
8926
9201
  return before.rows.map((row2, index) => checkedRef(row2, after.rows[index]?.stamp ?? null));
8927
9202
  }
@@ -8996,10 +9271,10 @@ function createIssueCheckCommand(seams = {}) {
8996
9271
  var check_default2 = createIssueCheckCommand();
8997
9272
 
8998
9273
  // src/commands/issue/comment.ts
8999
- var USAGE8 = "rafa issue comment <id> --body=<text>";
9274
+ var USAGE10 = "rafa issue comment <id> --body=<text>";
9000
9275
  async function commentOnIssue(context, seams) {
9001
- const id = expectOneArgument(context.args, USAGE8);
9002
- const body = readRequiredFlag(context.flags, "body", USAGE8);
9276
+ const id = expectOneArgument(context.args, USAGE10);
9277
+ const body = readRequiredFlag(context.flags, "body", USAGE10);
9003
9278
  const { tracker, data } = await resolveIssueTracker(context, seams);
9004
9279
  const ref = issueRef(tracker, id);
9005
9280
  await onTracker(tracker, `comment on issue ${id}`, () => tracker.comment(ref, body));
@@ -9053,16 +9328,16 @@ function createIssueCommentCommand(seams = DEFAULT_ISSUE_SEAMS) {
9053
9328
  var comment_default = createIssueCommentCommand();
9054
9329
 
9055
9330
  // src/commands/issue/create.ts
9056
- var USAGE9 = "rafa issue create --title=<text> [--body=<text>] [--type=<type>] [--module=<name>] [--priority=<priority>]";
9331
+ var USAGE11 = "rafa issue create --title=<text> [--body=<text>] [--type=<type>] [--module=<name>] [--priority=<priority>]";
9057
9332
  var DEFAULT_ISSUE_TYPE = "code";
9058
9333
  function readIssueDraft(flags) {
9059
9334
  return {
9060
9335
  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,
9336
+ title: readRequiredFlag(flags, "title", USAGE11),
9337
+ body: readTextFlag(flags, "body", USAGE11) ?? "",
9338
+ type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE11) ?? DEFAULT_ISSUE_TYPE,
9339
+ module: readNonBlankFlag(flags, "module", USAGE11) ?? TRIAGE_MODULE,
9340
+ priority: readChoiceFlag(flags, "priority", ISSUE_PRIORITIES, USAGE11) ?? null,
9066
9341
  project: null,
9067
9342
  blockedBy: []
9068
9343
  };
@@ -9071,7 +9346,7 @@ function renderCreated(ref) {
9071
9346
  return [`Created ${issueName(ref)}.`, ...urlLines(ref)];
9072
9347
  }
9073
9348
  async function createIssue(context, seams) {
9074
- expectNoArgument(context.args, USAGE9);
9349
+ expectNoArgument(context.args, USAGE11);
9075
9350
  const draft = readIssueDraft(context.flags);
9076
9351
  const { tracker, data } = await resolveIssueTracker(context, seams);
9077
9352
  const ref = await onTracker(tracker, "create the issue", () => tracker.create(draft));
@@ -9223,7 +9498,7 @@ function createGhBoardListing(options) {
9223
9498
  }
9224
9499
 
9225
9500
  // src/board/roadmap-rows.ts
9226
- import { readdirSync as readdirSync5 } from "fs";
9501
+ import { readdirSync as readdirSync4 } from "fs";
9227
9502
  var OUTLINE_HEADINGS = 3;
9228
9503
  var UNKNOWN_STATE = "unknown";
9229
9504
  function isMissing(error) {
@@ -9232,7 +9507,7 @@ function isMissing(error) {
9232
9507
  function createPlanDirNames(dir) {
9233
9508
  return () => {
9234
9509
  try {
9235
- return Object.freeze(readdirSync5(dir));
9510
+ return Object.freeze(readdirSync4(dir));
9236
9511
  } catch (error) {
9237
9512
  if (isMissing(error))
9238
9513
  return Object.freeze([]);
@@ -9463,24 +9738,24 @@ function renderRoadmapTable(rows, width) {
9463
9738
  }
9464
9739
 
9465
9740
  // 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}`;
9741
+ var USAGE12 = "rafa issue list [--roadmap [--all]] [--state=<state>] [--type=<type>] [--module=<name>]" + " [--search=<text>] [--limit=<n>]";
9742
+ var SWITCH_HINT = `Type it bare: ${USAGE12}`;
9468
9743
  var LIMIT = /^[1-9]\d*$/;
9469
9744
  function readLimit(flags) {
9470
- const value = readTextFlag(flags, "limit", USAGE10);
9745
+ const value = readTextFlag(flags, "limit", USAGE12);
9471
9746
  if (value === undefined)
9472
9747
  return;
9473
9748
  const limit = Number(value);
9474
9749
  if (LIMIT.test(value) && Number.isSafeInteger(limit))
9475
9750
  return limit;
9476
- throw lineRefusal(`--limit is "${value}", expected a positive whole number`, USAGE10);
9751
+ throw lineRefusal(`--limit is "${value}", expected a positive whole number`, USAGE12);
9477
9752
  }
9478
9753
  function readIssueQuery(flags) {
9479
9754
  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),
9755
+ state: readChoiceFlag(flags, "state", ISSUE_STATES, USAGE12),
9756
+ type: readChoiceFlag(flags, "type", ISSUE_TYPES, USAGE12),
9757
+ module: readNonBlankFlag(flags, "module", USAGE12),
9758
+ text: readNonBlankFlag(flags, "search", USAGE12),
9484
9759
  limit: readLimit(flags)
9485
9760
  };
9486
9761
  return Object.fromEntries(Object.entries(narrowed).filter(([, value]) => value !== undefined));
@@ -9489,10 +9764,10 @@ function readIssueListLine(flags) {
9489
9764
  const roadmap = readSwitch("roadmap", flags["roadmap"], SWITCH_HINT);
9490
9765
  const all = readSwitch("all", flags["all"], SWITCH_HINT);
9491
9766
  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);
9767
+ 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
9768
  }
9494
9769
  if (all && !roadmap)
9495
- throw lineRefusal("--all keeps the ticked Roadmap lines, so it needs --roadmap", USAGE10);
9770
+ throw lineRefusal("--all keeps the ticked Roadmap lines, so it needs --roadmap", USAGE12);
9496
9771
  return { roadmap, all };
9497
9772
  }
9498
9773
  function renderIssueList(kind, issues) {
@@ -9571,7 +9846,7 @@ async function listRoadmap(context, seams, all, filter) {
9571
9846
  });
9572
9847
  }
9573
9848
  async function listIssues(context, seams) {
9574
- expectNoArgument(context.args, USAGE10);
9849
+ expectNoArgument(context.args, USAGE12);
9575
9850
  const query = readIssueQuery(context.flags);
9576
9851
  const { tracker, data } = await resolveIssueTracker(context, seams);
9577
9852
  const refs = await onTracker(tracker, "list issues", () => tracker.find(query));
@@ -9590,7 +9865,7 @@ async function runIssueList(context, seams) {
9590
9865
  context.output.info(text);
9591
9866
  return;
9592
9867
  }
9593
- expectNoArgument(context.args, USAGE10);
9868
+ expectNoArgument(context.args, USAGE12);
9594
9869
  const filter = readIssueQuery(context.flags);
9595
9870
  const listed2 = await listRoadmap(context, seams, line.all, filter);
9596
9871
  if (context.outputMode === "json") {
@@ -9677,10 +9952,10 @@ function createIssueListCommand(seams = DEFAULT_ISSUE_SEAMS) {
9677
9952
  var list_default5 = createIssueListCommand();
9678
9953
 
9679
9954
  // src/commands/issue/move.ts
9680
- var USAGE11 = "rafa issue move <id> <state>";
9955
+ var USAGE13 = "rafa issue move <id> <state>";
9681
9956
  async function moveIssue(context, seams) {
9682
- const [id, word] = expectTwoArguments(context.args, USAGE11);
9683
- const state = readChoice(word, "The state", ISSUE_STATES, USAGE11);
9957
+ const [id, word] = expectTwoArguments(context.args, USAGE13);
9958
+ const state = readChoice(word, "The state", ISSUE_STATES, USAGE13);
9684
9959
  const { tracker, data } = await resolveIssueTracker(context, seams);
9685
9960
  const ref = issueRef(tracker, id);
9686
9961
  const moved = await onTracker(tracker, `move issue ${id} to ${state}`, () => tracker.transition(ref, state));
@@ -9739,7 +10014,7 @@ function createIssueMoveCommand(seams = DEFAULT_ISSUE_SEAMS) {
9739
10014
  var move_default = createIssueMoveCommand();
9740
10015
 
9741
10016
  // src/commands/issue/show.ts
9742
- var USAGE12 = "rafa issue show <id>";
10017
+ var USAGE14 = "rafa issue show <id>";
9743
10018
  var NO_PRIORITY = "needs-triage";
9744
10019
  function renderIssue(kind, issue) {
9745
10020
  const project = issue.project === null ? [] : [`Project: ${issue.project}`];
@@ -9761,7 +10036,7 @@ function renderIssue(kind, issue) {
9761
10036
  ];
9762
10037
  }
9763
10038
  async function showIssue(context, seams) {
9764
- const id = expectOneArgument(context.args, USAGE12);
10039
+ const id = expectOneArgument(context.args, USAGE14);
9765
10040
  const { tracker, data } = await resolveIssueTracker(context, seams);
9766
10041
  const issue = await onTracker(tracker, `read issue ${id}`, () => tracker.get(issueRef(tracker, id)));
9767
10042
  return { tracker: data, issue };
@@ -10050,8 +10325,8 @@ function projectRoot2(context) {
10050
10325
  throw new Error("rafa issue unblock runs inside a project, and was handed none");
10051
10326
  return context.project.root;
10052
10327
  }
10053
- function isYes(answer) {
10054
- return answer !== null && YES_ANSWERS2.includes(answer.trim().toLowerCase());
10328
+ function isYes(answer2) {
10329
+ return answer2 !== null && YES_ANSWERS2.includes(answer2.trim().toLowerCase());
10055
10330
  }
10056
10331
  function lazyPrompter2(open) {
10057
10332
  let prompter = null;
@@ -10151,7 +10426,7 @@ function createIssueUnblockCommand(seams = DEFAULT_UNBLOCK_SEAMS) {
10151
10426
  var unblock_default = createIssueUnblockCommand();
10152
10427
 
10153
10428
  // src/commands/loop/list.ts
10154
- var USAGE13 = "rafa loop list";
10429
+ var USAGE15 = "rafa loop list";
10155
10430
  function renderSessionList(list) {
10156
10431
  if (list.sessions.length === 0)
10157
10432
  return ["No running sessions."];
@@ -10161,7 +10436,7 @@ function renderSessionList(list) {
10161
10436
  ];
10162
10437
  }
10163
10438
  async function runList5(context, seams) {
10164
- expectNoArgument(context.args, USAGE13);
10439
+ expectNoArgument(context.args, USAGE15);
10165
10440
  const root = projectRoot(context);
10166
10441
  const sessions = readRecords(root, seams).filter(isLive).map((session) => {
10167
10442
  const checklist = readSessionChecklist(root, session);
@@ -10206,7 +10481,7 @@ function createLoopListCommand(seams = {}) {
10206
10481
  var list_default6 = createLoopListCommand();
10207
10482
 
10208
10483
  // src/commands/loop/pause.ts
10209
- var USAGE14 = "rafa loop pause [-s|--session-id=<id>]";
10484
+ var USAGE16 = "rafa loop pause [-s|--session-id=<id>]";
10210
10485
  function renderPause(result) {
10211
10486
  const { session } = result;
10212
10487
  if (!result.changed)
@@ -10215,8 +10490,8 @@ function renderPause(result) {
10215
10490
  return [when, " Nothing is marked. `rafa loop resume` goes on, and `rafa loop stop` ends the run."];
10216
10491
  }
10217
10492
  async function runPause(context, seams) {
10218
- expectNoArgument(context.args, USAGE14);
10219
- const { root, record } = pickSession(context, USAGE14, "live", seams);
10493
+ expectNoArgument(context.args, USAGE16);
10494
+ const { root, record } = pickSession(context, USAGE16, "live", seams);
10220
10495
  if (!isLive(record)) {
10221
10496
  throw refusal(`Session ${record.sessionId} reads ${record.state}: no run is left to pause.`);
10222
10497
  }
@@ -10256,7 +10531,7 @@ function createLoopPauseCommand(seams = {}) {
10256
10531
  var pause_default = createLoopPauseCommand();
10257
10532
 
10258
10533
  // src/commands/loop/resume.ts
10259
- var USAGE15 = "rafa loop resume [-s|--session-id=<id>]";
10534
+ var USAGE17 = "rafa loop resume [-s|--session-id=<id>]";
10260
10535
  function renderResume(result) {
10261
10536
  const { session } = result;
10262
10537
  if (!result.changed)
@@ -10264,8 +10539,8 @@ function renderResume(result) {
10264
10539
  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
10540
  }
10266
10541
  async function runResume(context, seams) {
10267
- expectNoArgument(context.args, USAGE15);
10268
- const { root, record } = pickSession(context, USAGE15, "live", seams);
10542
+ expectNoArgument(context.args, USAGE17);
10543
+ const { root, record } = pickSession(context, USAGE17, "live", seams);
10269
10544
  if (!isLive(record)) {
10270
10545
  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
10546
  }
@@ -10400,7 +10675,7 @@ var loopStart = Object.freeze({
10400
10675
  var start_default = endingWith(loopStart);
10401
10676
 
10402
10677
  // src/commands/loop/status.ts
10403
- var USAGE16 = "rafa loop status [-s|--session-id=<id>]";
10678
+ var USAGE18 = "rafa loop status [-s|--session-id=<id>]";
10404
10679
  var BLOCKED_TASK_LINE = /^- \[BLOCKED\] (.+)/;
10405
10680
  var NO_BLOCKER = "the line trails no blocker comment";
10406
10681
  function blockerAt(checklist, lineNum) {
@@ -10436,8 +10711,8 @@ function renderStatus(status) {
10436
10711
  ];
10437
10712
  }
10438
10713
  async function runStatus(context, seams) {
10439
- expectNoArgument(context.args, USAGE16);
10440
- const { root, record } = pickSession(context, USAGE16, "live-or-newest", seams);
10714
+ expectNoArgument(context.args, USAGE18);
10715
+ const { root, record } = pickSession(context, USAGE18, "live-or-newest", seams);
10441
10716
  const checklist = readSessionChecklist(root, record);
10442
10717
  const tasks = checklist === null ? null : countTasks(checklist.tasks);
10443
10718
  let eta = null;
@@ -10490,7 +10765,7 @@ function createLoopStatusCommand(seams = {}) {
10490
10765
  var status_default = createLoopStatusCommand();
10491
10766
 
10492
10767
  // src/commands/loop/stop.ts
10493
- var USAGE17 = "rafa loop stop [-s|--session-id=<id>]";
10768
+ var USAGE19 = "rafa loop stop [-s|--session-id=<id>]";
10494
10769
  function signalRun(record, interrupt) {
10495
10770
  try {
10496
10771
  interrupt(record.pid);
@@ -10543,8 +10818,8 @@ function renderStop(result) {
10543
10818
  ];
10544
10819
  }
10545
10820
  async function runStop(context, seams) {
10546
- expectNoArgument(context.args, USAGE17);
10547
- const { root, record } = pickSession(context, USAGE17, "live", seams);
10821
+ expectNoArgument(context.args, USAGE19);
10822
+ const { root, record } = pickSession(context, USAGE19, "live", seams);
10548
10823
  if (!isLive(record)) {
10549
10824
  throw refusal(`Session ${record.sessionId} reads ${record.state}: no run is left to stop.`);
10550
10825
  }
@@ -10595,7 +10870,7 @@ function createLoopStopCommand(seams = {}) {
10595
10870
  var stop_default = createLoopStopCommand();
10596
10871
 
10597
10872
  // src/commands/module/exec.ts
10598
- var USAGE18 = "rafa module exec <module> <action> [args] [flags]";
10873
+ var USAGE20 = "rafa module exec <module> <action> [args] [flags]";
10599
10874
  var execCommand = {
10600
10875
  name: "module exec",
10601
10876
  subject: "module",
@@ -10624,13 +10899,13 @@ var execCommand = {
10624
10899
  const mounts = context.registry.mounts();
10625
10900
  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
10901
  throw new CommandExit(1, `\u274C Expected a module and one of its actions; mounted: ${mounted}
10627
- Usage: ${USAGE18}`);
10902
+ Usage: ${USAGE20}`);
10628
10903
  }
10629
10904
  };
10630
10905
  var exec_default = Object.freeze(execCommand);
10631
10906
 
10632
10907
  // src/commands/module/list.ts
10633
- var USAGE19 = "rafa module list";
10908
+ var USAGE21 = "rafa module list";
10634
10909
  function sourceText(source) {
10635
10910
  const ref = source.ref === null ? "" : `@${source.ref}`;
10636
10911
  return `${source.kind} ${source.location}${ref}`;
@@ -10651,10 +10926,10 @@ function renderModuleList(list) {
10651
10926
  return ["Modules:", ...list.modules.flatMap(moduleLines)];
10652
10927
  }
10653
10928
  async function runList6(context, seams) {
10654
- expectNoArgument(context.args, USAGE19);
10929
+ expectNoArgument(context.args, USAGE21);
10655
10930
  const { project } = context;
10656
10931
  if (project === null)
10657
- throw new CommandExit(1, `\u274C ${USAGE19} runs inside a project`);
10932
+ throw new CommandExit(1, `\u274C ${USAGE21} runs inside a project`);
10658
10933
  let loaded;
10659
10934
  try {
10660
10935
  const resolved = loadConfig({ root: project.root, home: project.home });
@@ -11120,10 +11395,10 @@ var wrapped2 = wrapPhaseZeroCommand({
11120
11395
  var create_default2 = endingWith(wrapped2);
11121
11396
 
11122
11397
  // src/commands/plan/risk.ts
11123
- import { readFileSync as readFileSync18 } from "fs";
11398
+ import { readFileSync as readFileSync17 } from "fs";
11124
11399
  import { resolve as resolve11 } from "path";
11125
11400
  var COMMAND2 = "rafa plan risk";
11126
- var USAGE20 = "rafa plan risk [<plan>] [--strict]";
11401
+ var USAGE22 = "rafa plan risk [<plan>] [--strict]";
11127
11402
  var STRICT_HINT = `Type the plan first: ${COMMAND2} <plan> --strict`;
11128
11403
  function spawningRunners(root) {
11129
11404
  return { git: createGitRunner(root), gh: createGhRunner({ cwd: root }) };
@@ -11136,7 +11411,7 @@ function riskPlanPath(root, planDir, typed) {
11136
11411
  throw new CommandExit(1, `\u274C Plan file not found: ${path}`);
11137
11412
  const lookedFor = [...new Set([resolve11(root, planDir, DEFAULT_PLAN_FILE), resolve11(root, DEFAULT_PLAN_FILE)])];
11138
11413
  throw new CommandExit(1, `\u274C No plan named, and no default plan at ${lookedFor.join(" or ")}
11139
- Usage: ${USAGE20}`);
11414
+ Usage: ${USAGE22}`);
11140
11415
  }
11141
11416
  function riskLine(finding) {
11142
11417
  const line = finding.line === undefined ? "" : `:${String(finding.line)}`;
@@ -11148,7 +11423,7 @@ function strictRefusal(report2) {
11148
11423
  }
11149
11424
  async function readRisk(path, project, config, context, seams) {
11150
11425
  const makeRunners = seams.runners ?? spawningRunners;
11151
- return assessPlanRisk({ path, text: readFileSync18(path, "utf8") }, {
11426
+ return assessPlanRisk({ path, text: readFileSync17(path, "utf8") }, {
11152
11427
  repoRoot: project.root,
11153
11428
  home: project.home,
11154
11429
  settingSources: config.settingSources,
@@ -11200,7 +11475,7 @@ function createPlanRiskCommand(seams = {}) {
11200
11475
  outputs: ["text", "json"],
11201
11476
  run: async (context) => {
11202
11477
  const strict = readSwitch("strict", context.flags["strict"], STRICT_HINT);
11203
- const typed = expectAtMostOneArgument(context.args, USAGE20);
11478
+ const typed = expectAtMostOneArgument(context.args, USAGE22);
11204
11479
  const project = requireProject(context, COMMAND2);
11205
11480
  const config = resolveProjectConfig(project, COMMAND2, (message) => {
11206
11481
  context.output.warn(message);
@@ -11231,9 +11506,9 @@ function createPlanRiskCommand(seams = {}) {
11231
11506
  var risk_default = createPlanRiskCommand();
11232
11507
 
11233
11508
  // 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]";
11509
+ import { readFileSync as readFileSync18 } from "fs";
11510
+ import { join as join23 } from "path";
11511
+ var USAGE23 = "rafa plan show <stub> [--tracker]";
11237
11512
  var COMMAND3 = "rafa plan show";
11238
11513
  function readTrackerFlag(value) {
11239
11514
  if (value === undefined || value === false || value === "false")
@@ -11250,10 +11525,10 @@ function showPlan(plans, stub, tracker) {
11250
11525
  throw new CommandExit(1, `\u274C "${stub}" is no plan stub: a stub is letters, digits, ".", "_" and "-"`);
11251
11526
  }
11252
11527
  const name2 = planFileName(stub, tracker);
11253
- const file = join24(plans.path, name2);
11528
+ const file = join23(plans.path, name2);
11254
11529
  if (!isFile(file))
11255
- throw new CommandExit(1, missingText(stub, tracker, join24(plans.label, name2)));
11256
- const model = parsePlan(readFileSync19(file, "utf8"));
11530
+ throw new CommandExit(1, missingText(stub, tracker, join23(plans.label, name2)));
11531
+ const model = parsePlan(readFileSync18(file, "utf8"));
11257
11532
  const { header } = model;
11258
11533
  return {
11259
11534
  stub,
@@ -11276,7 +11551,7 @@ function taskLine(task) {
11276
11551
  return ` ${checkbox(task.status)} ${task.text}`;
11277
11552
  }
11278
11553
  function renderShownPlan(shown, dirLabel) {
11279
- const relative7 = join24(dirLabel, planFileName(shown.stub, shown.tracker));
11554
+ const relative7 = join23(dirLabel, planFileName(shown.stub, shown.tracker));
11280
11555
  const fileLabel = shown.tracker ? "Tracker" : "File";
11281
11556
  const lines2 = [`Plan: ${shown.stub}`, `${fileLabel}: ${relative7}`];
11282
11557
  if (shown.header.issue !== null)
@@ -11329,7 +11604,7 @@ var planShowCommand = {
11329
11604
  outputs: ["text", "json"],
11330
11605
  run: async (context) => {
11331
11606
  const tracker = readTrackerFlag(context.flags.tracker);
11332
- const stub = expectOneArgument(context.args, USAGE21);
11607
+ const stub = expectOneArgument(context.args, USAGE23);
11333
11608
  const plans = resolvePlansDir(requireProject(context, COMMAND3), COMMAND3, (message) => {
11334
11609
  context.output.warn(message);
11335
11610
  });
@@ -11468,7 +11743,7 @@ Run rafa pr list to see the open pull requests.`, usage2);
11468
11743
  }
11469
11744
 
11470
11745
  // src/commands/pr/current.ts
11471
- var USAGE22 = PR_USAGE.current;
11746
+ var USAGE24 = PR_USAGE.current;
11472
11747
  var SEPARATOR = " \u2014 ";
11473
11748
  function trimmedOrNull(value) {
11474
11749
  const trimmed = value.trim();
@@ -11499,9 +11774,9 @@ async function probeChecks(pulls, number) {
11499
11774
  }
11500
11775
  }
11501
11776
  async function readCurrent(context, seams) {
11502
- expectNoArguments(context.args, USAGE22);
11777
+ expectNoArguments(context.args, USAGE24);
11503
11778
  const pr = openPrContext(context, seams);
11504
- const pick = await pickPullRequest(pr, null, USAGE22);
11779
+ const pick = await pickPullRequest(pr, null, USAGE24);
11505
11780
  const summary = pick.summary;
11506
11781
  const probe = await probeChecks(pr.pulls, pick.number);
11507
11782
  const reading = {
@@ -11554,7 +11829,7 @@ function createPrCurrentCommand(seams = DEFAULT_PR_SEAMS) {
11554
11829
  var current_default = createPrCurrentCommand();
11555
11830
 
11556
11831
  // src/commands/pr/list.ts
11557
- var USAGE23 = PR_USAGE.list;
11832
+ var USAGE25 = PR_USAGE.list;
11558
11833
  var UNREADABLE2 = "?";
11559
11834
  var PROBE_LIMIT = 6;
11560
11835
  var TITLE_WIDTH = 60;
@@ -11655,7 +11930,7 @@ async function rowOf3(pulls, pull) {
11655
11930
  };
11656
11931
  }
11657
11932
  async function readList(context, seams, now) {
11658
- expectNoArguments(context.args, USAGE23);
11933
+ expectNoArguments(context.args, USAGE25);
11659
11934
  const pr = openPrContext(context, seams);
11660
11935
  const open = await onProvider("list the open pull requests", () => pr.pulls.list());
11661
11936
  const rows = await mapWithLimit(open, PROBE_LIMIT, (pull) => rowOf3(pr.pulls, pull));
@@ -11695,8 +11970,8 @@ function createPrListCommand(seams = DEFAULT_PR_SEAMS) {
11695
11970
  var list_default8 = createPrListCommand();
11696
11971
 
11697
11972
  // src/commands/pr/merge.ts
11698
- import { existsSync as existsSync9, readFileSync as readFileSync21 } from "fs";
11699
- import { join as join26 } from "path";
11973
+ import { existsSync as existsSync9, readFileSync as readFileSync20 } from "fs";
11974
+ import { join as join25 } from "path";
11700
11975
 
11701
11976
  // src/board/roadmap-tick.ts
11702
11977
  var PREFIX5 = "board roadmap";
@@ -11853,15 +12128,15 @@ import {
11853
12128
  copyFileSync as copyFileSync3,
11854
12129
  existsSync as existsSync8,
11855
12130
  mkdirSync as mkdirSync6,
11856
- readdirSync as readdirSync6,
11857
- readFileSync as readFileSync20,
12131
+ readdirSync as readdirSync5,
12132
+ readFileSync as readFileSync19,
11858
12133
  realpathSync as realpathSync5,
11859
12134
  renameSync,
11860
12135
  rmSync as rmSync2,
11861
- statSync as statSync13,
12136
+ statSync as statSync12,
11862
12137
  symlinkSync
11863
12138
  } from "fs";
11864
- import { basename as basename7, delimiter as delimiter2, dirname as dirname4, join as join25, relative as relative7, resolve as resolve12 } from "path";
12139
+ import { basename as basename7, delimiter as delimiter2, dirname as dirname4, join as join24, relative as relative7, resolve as resolve12 } from "path";
11865
12140
  var LINK_NAME = "rafa";
11866
12141
  var FORCE_FLAG = "--force";
11867
12142
  var EXIT_DONE = 0;
@@ -11923,19 +12198,19 @@ function runtimeRefusalLines(runtimeDir, version2) {
11923
12198
  }
11924
12199
  function listTrackers(repoRoot, planDir) {
11925
12200
  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));
12201
+ 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
12202
  }
11928
12203
  function openTrackers(repoRoot, planDir) {
11929
12204
  return listTrackers(repoRoot, planDir).flatMap((path) => {
11930
- const task = findNextTask(readFileSync20(join25(repoRoot, path), "utf8"));
12205
+ const task = findNextTask(readFileSync19(join24(repoRoot, path), "utf8"));
11931
12206
  return task ? [{ path, task }] : [];
11932
12207
  });
11933
12208
  }
11934
12209
  function readManifestVersion2(repoRoot) {
11935
- const manifest = JSON.parse(readFileSync20(join25(repoRoot, "package.json"), "utf8"));
12210
+ const manifest = JSON.parse(readFileSync19(join24(repoRoot, "package.json"), "utf8"));
11936
12211
  const record = typeof manifest === "object" && manifest !== null ? manifest : {};
11937
12212
  if (record["name"] !== name) {
11938
- throw new Error(`${join25(repoRoot, "package.json")} names ${JSON.stringify(record["name"])}, not ${name}: this is no rafa checkout`);
12213
+ throw new Error(`${join24(repoRoot, "package.json")} names ${JSON.stringify(record["name"])}, not ${name}: this is no rafa checkout`);
11939
12214
  }
11940
12215
  const version2 = record["version"];
11941
12216
  if (typeof version2 !== "string" || !VERSION_SHAPE.test(version2)) {
@@ -11946,10 +12221,10 @@ function readManifestVersion2(repoRoot) {
11946
12221
  function copyTree(from, to) {
11947
12222
  mkdirSync6(to, { recursive: true });
11948
12223
  let copied = 0;
11949
- const entries = readdirSync6(from, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
12224
+ const entries = readdirSync5(from, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
11950
12225
  for (const entry of entries) {
11951
- const source = join25(from, entry.name);
11952
- const target = join25(to, entry.name);
12226
+ const source = join24(from, entry.name);
12227
+ const target = join24(to, entry.name);
11953
12228
  if (entry.isDirectory()) {
11954
12229
  copied += copyTree(source, target);
11955
12230
  } else if (entry.isFile()) {
@@ -12044,8 +12319,8 @@ function installRuntime(seams, options = {}) {
12044
12319
  }
12045
12320
  function runInstall(seams, options) {
12046
12321
  const { repoRoot, home, log } = seams;
12047
- const runtimeRoot = join25(home, RUNTIME_SUBDIR);
12048
- const linkPath = join25(home, RAFA_BIN_DIR, LINK_NAME);
12322
+ const runtimeRoot = join24(home, RUNTIME_SUBDIR);
12323
+ const linkPath = join24(home, RAFA_BIN_DIR, LINK_NAME);
12049
12324
  log(`repo root: ${repoRoot}`);
12050
12325
  log(`runtime root: ${runtimeRoot}`);
12051
12326
  log(`link: ${linkPath}`);
@@ -12055,8 +12330,8 @@ function runInstall(seams, options) {
12055
12330
  const open = inStage("trackers", () => openTrackers(repoRoot, planDir));
12056
12331
  if (open.length > 0)
12057
12332
  return { kind: "refused", reason: "trackers", planDir, trackers: open };
12058
- const distDir = join25(repoRoot, "dist");
12059
- const runtimeDir = join25(runtimeRoot, version2);
12333
+ const distDir = join24(repoRoot, "dist");
12334
+ const runtimeDir = join24(runtimeRoot, version2);
12060
12335
  const installed = existsSync8(runtimeDir);
12061
12336
  if (installed && options.force !== true) {
12062
12337
  return { kind: "refused", reason: "runtime-exists", version: version2, runtimeDir };
@@ -12065,13 +12340,13 @@ function runInstall(seams, options) {
12065
12340
  const code = inStage("build", () => seams.build(repoRoot));
12066
12341
  if (code !== 0)
12067
12342
  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)}`);
12343
+ if (!existsSync8(join24(distDir, RUNTIME_ENTRY))) {
12344
+ throw new StageFailure("build", `the build exited 0 and left no ${join24(distDir, RUNTIME_ENTRY)}`);
12070
12345
  }
12071
12346
  log(installed ? `copying ${distDir} over ${runtimeDir}, replacing it whole` : `copying ${distDir} into ${runtimeDir}`);
12072
12347
  const copied = inStage("copy", () => replaceTree(distDir, runtimeDir));
12073
12348
  log(`copied ${copied} file(s)`);
12074
- const resolved = inStage("link", () => relink(linkPath, join25(runtimeDir, RUNTIME_ENTRY)));
12349
+ const resolved = inStage("link", () => relink(linkPath, join24(runtimeDir, RUNTIME_ENTRY)));
12075
12350
  log(`${linkPath} resolves to ${resolved}`);
12076
12351
  return { kind: "done", version: version2, runtimeDir, linkPath, resolved, copied };
12077
12352
  }
@@ -12086,7 +12361,7 @@ function inStage(stage, run) {
12086
12361
  }
12087
12362
  function entryNames(dir) {
12088
12363
  try {
12089
- return readdirSync6(dir);
12364
+ return readdirSync5(dir);
12090
12365
  } catch (err) {
12091
12366
  if (typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT")
12092
12367
  return [];
@@ -12097,7 +12372,7 @@ function replaceFile(source, target) {
12097
12372
  const temporary = temporaryName(target);
12098
12373
  try {
12099
12374
  copyFileSync3(source, temporary);
12100
- chmodSync(temporary, statSync13(source).mode & 4095);
12375
+ chmodSync(temporary, statSync12(source).mode & 4095);
12101
12376
  renameSync(temporary, target);
12102
12377
  } catch (err) {
12103
12378
  rmSync2(temporary, { force: true });
@@ -12105,7 +12380,7 @@ function replaceFile(source, target) {
12105
12380
  }
12106
12381
  }
12107
12382
  function temporaryName(path) {
12108
- return join25(dirname4(path), `.${basename7(path)}.snapshot-${process.pid}`);
12383
+ return join24(dirname4(path), `.${basename7(path)}.snapshot-${process.pid}`);
12109
12384
  }
12110
12385
 
12111
12386
  // src/commands/pr/merge-followups.ts
@@ -12281,8 +12556,8 @@ async function readUncheckedMerge(options) {
12281
12556
  }
12282
12557
  return Object.freeze({ workflowCount, reading, yes });
12283
12558
  }
12284
- function isYes2(answer) {
12285
- return answer !== null && YES_ANSWERS3.includes(answer.trim().toLowerCase());
12559
+ function isYes2(answer2) {
12560
+ return answer2 !== null && YES_ANSWERS3.includes(answer2.trim().toLowerCase());
12286
12561
  }
12287
12562
  async function confirmUncheckedMerge(unchecked, options) {
12288
12563
  for (const line of unchecked.reading.warning)
@@ -12315,7 +12590,7 @@ async function postUncheckedComment(pulls, number, unchecked, warn) {
12315
12590
  }
12316
12591
 
12317
12592
  // src/commands/pr/merge.ts
12318
- var USAGE24 = PR_USAGE.merge;
12593
+ var USAGE26 = PR_USAGE.merge;
12319
12594
  var REMOTE3 = "origin";
12320
12595
  var INDENT4 = " ";
12321
12596
  var YES_ANSWERS4 = ["y", "yes"];
@@ -12373,8 +12648,8 @@ function requireTerminal(seams, summary) {
12373
12648
  "Merge it without the question with --yes."
12374
12649
  ]);
12375
12650
  }
12376
- function isYes3(answer) {
12377
- return answer !== null && YES_ANSWERS4.includes(answer.trim().toLowerCase());
12651
+ function isYes3(answer2) {
12652
+ return answer2 !== null && YES_ANSWERS4.includes(answer2.trim().toLowerCase());
12378
12653
  }
12379
12654
  function prompterOf(seams) {
12380
12655
  return seams.openPrompter ?? (() => createLinePrompter(process.stdin, process.stderr));
@@ -12396,13 +12671,13 @@ function remoteHoldsBranch(git, branch, warn) {
12396
12671
  }
12397
12672
  function textOf(path) {
12398
12673
  try {
12399
- return readFileSync21(path, "utf8");
12674
+ return readFileSync20(path, "utf8");
12400
12675
  } catch {
12401
12676
  return "";
12402
12677
  }
12403
12678
  }
12404
12679
  function followUpsFor(pr, git) {
12405
- const facts = readPackageFacts(textOf(join26(pr.project.root, "package.json")));
12680
+ const facts = readPackageFacts(textOf(join25(pr.project.root, "package.json")));
12406
12681
  if (facts.version === null)
12407
12682
  return [];
12408
12683
  const tags = git(["tag", "--list", versionTag(facts.version)]);
@@ -12410,7 +12685,7 @@ function followUpsFor(pr, git) {
12410
12685
  version: facts.version,
12411
12686
  tagged: tags.ok && tags.stdout.trim() !== "",
12412
12687
  rafaCheckout: facts.rafaCheckout,
12413
- runtimeInstalled: existsSync9(join26(pr.project.home, RUNTIME_SUBDIR, facts.version))
12688
+ runtimeInstalled: existsSync9(join25(pr.project.home, RUNTIME_SUBDIR, facts.version))
12414
12689
  });
12415
12690
  }
12416
12691
  function openGh(pr, seams) {
@@ -12522,22 +12797,22 @@ async function commentIfUnchecked(context, pr, number, unchecked) {
12522
12797
  return posted.url;
12523
12798
  }
12524
12799
  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);
12800
+ const yes = readBooleanFlag(context.flags, "yes", USAGE26);
12801
+ const skipChecks = readBooleanFlag(context.flags, "skip-checks", USAGE26);
12802
+ const wanted = readMethodFlag(context.flags, USAGE26);
12803
+ const asked = readPullArgument(context.args, USAGE26);
12529
12804
  const pr = openPrContext(context, seams);
12530
12805
  const git = (seams.git ?? createGitRunner)(pr.project.root);
12531
12806
  const method = wanted ?? pr.mergeMethod;
12532
- const pick = await pickPullRequest(pr, asked, USAGE24);
12807
+ const pick = await pickPullRequest(pr, asked, USAGE26);
12533
12808
  const detail = await onProvider(`read pull request #${pick.number}`, () => pr.pulls.get(pick.number));
12534
12809
  if (detail === null) {
12535
- throw lineRefusal3(`No pull request #${pick.number} at ${pr.project.root}`, USAGE24);
12810
+ throw lineRefusal3(`No pull request #${pick.number} at ${pr.project.root}`, USAGE26);
12536
12811
  }
12537
12812
  const checks = await onProvider(`read the checks of #${pick.number}`, () => pr.pulls.checks(pick.number));
12538
12813
  refuseFromGit(git, detail, checks, skipChecks);
12539
12814
  const summary = summaryLine2(detail, method);
12540
- const answer = await askToMerge(context, pr, seams, { number: detail.number, summary, yes, skipChecks });
12815
+ const answer2 = await askToMerge(context, pr, seams, { number: detail.number, summary, yes, skipChecks });
12541
12816
  const answered3 = {
12542
12817
  number: detail.number,
12543
12818
  source: pick.source,
@@ -12552,9 +12827,9 @@ async function runMerge(context, seams) {
12552
12827
  followUps: [],
12553
12828
  roadmapTick: null,
12554
12829
  unblocked: null,
12555
- unchecked: uncheckedReport(answer.unchecked, null)
12830
+ unchecked: uncheckedReport(answer2.unchecked, null)
12556
12831
  };
12557
- if (!answer.go) {
12832
+ if (!answer2.go) {
12558
12833
  context.output.info("Nothing was merged.");
12559
12834
  return answered3;
12560
12835
  }
@@ -12563,7 +12838,7 @@ async function runMerge(context, seams) {
12563
12838
  throw refusal5([`\u274C ${pr.pulls.kind} would not merge #${detail.number}: ${outcome2.detail}`]);
12564
12839
  }
12565
12840
  context.output.info(`Merged #${detail.number} into ${detail.baseRefName} (${method}).`);
12566
- const commentUrl = await commentIfUnchecked(context, pr, detail.number, answer.unchecked);
12841
+ const commentUrl = await commentIfUnchecked(context, pr, detail.number, answer2.unchecked);
12567
12842
  const roadmapTick = await reportTick(context, pr, seams, detail);
12568
12843
  const remoteBranchPresent = remoteHoldsBranch(git, detail.headRefName, (message) => {
12569
12844
  context.output.warn(message);
@@ -12586,7 +12861,7 @@ async function runMerge(context, seams) {
12586
12861
  followUps,
12587
12862
  roadmapTick,
12588
12863
  unblocked,
12589
- unchecked: uncheckedReport(answer.unchecked, commentUrl)
12864
+ unchecked: uncheckedReport(answer2.unchecked, commentUrl)
12590
12865
  };
12591
12866
  }
12592
12867
  function createPrMergeCommand(seams = DEFAULT_MERGE_SEAMS) {
@@ -13088,7 +13363,7 @@ function readLastTriage(comments) {
13088
13363
  }
13089
13364
 
13090
13365
  // src/commands/pr/show.ts
13091
- var USAGE25 = PR_USAGE.show;
13366
+ var USAGE27 = PR_USAGE.show;
13092
13367
  var INDENT5 = " ";
13093
13368
  var SHORT_SHA = 7;
13094
13369
  function headLine4(detail) {
@@ -13186,12 +13461,12 @@ async function probe2(call) {
13186
13461
  }
13187
13462
  }
13188
13463
  async function readShow(context, seams) {
13189
- const asked = readPullArgument(context.args, USAGE25);
13464
+ const asked = readPullArgument(context.args, USAGE27);
13190
13465
  const pr = openPrContext(context, seams);
13191
- const pick = await pickPullRequest(pr, asked, USAGE25);
13466
+ const pick = await pickPullRequest(pr, asked, USAGE27);
13192
13467
  const detail = await onProvider(`read pull request #${pick.number}`, () => pr.pulls.get(pick.number));
13193
13468
  if (detail === null) {
13194
- throw lineRefusal3(`No pull request #${pick.number} in the repository at ${pr.project.root}`, USAGE25);
13469
+ throw lineRefusal3(`No pull request #${pick.number} in the repository at ${pr.project.root}`, USAGE27);
13195
13470
  }
13196
13471
  const checks = await probe2(() => pr.pulls.checks(pick.number));
13197
13472
  const comments = await probe2(() => pr.pulls.comments(pick.number));
@@ -14020,8 +14295,8 @@ function withTaskBudget(plan2, usd) {
14020
14295
  }
14021
14296
 
14022
14297
  // 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";
14298
+ import { existsSync as existsSync10, readFileSync as readFileSync21 } from "fs";
14299
+ import { dirname as dirname5, join as join26 } from "path";
14025
14300
  import { fileURLToPath as fileURLToPath2 } from "url";
14026
14301
  var MODULE_DIR2 = dirname5(fileURLToPath2(import.meta.url));
14027
14302
  var PINNED_PLANS_DIRNAME = "plans";
@@ -14038,8 +14313,8 @@ function hasPinnedPlan(triageClass) {
14038
14313
  function pinnedPlanCandidates(moduleDir, triageClass) {
14039
14314
  const name2 = pinnedPlanFileName(triageClass);
14040
14315
  return [
14041
- join27(moduleDir, PINNED_PLANS_DIRNAME, name2),
14042
- join27(moduleDir, name2)
14316
+ join26(moduleDir, PINNED_PLANS_DIRNAME, name2),
14317
+ join26(moduleDir, name2)
14043
14318
  ];
14044
14319
  }
14045
14320
  function readPinnedPlan(triageClass, lookup = {}) {
@@ -14051,7 +14326,7 @@ function readPinnedPlan(triageClass, lookup = {}) {
14051
14326
  if (found === undefined) {
14052
14327
  throw new Error(`The pinned resolve plan for ${triageClass} is missing: ` + `no file at ${candidates.join(" or ")}`);
14053
14328
  }
14054
- return readFileSync22(found, "utf8");
14329
+ return readFileSync21(found, "utf8");
14055
14330
  }
14056
14331
  var SLOT_PATTERN = /\{[A-Z][A-Z0-9_]*\}/g;
14057
14332
  var CONFLICT_SENTENCE_SLOT = "CONFLICT_SENTENCE";
@@ -14192,19 +14467,19 @@ function readAttemptRepeat(input) {
14192
14467
 
14193
14468
  // src/commands/pr/resolve-loop.ts
14194
14469
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
14195
- import { join as join28 } from "path";
14196
- var RESOLVE_SUBDIR = join28(".rafa", "resolve");
14470
+ import { join as join27 } from "path";
14471
+ var RESOLVE_SUBDIR = join27(".rafa", "resolve");
14197
14472
  var RUN_PREFIX = "pr-";
14198
14473
  var ATTEMPT_PREFIX = "attempt-";
14199
14474
  var LOOP_WORDS = Object.freeze(["loop", "start"]);
14200
14475
  var CHILD_OUTPUT = "text";
14201
14476
  function resolveRunDir(home, number, attempt3) {
14202
- return join28(home, RESOLVE_SUBDIR, `${RUN_PREFIX}${number}`, `${ATTEMPT_PREFIX}${attempt3}`);
14477
+ return join27(home, RESOLVE_SUBDIR, `${RUN_PREFIX}${number}`, `${ATTEMPT_PREFIX}${attempt3}`);
14203
14478
  }
14204
14479
  function writeResolvePlan(write) {
14205
14480
  const dir = resolveRunDir(write.home, write.number, write.attempt);
14206
14481
  mkdirSync7(dir, { recursive: true });
14207
- const path = join28(dir, pinnedPlanFileName(write.triageClass));
14482
+ const path = join27(dir, pinnedPlanFileName(write.triageClass));
14208
14483
  writeFileSync6(path, write.plan, "utf8");
14209
14484
  return path;
14210
14485
  }
@@ -14563,7 +14838,7 @@ async function runAttempts(run, detail, first) {
14563
14838
  }
14564
14839
 
14565
14840
  // src/commands/pr/triage.ts
14566
- var USAGE26 = PR_USAGE.triage;
14841
+ var USAGE28 = PR_USAGE.triage;
14567
14842
  var DEFAULT_MAX_ATTEMPTS = 2;
14568
14843
  var DETACHED_HEAD2 = "HEAD";
14569
14844
  var RESOLVED = false;
@@ -14619,7 +14894,7 @@ async function selectTargets(pr, warn, now, resolve13) {
14619
14894
  async function detailOf6(pr, number) {
14620
14895
  const detail = await onProvider(`read pull request #${number}`, () => pr.pulls.get(number));
14621
14896
  if (detail === null) {
14622
- throw lineRefusal3(`No pull request #${number} in the repository at ${pr.project.root}`, USAGE26);
14897
+ throw lineRefusal3(`No pull request #${number} in the repository at ${pr.project.root}`, USAGE28);
14623
14898
  }
14624
14899
  return detail;
14625
14900
  }
@@ -14714,14 +14989,14 @@ async function assessOne(options) {
14714
14989
  function refuseResolveWithoutComment(wantsResolve, wantsComment) {
14715
14990
  if (!wantsResolve || wantsComment)
14716
14991
  return;
14717
- throw lineRefusal3("--resolve writes the attempt count into the triage comment, and --no-comment writes none;" + " run one or the other", USAGE26);
14992
+ throw lineRefusal3("--resolve writes the attempt count into the triage comment, and --no-comment writes none;" + " run one or the other", USAGE28);
14718
14993
  }
14719
14994
  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);
14995
+ const wantsComment = readBooleanFlag(context.flags, "comment", USAGE28, true);
14996
+ const wantsResolve = readBooleanFlag(context.flags, "resolve", USAGE28, false);
14997
+ const maxAttempts = readMaxAttempts(context.flags, USAGE28);
14723
14998
  refuseResolveWithoutComment(wantsResolve, wantsComment);
14724
- const asked = readPullArgument(context.args, USAGE26);
14999
+ const asked = readPullArgument(context.args, USAGE28);
14725
15000
  const pr = openPrContext(context, seams);
14726
15001
  const git = (seams.git ?? createGitRunner)(pr.project.root);
14727
15002
  const permissions = (seams.permissions ?? ghPermissionsIn)(pr.project.root);
@@ -14854,7 +15129,7 @@ function createPrTriageCommand(seams = DEFAULT_TRIAGE_SEAMS) {
14854
15129
  var triage_default = createPrTriageCommand();
14855
15130
 
14856
15131
  // src/commands/pr/view.ts
14857
- var USAGE27 = PR_USAGE.view;
15132
+ var USAGE29 = PR_USAGE.view;
14858
15133
  function trimmedOrNull3(value) {
14859
15134
  const trimmed = value.trim();
14860
15135
  return trimmed === "" ? null : trimmed;
@@ -14864,9 +15139,9 @@ function renderView(number, url) {
14864
15139
  return url === null ? opened : `${opened}${SEPARATOR}${url}`;
14865
15140
  }
14866
15141
  async function runView2(context, seams) {
14867
- const asked = readPullArgument(context.args, USAGE27);
15142
+ const asked = readPullArgument(context.args, USAGE29);
14868
15143
  const pr = openPrContext(context, seams);
14869
- const pick = await pickPullRequest(pr, asked, USAGE27);
15144
+ const pick = await pickPullRequest(pr, asked, USAGE29);
14870
15145
  await onProvider(`open pull request #${pick.number} in the browser`, () => pr.pulls.browse(pick.number));
14871
15146
  const url = trimmedOrNull3(pick.summary?.url ?? "");
14872
15147
  return {
@@ -14921,7 +15196,7 @@ function createPrViewCommand(seams = DEFAULT_PR_SEAMS) {
14921
15196
  var view_default = createPrViewCommand();
14922
15197
 
14923
15198
  // src/commands/pr/wait.ts
14924
- var USAGE28 = PR_USAGE.wait;
15199
+ var USAGE30 = PR_USAGE.wait;
14925
15200
  var TIMEOUT_FLAG = "timeout";
14926
15201
  var DEFAULT_WAIT_TIMEOUT_MIN = DEFAULT_CI_TIMEOUT_MIN;
14927
15202
  var MS_PER_MIN = 60000;
@@ -14987,10 +15262,10 @@ function renderWait(reading) {
14987
15262
  `);
14988
15263
  }
14989
15264
  async function runWait(context, seams) {
14990
- const minutes = readTimeoutMinutes(context.flags, USAGE28);
14991
- const asked = readPullArgument(context.args, USAGE28);
15265
+ const minutes = readTimeoutMinutes(context.flags, USAGE30);
15266
+ const asked = readPullArgument(context.args, USAGE30);
14992
15267
  const pr = openPrContext(context, seams);
14993
- const pick = await pickPullRequest(pr, asked, USAGE28);
15268
+ const pick = await pickPullRequest(pr, asked, USAGE30);
14994
15269
  const timeoutMs = minutes * MS_PER_MIN;
14995
15270
  context.output.info(`Waiting for the checks of #${pick.number}, up to ${minutes} min.`);
14996
15271
  const waited = await waitForChecks({
@@ -15069,8 +15344,8 @@ function createPrWaitCommand(seams = DEFAULT_WAIT_SEAMS) {
15069
15344
  var wait_default = createPrWaitCommand();
15070
15345
 
15071
15346
  // 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";
15347
+ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync22 } from "fs";
15348
+ import { join as join28 } from "path";
15074
15349
  var RELEASE_STATUS_USAGE = "rafa release status [--plan=<stub>]";
15075
15350
  var UNREADABLE3 = "?";
15076
15351
  var NOTHING = "none";
@@ -15171,13 +15446,13 @@ function untaggedVersions(released, tags) {
15171
15446
  }
15172
15447
  function textOf2(path) {
15173
15448
  try {
15174
- return readFileSync23(path, "utf8");
15449
+ return readFileSync22(path, "utf8");
15175
15450
  } catch {
15176
15451
  return null;
15177
15452
  }
15178
15453
  }
15179
15454
  function readVersionFile(root, configured) {
15180
- const resolved = join29(root, configured);
15455
+ const resolved = join28(root, configured);
15181
15456
  const text = textOf2(resolved);
15182
15457
  if (text === null) {
15183
15458
  return { path: configured, version: null, problem: `the version file could not be read at ${resolved}` };
@@ -15194,7 +15469,7 @@ function readTags(git) {
15194
15469
  return { tags, latest: tags[0] ?? null, problem: null };
15195
15470
  }
15196
15471
  function readUntagged(root, configured, tags) {
15197
- const resolved = join29(root, configured);
15472
+ const resolved = join28(root, configured);
15198
15473
  const text = textOf2(resolved);
15199
15474
  if (text === null) {
15200
15475
  return {
@@ -15213,11 +15488,11 @@ function readBranch2(git) {
15213
15488
  return result.ok && branch !== "" && branch !== "HEAD" ? branch : null;
15214
15489
  }
15215
15490
  function planStubsUnder(root, planDir) {
15216
- const resolved = join29(root, planDir);
15491
+ const resolved = join28(root, planDir);
15217
15492
  if (!existsSync11(resolved))
15218
15493
  return [];
15219
15494
  try {
15220
- return planStubsFromFileNames(readdirSync7(resolved));
15495
+ return planStubsFromFileNames(readdirSync6(resolved));
15221
15496
  } catch {
15222
15497
  return [];
15223
15498
  }
@@ -15415,8 +15690,8 @@ function createReleaseStatusCommand(seams = DEFAULT_RELEASE_SEAMS) {
15415
15690
  var status_default2 = createReleaseStatusCommand();
15416
15691
 
15417
15692
  // src/commands/release/tag.ts
15418
- import { readFileSync as readFileSync24 } from "fs";
15419
- import { join as join30 } from "path";
15693
+ import { readFileSync as readFileSync23 } from "fs";
15694
+ import { join as join29 } from "path";
15420
15695
  var RELEASE_TAG_USAGE = "rafa release tag";
15421
15696
  var DEFAULT_RELEASE_BRANCH = "main";
15422
15697
  var DEFAULT_REGISTRY = "https://registry.npmjs.org";
@@ -15435,13 +15710,13 @@ function readBranch3(git) {
15435
15710
  }
15436
15711
  function textOf3(path) {
15437
15712
  try {
15438
- return readFileSync24(path, "utf8");
15713
+ return readFileSync23(path, "utf8");
15439
15714
  } catch {
15440
15715
  return null;
15441
15716
  }
15442
15717
  }
15443
15718
  function readVersion(root, configured) {
15444
- const resolved = join30(root, configured);
15719
+ const resolved = join29(root, configured);
15445
15720
  const text = textOf3(resolved);
15446
15721
  if (text === null) {
15447
15722
  return {
@@ -15455,7 +15730,7 @@ function readVersion(root, configured) {
15455
15730
  return version2 === null ? { path: configured, text, version: null, problem: `${resolved} declares no version this can read` } : { path: configured, text, version: version2, problem: null };
15456
15731
  }
15457
15732
  function readNewestRelease(root, configured) {
15458
- const resolved = join30(root, configured);
15733
+ const resolved = join29(root, configured);
15459
15734
  const text = textOf3(resolved);
15460
15735
  if (text === null) {
15461
15736
  return { path: configured, version: null, problem: `the changelog could not be read at ${resolved}` };
@@ -15676,14 +15951,14 @@ var roadmap_default = createRoadmapCommand();
15676
15951
 
15677
15952
  // src/commands/self-update.ts
15678
15953
  var DEFAULT_SELF_UPDATE_SEAMS = Object.freeze({ build: runBuild });
15679
- var USAGE29 = "rafa self-update [--force]";
15954
+ var USAGE31 = "rafa self-update [--force]";
15680
15955
  function readForceFlag(value) {
15681
15956
  if (value === undefined || value === false || value === "false")
15682
15957
  return false;
15683
15958
  if (value === true || value === "true")
15684
15959
  return true;
15685
15960
  throw new CommandExit(1, `\u274C --force takes no value, and read "${value}" as one
15686
- Usage: ${USAGE29}`);
15961
+ Usage: ${USAGE31}`);
15687
15962
  }
15688
15963
  function projectOf11(context) {
15689
15964
  if (context.project === null)
@@ -15691,7 +15966,7 @@ function projectOf11(context) {
15691
15966
  return context.project;
15692
15967
  }
15693
15968
  async function runSelfUpdate(context, seams) {
15694
- expectNoArgument(context.args, USAGE29);
15969
+ expectNoArgument(context.args, USAGE31);
15695
15970
  const force = readForceFlag(context.flags["force"]);
15696
15971
  const project = projectOf11(context);
15697
15972
  const info = (line) => context.output.info(line);
@@ -15749,17 +16024,17 @@ function createSelfUpdateCommand(seams = DEFAULT_SELF_UPDATE_SEAMS) {
15749
16024
  var self_update_default = createSelfUpdateCommand();
15750
16025
 
15751
16026
  // src/commands/skill/backfill.ts
15752
- import { statSync as statSync15 } from "fs";
15753
- import { join as join35, resolve as resolve15 } from "path";
16027
+ import { statSync as statSync14 } from "fs";
16028
+ import { join as join34, resolve as resolve15 } from "path";
15754
16029
 
15755
16030
  // src/backfill/backup.ts
15756
16031
  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";
16032
+ import { dirname as dirname6, isAbsolute as isAbsolute8, join as join31, relative as relative8, resolve as resolve13, sep as sep5 } from "path";
15758
16033
 
15759
16034
  // 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");
16035
+ import { readdirSync as readdirSync7, readFileSync as readFileSync24 } from "fs";
16036
+ import { join as join30 } from "path";
16037
+ var BACKFILL_PATH = join30(".rafa", "backfill");
15763
16038
  var PROPOSAL_FILE_PREFIX = "proposals-";
15764
16039
  var PROPOSAL_FILE_EXTENSION = ".yaml";
15765
16040
  var SHA256_PATTERN = /^[0-9a-f]{64}$/;
@@ -15785,7 +16060,7 @@ var PROPOSAL_FILE_HEADER = [
15785
16060
  ].join(`
15786
16061
  `);
15787
16062
  function proposalPath(dir, batch) {
15788
- return join31(dir, `${PROPOSAL_FILE_PREFIX}${String(batch).padStart(2, "0")}${PROPOSAL_FILE_EXTENSION}`);
16063
+ return join30(dir, `${PROPOSAL_FILE_PREFIX}${String(batch).padStart(2, "0")}${PROPOSAL_FILE_EXTENSION}`);
15789
16064
  }
15790
16065
  function isProposalFileName(name2) {
15791
16066
  return name2.startsWith(PROPOSAL_FILE_PREFIX) && name2.endsWith(PROPOSAL_FILE_EXTENSION);
@@ -15916,14 +16191,14 @@ function parseProposalFile(text) {
15916
16191
  function readProposalFiles(dir) {
15917
16192
  let names;
15918
16193
  try {
15919
- names = readdirSync8(dir);
16194
+ names = readdirSync7(dir);
15920
16195
  } catch {
15921
16196
  return [];
15922
16197
  }
15923
16198
  return names.filter((name2) => isProposalFileName(name2)).sort((left, right) => left.localeCompare(right)).map((name2) => {
15924
- const path = join31(dir, name2);
16199
+ const path = join30(dir, name2);
15925
16200
  try {
15926
- return { path, result: parseProposalFile(readFileSync25(path, "utf8")) };
16201
+ return { path, result: parseProposalFile(readFileSync24(path, "utf8")) };
15927
16202
  } catch (error) {
15928
16203
  return { path, result: unreadable(`the file cannot be read (${error instanceof Error ? error.message : String(error)})`) };
15929
16204
  }
@@ -15931,10 +16206,10 @@ function readProposalFiles(dir) {
15931
16206
  }
15932
16207
 
15933
16208
  // src/backfill/backup.ts
15934
- var BACKUP_PATH = join32(BACKFILL_PATH, "backup");
16209
+ var BACKUP_PATH = join31(BACKFILL_PATH, "backup");
15935
16210
  var BACKUP_KINDS = ["copied", "kept", "tracked", "outside", "missing"];
15936
16211
  function backupDirectory(base) {
15937
- return join32(base, BACKUP_PATH);
16212
+ return join31(base, BACKUP_PATH);
15938
16213
  }
15939
16214
  function isUnder(root, path) {
15940
16215
  const step = relative8(resolve13(root), resolve13(path));
@@ -15943,7 +16218,7 @@ function isUnder(root, path) {
15943
16218
  function backupPathFor(path, root, backupDir) {
15944
16219
  if (!isUnder(root, path))
15945
16220
  return null;
15946
- return join32(backupDir, relative8(resolve13(root), resolve13(path)));
16221
+ return join31(backupDir, relative8(resolve13(root), resolve13(path)));
15947
16222
  }
15948
16223
  function backupFile(path, options) {
15949
16224
  if (options.repoRoot !== null && isUnder(options.repoRoot, path)) {
@@ -15979,348 +16254,8 @@ function countBackups(results) {
15979
16254
  }
15980
16255
 
15981
16256
  // src/backfill/derive.ts
15982
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync7 } from "fs";
16257
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync7 } from "fs";
15983
16258
  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
16259
  var DERIVED_FIELDS = ["stack", "paths", "when_to_use"];
16325
16260
  function renderWhenToUse(trigger, prevents) {
16326
16261
  return `${sentenceEnded(trigger)} Prevents: ${prevents}`;
@@ -16445,7 +16380,7 @@ function planFile(entry, options) {
16445
16380
  }
16446
16381
  let original;
16447
16382
  try {
16448
- original = readFileSync26(entry.path, "utf8");
16383
+ original = readFileSync25(entry.path, "utf8");
16449
16384
  } catch (error) {
16450
16385
  return inert(entry, "skipped", `the file cannot be read (${error instanceof Error ? error.message : String(error)})`);
16451
16386
  }
@@ -16489,7 +16424,7 @@ function planDerivation(root, options) {
16489
16424
  function applyFile(action, options) {
16490
16425
  if (action.text === null || action.original === null)
16491
16426
  return action;
16492
- const current = readFileSync26(action.path, "utf8");
16427
+ const current = readFileSync25(action.path, "utf8");
16493
16428
  if (current !== action.original) {
16494
16429
  return {
16495
16430
  ...action,
@@ -16520,7 +16455,7 @@ function applyDerivation(plan2, options) {
16520
16455
  }
16521
16456
 
16522
16457
  // src/backfill/proposal-batch.ts
16523
- import { readFileSync as readFileSync27 } from "fs";
16458
+ import { readFileSync as readFileSync26 } from "fs";
16524
16459
  import { relative as relative9 } from "path";
16525
16460
 
16526
16461
  // src/demote/report.ts
@@ -16819,7 +16754,7 @@ function readCandidate(root, entry) {
16819
16754
  return null;
16820
16755
  let text;
16821
16756
  try {
16822
- text = readFileSync27(entry.path, "utf8");
16757
+ text = readFileSync26(entry.path, "utf8");
16823
16758
  } catch {
16824
16759
  return null;
16825
16760
  }
@@ -16925,8 +16860,8 @@ function parseSessionAnswer(stdout) {
16925
16860
  }
16926
16861
 
16927
16862
  // 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";
16863
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync27, writeFileSync as writeFileSync8 } from "fs";
16864
+ import { join as join32, resolve as resolve14 } from "path";
16930
16865
  var PROPOSAL_ACTION_KINDS = [
16931
16866
  "applied",
16932
16867
  "unchanged",
@@ -16947,47 +16882,47 @@ function unanswered(candidate, note) {
16947
16882
  note
16948
16883
  };
16949
16884
  }
16950
- function answerProblem(needs, answer) {
16885
+ function answerProblem(needs, answer2) {
16951
16886
  if (needs.includes("prevents")) {
16952
- if (answer.prevents === null)
16887
+ if (answer2.prevents === null)
16953
16888
  return "the answer carries no prevents";
16954
- if (answer.signal === null)
16889
+ if (answer2.signal === null)
16955
16890
  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 ")}`;
16891
+ if (!isSkillSignal(answer2.signal)) {
16892
+ return `the answer signal ${answer2.signal} is neither ${SKILL_SIGNALS.join(" nor ")}`;
16958
16893
  }
16959
16894
  }
16960
- if (needs.includes("trigger") && answer.trigger === null) {
16895
+ if (needs.includes("trigger") && answer2.trigger === null) {
16961
16896
  return "the answer carries no trigger sentence";
16962
16897
  }
16963
16898
  if (needs.includes("description")) {
16964
- if (answer.description === null)
16899
+ if (answer2.description === null)
16965
16900
  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`;
16901
+ if (countCharacters(answer2.description) >= DESCRIPTION_LIMIT) {
16902
+ return `the answer description is ${countCharacters(answer2.description)} characters, at or over the ${DESCRIPTION_LIMIT} cap`;
16968
16903
  }
16969
16904
  }
16970
16905
  return null;
16971
16906
  }
16972
- function proposalRow(candidate, answer) {
16973
- if (answer === undefined) {
16907
+ function proposalRow(candidate, answer2) {
16908
+ if (answer2 === undefined) {
16974
16909
  return unanswered(candidate, "the session answered nothing about this file");
16975
16910
  }
16976
- const problem2 = answerProblem(candidate.needs, answer);
16911
+ const problem2 = answerProblem(candidate.needs, answer2);
16977
16912
  if (problem2 !== null)
16978
16913
  return unanswered(candidate, problem2);
16979
16914
  const wants = (need) => candidate.needs.includes(need);
16980
- const signal = answer.signal;
16915
+ const signal = answer2.signal;
16981
16916
  return {
16982
16917
  path: candidate.relative,
16983
16918
  name: candidate.name,
16984
16919
  hash: candidate.hash,
16985
16920
  needs: candidate.needs,
16986
16921
  status: ANSWERED_ROW,
16987
- prevents: wants("prevents") ? answer.prevents : null,
16922
+ prevents: wants("prevents") ? answer2.prevents : null,
16988
16923
  signal: wants("prevents") && signal !== null && isSkillSignal(signal) ? signal : null,
16989
- trigger: wants("trigger") ? answer.trigger : null,
16990
- description: wants("description") ? answer.description : null,
16924
+ trigger: wants("trigger") ? answer2.trigger : null,
16925
+ description: wants("description") ? answer2.description : null,
16991
16926
  note: null
16992
16927
  };
16993
16928
  }
@@ -17075,7 +17010,7 @@ function writeRow(path, row2, original, options) {
17075
17010
  };
17076
17011
  }
17077
17012
  function applyRow(root, row2, options) {
17078
- const path = join33(root, ...row2.path.split("/"));
17013
+ const path = join32(root, ...row2.path.split("/"));
17079
17014
  if (row2.status === UNANSWERED_ROW) {
17080
17015
  return inert2(path, row2, "unanswered", row2.note ?? "the row carries no answer");
17081
17016
  }
@@ -17084,7 +17019,7 @@ function applyRow(root, row2, options) {
17084
17019
  }
17085
17020
  let original;
17086
17021
  try {
17087
- original = readFileSync28(path, "utf8");
17022
+ original = readFileSync27(path, "utf8");
17088
17023
  } catch {
17089
17024
  return inert2(path, row2, "refused", "the file the row names is gone");
17090
17025
  }
@@ -17112,7 +17047,7 @@ function applyProposals(files, root, options) {
17112
17047
  for (const file of files) {
17113
17048
  const refusal7 = fileRefusal(file, root);
17114
17049
  for (const row2 of file.rows) {
17115
- const action = refusal7 === null ? applyRow(root, row2, options) : inert2(join33(root, ...row2.path.split("/")), row2, "refused", refusal7);
17050
+ const action = refusal7 === null ? applyRow(root, row2, options) : inert2(join32(root, ...row2.path.split("/")), row2, "refused", refusal7);
17116
17051
  actions.push(action);
17117
17052
  if (row2.trigger !== null && action.kind !== "refused" && action.kind !== "unanswered") {
17118
17053
  triggers[row2.name] = row2.trigger;
@@ -17123,13 +17058,13 @@ function applyProposals(files, root, options) {
17123
17058
  }
17124
17059
 
17125
17060
  // 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";
17061
+ import { readdirSync as readdirSync8, readFileSync as readFileSync28, realpathSync as realpathSync6, statSync as statSync13 } from "fs";
17062
+ import { basename as basename9, dirname as dirname7, join as join33 } from "path";
17128
17063
  var SKILLS_DIRECTORY = "skills";
17129
17064
  var CLAUDE_DIRECTORY = ".claude";
17130
17065
  var AUTO_EXTRACTED_ORIGIN = "auto-extracted";
17131
- var DEMOTED_PATH = join34(".rafa", "demoted");
17132
- var INSTINCTS_PATH = join34(".rafa", "instincts");
17066
+ var DEMOTED_PATH = join33(".rafa", "demoted");
17067
+ var INSTINCTS_PATH = join33(".rafa", "instincts");
17133
17068
  var REPORT_FILE = "report.md";
17134
17069
  function realOrSelf(path) {
17135
17070
  try {
@@ -17152,19 +17087,19 @@ function resolveDemotionScope(dir, home) {
17152
17087
  if (basename9(claude) !== CLAUDE_DIRECTORY)
17153
17088
  return null;
17154
17089
  const base = dirname7(claude);
17155
- const demotedDir = join34(base, DEMOTED_PATH);
17090
+ const demotedDir = join33(base, DEMOTED_PATH);
17156
17091
  return {
17157
17092
  scope: samePath(base, home) ? "user" : "project",
17158
17093
  dir,
17159
17094
  base,
17160
17095
  demotedDir,
17161
- instinctsDir: join34(base, INSTINCTS_PATH),
17162
- reportPath: join34(demotedDir, REPORT_FILE)
17096
+ instinctsDir: join33(base, INSTINCTS_PATH),
17097
+ reportPath: join33(demotedDir, REPORT_FILE)
17163
17098
  };
17164
17099
  }
17165
17100
  function entryKind(path) {
17166
17101
  try {
17167
- const stats = statSync14(path);
17102
+ const stats = statSync13(path);
17168
17103
  if (stats.isFile())
17169
17104
  return "file";
17170
17105
  if (stats.isDirectory())
@@ -17176,7 +17111,7 @@ function entryKind(path) {
17176
17111
  }
17177
17112
  function visibleNames(dir) {
17178
17113
  try {
17179
- return readdirSync9(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
17114
+ return readdirSync8(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
17180
17115
  } catch {
17181
17116
  return [];
17182
17117
  }
@@ -17185,8 +17120,8 @@ function readSelected(absolute, path, entries) {
17185
17120
  let text;
17186
17121
  let mtime;
17187
17122
  try {
17188
- text = readFileSync29(absolute, "utf8");
17189
- mtime = statSync14(absolute).mtime.toISOString();
17123
+ text = readFileSync28(absolute, "utf8");
17124
+ mtime = statSync13(absolute).mtime.toISOString();
17190
17125
  } catch {
17191
17126
  return null;
17192
17127
  }
@@ -17201,14 +17136,14 @@ function selectsLearned(text, scope) {
17201
17136
  return origin === AUTO_EXTRACTED_ORIGIN;
17202
17137
  }
17203
17138
  function selectLearned(scope) {
17204
- const dir = join34(scope.dir, LEARNED_DIRECTORY);
17139
+ const dir = join33(scope.dir, LEARNED_DIRECTORY);
17205
17140
  if (entryKind(dir) !== "directory")
17206
17141
  return [];
17207
17142
  const selected = [];
17208
17143
  for (const name2 of visibleNames(dir)) {
17209
17144
  if (!name2.endsWith(MARKDOWN_EXTENSION) || name2 === MARKDOWN_EXTENSION)
17210
17145
  continue;
17211
- const absolute = join34(dir, name2);
17146
+ const absolute = join33(dir, name2);
17212
17147
  if (entryKind(absolute) !== "file")
17213
17148
  continue;
17214
17149
  const file = readSelected(absolute, `${LEARNED_DIRECTORY}/${name2}`, undefined);
@@ -17222,10 +17157,10 @@ function selectSkillFiles(scope) {
17222
17157
  for (const name2 of visibleNames(scope.dir)) {
17223
17158
  if (name2 === LEARNED_DIRECTORY)
17224
17159
  continue;
17225
- const skillDir = join34(scope.dir, name2);
17160
+ const skillDir = join33(scope.dir, name2);
17226
17161
  if (entryKind(skillDir) !== "directory")
17227
17162
  continue;
17228
- const absolute = join34(skillDir, SKILL_FILE);
17163
+ const absolute = join33(skillDir, SKILL_FILE);
17229
17164
  if (entryKind(absolute) !== "file")
17230
17165
  continue;
17231
17166
  const file = readSelected(absolute, `${name2}/${SKILL_FILE}`, visibleNames(skillDir));
@@ -17286,7 +17221,7 @@ Usage: ${BACKFILL_USAGE}`);
17286
17221
  }
17287
17222
  function isDirectory3(path) {
17288
17223
  try {
17289
- return statSync15(path).isDirectory();
17224
+ return statSync14(path).isDirectory();
17290
17225
  } catch {
17291
17226
  return false;
17292
17227
  }
@@ -17410,7 +17345,7 @@ function reviewedProposals(dir) {
17410
17345
  return read2.flatMap((entry) => entry.result.file === null ? [] : [entry.result.file]);
17411
17346
  }
17412
17347
  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("/"))));
17348
+ return files.flatMap((file) => file.status !== REVIEWED_FILE ? [] : file.rows.filter((row2) => row2.status === ANSWERED_ROW).map((row2) => join34(root, ...row2.path.split("/"))));
17414
17349
  }
17415
17350
  function runApply(context, scope, backfillDir, projectRoot3) {
17416
17351
  const options = checkOptions(context, projectRoot3);
@@ -17456,7 +17391,7 @@ async function runBackfill(context, seams) {
17456
17391
  const dir = readBackfillDirectory(context.args, seams.cwd);
17457
17392
  const projectRoot3 = readConsumerRoot(context.flags["project"], seams.cwd);
17458
17393
  const scope = backfillScopeOf(dir, projectOf12(context).home);
17459
- const backfillDir = join35(scope.base, BACKFILL_PATH);
17394
+ const backfillDir = join34(scope.base, BACKFILL_PATH);
17460
17395
  if (mode === "propose") {
17461
17396
  await runPropose(context, scope, backfillDir, seams);
17462
17397
  return;
@@ -17570,13 +17505,13 @@ function createSkillCheckCommand(seams = DEFAULT_CHECK_SEAMS) {
17570
17505
  var check_default3 = createSkillCheckCommand();
17571
17506
 
17572
17507
  // src/commands/skill/demote.ts
17573
- import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync31, statSync as statSync17, writeFileSync as writeFileSync10 } from "fs";
17508
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync30, statSync as statSync16, writeFileSync as writeFileSync10 } from "fs";
17574
17509
  import { dirname as dirname9, resolve as resolve16 } from "path";
17575
17510
 
17576
17511
  // 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";
17512
+ import { copyFileSync as copyFileSync5, existsSync as existsSync13, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, readdirSync as readdirSync9, readFileSync as readFileSync29, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync15, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
17578
17513
  import { tmpdir as tmpdir2 } from "os";
17579
- import { dirname as dirname8, join as join36 } from "path";
17514
+ import { dirname as dirname8, join as join35 } from "path";
17580
17515
  var DEMOTION_ACTION_KINDS = [
17581
17516
  "demoted",
17582
17517
  "kept",
@@ -17597,18 +17532,18 @@ function learnedSkillName(path) {
17597
17532
  return base.slice(0, -MARKDOWN_EXTENSION.length);
17598
17533
  }
17599
17534
  function sourcePath(scope, path) {
17600
- return join36(scope.dir, ...path.split("/"));
17535
+ return join35(scope.dir, ...path.split("/"));
17601
17536
  }
17602
17537
  function demotedPath(scope, path) {
17603
- return join36(scope.demotedDir, ...path.split("/"));
17538
+ return join35(scope.demotedDir, ...path.split("/"));
17604
17539
  }
17605
17540
  function promotedPath(scope, path) {
17606
- return join36(scope.dir, learnedSkillName(path), SKILL_FILE);
17541
+ return join35(scope.dir, learnedSkillName(path), SKILL_FILE);
17607
17542
  }
17608
17543
  function takenInstinctIds(dir) {
17609
17544
  let names;
17610
17545
  try {
17611
- names = readdirSync10(dir);
17546
+ names = readdirSync9(dir);
17612
17547
  } catch {
17613
17548
  return [];
17614
17549
  }
@@ -17616,7 +17551,7 @@ function takenInstinctIds(dir) {
17616
17551
  }
17617
17552
  function readText4(path) {
17618
17553
  try {
17619
- return statSync16(path).isFile() ? readFileSync30(path, "utf8") : null;
17554
+ return statSync15(path).isFile() ? readFileSync29(path, "utf8") : null;
17620
17555
  } catch {
17621
17556
  return null;
17622
17557
  }
@@ -17658,7 +17593,7 @@ function planKept(scope, row2, file) {
17658
17593
  };
17659
17594
  }
17660
17595
  function checkCandidate(dir, id, text, pathDirs) {
17661
- const path = join36(dir, `${id}${MARKDOWN_EXTENSION}`);
17596
+ const path = join35(dir, `${id}${MARKDOWN_EXTENSION}`);
17662
17597
  writeFileSync9(path, text, "utf8");
17663
17598
  const report3 = checkFile(path, "instinct", { projectRoot: null, pathDirs });
17664
17599
  return failureLines2(report3.issues);
@@ -17679,7 +17614,7 @@ function planDemoted(scope, row2, file, context) {
17679
17614
  if (failures.length > 0) {
17680
17615
  return inert3(row2.path, "observation", "refused", `the record ${id} fails the checker \u2014 ${failures.join("; ")}`);
17681
17616
  }
17682
- const destination = join36(scope.instinctsDir, `${id}${MARKDOWN_EXTENSION}`);
17617
+ const destination = join35(scope.instinctsDir, `${id}${MARKDOWN_EXTENSION}`);
17683
17618
  const kept = demotedPath(scope, row2.path);
17684
17619
  if (existsSync13(destination))
17685
17620
  return inert3(row2.path, "observation", "refused", `${destination} is already there`);
@@ -17715,7 +17650,7 @@ function planRow(scope, row2, context) {
17715
17650
  entries: undefined,
17716
17651
  absolute,
17717
17652
  hash,
17718
- mtime: statSync16(absolute).mtime.toISOString()
17653
+ mtime: statSync15(absolute).mtime.toISOString()
17719
17654
  };
17720
17655
  return verdict === "procedure" ? planKept(scope, row2, file) : planDemoted(scope, row2, file, context);
17721
17656
  }
@@ -17726,7 +17661,7 @@ function countActions(actions) {
17726
17661
  return counts;
17727
17662
  }
17728
17663
  function planDemotion(report3, scope, seams = DEFAULT_APPLY_SEAMS) {
17729
- const temp = mkdtempSync2(join36(tmpdir2(), "rafa-demote-"));
17664
+ const temp = mkdtempSync2(join35(tmpdir2(), "rafa-demote-"));
17730
17665
  const taken = [...takenInstinctIds(scope.instinctsDir)];
17731
17666
  try {
17732
17667
  const actions = report3.rows.map((row2) => planRow(scope, row2, { temp, taken, seams }));
@@ -17817,7 +17752,7 @@ Usage: ${DEMOTE_USAGE}`);
17817
17752
  }
17818
17753
  function isDirectory4(path) {
17819
17754
  try {
17820
- return statSync17(path).isDirectory();
17755
+ return statSync16(path).isDirectory();
17821
17756
  } catch {
17822
17757
  return false;
17823
17758
  }
@@ -17847,7 +17782,7 @@ function verdictLine(report3) {
17847
17782
  function previousReport(path, context) {
17848
17783
  if (!existsSync14(path))
17849
17784
  return null;
17850
- const parsed = parseDemotionReport(readFileSync31(path, "utf8"));
17785
+ const parsed = parseDemotionReport(readFileSync30(path, "utf8"));
17851
17786
  if (parsed.report !== null)
17852
17787
  return parsed.report;
17853
17788
  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(", ")}`);
@@ -17883,7 +17818,7 @@ function reviewedReport(scope) {
17883
17818
  if (!existsSync14(scope.reportPath)) {
17884
17819
  throw new CommandExit(1, `\u274C No report at ${scope.reportPath}; run "rafa skill demote ${scope.dir}" first, then review it`);
17885
17820
  }
17886
- const parsed = parseDemotionReport(readFileSync31(scope.reportPath, "utf8"));
17821
+ const parsed = parseDemotionReport(readFileSync30(scope.reportPath, "utf8"));
17887
17822
  if (parsed.report === null) {
17888
17823
  const lines2 = parsed.issues.map((issue2) => ` line ${String(issue2.line)} ${issue2.code}: ${issue2.message}`);
17889
17824
  throw new CommandExit(1, [`\u274C ${scope.reportPath} does not parse:`, ...lines2].join(`
@@ -17990,7 +17925,7 @@ var demote_default = createSkillDemoteCommand();
17990
17925
  // src/commands/skill/show.ts
17991
17926
  var DEFAULT_SKILL_SHOW_SEAMS = DEFAULT_SKILL_LIST_SEAMS;
17992
17927
  var COMMAND_NAME5 = "rafa skill show";
17993
- var USAGE30 = "rafa skill show <name> [--full]";
17928
+ var USAGE32 = "rafa skill show <name> [--full]";
17994
17929
  function unknownSkillMessage(name2, inventory) {
17995
17930
  const agent = findShown(inventory.records, "agent", name2);
17996
17931
  const hint = agent === null ? [] : [`An agent is named "${name2}" (${agent.source}): rafa agent show ${name2}`];
@@ -17998,7 +17933,7 @@ function unknownSkillMessage(name2, inventory) {
17998
17933
  `\u274C No skill is named "${name2}".`,
17999
17934
  ...hint,
18000
17935
  "Run `rafa skill list` to see every skill and where it comes from.",
18001
- `Usage: ${USAGE30}`
17936
+ `Usage: ${USAGE32}`
18002
17937
  ].join(`
18003
17938
  `);
18004
17939
  }
@@ -18014,8 +17949,8 @@ function projectOf14(context) {
18014
17949
  return context.project;
18015
17950
  }
18016
17951
  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);
17952
+ const full = readSwitch("full", context.flags["full"], `Type the name ahead of it: ${USAGE32}`);
17953
+ const name2 = expectOneArgument(context.args, USAGE32);
18019
17954
  const project = projectOf14(context);
18020
17955
  const { inventory, settingSources } = await projectInventory(project, context, seams, COMMAND_NAME5);
18021
17956
  const warnings = warningLines(inventory);
@@ -18432,7 +18367,7 @@ var CORE_SUBJECTS = Object.freeze([
18432
18367
  { name: "module", summary: "list the configured modules; run an action a module provides" },
18433
18368
  { name: "agent", summary: "copy an agent definition into the project; list what a session sees" },
18434
18369
  { 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" },
18370
+ { name: "instinct", summary: "check an instincts directory; list, show, flag and promote its records" },
18436
18371
  { name: "release", summary: "read the release state of the project; tag the release branch's HEAD" }
18437
18372
  ]);
18438
18373
  var CORE_COMMANDS = Object.freeze([
@@ -18480,6 +18415,8 @@ var CORE_COMMANDS = Object.freeze([
18480
18415
  check_default,
18481
18416
  list_default4,
18482
18417
  show_default2,
18418
+ flag_default,
18419
+ promote_default,
18483
18420
  status_default2,
18484
18421
  tag_default,
18485
18422
  status_default3,