@open-tomato/rafa 0.45.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +255 -23
  2. package/dist/PROMPT.md +18 -1
  3. package/dist/adapters/logger/settings.d.ts +132 -0
  4. package/dist/bugs/closest.d.ts +19 -0
  5. package/dist/bugs/fenced.d.ts +8 -0
  6. package/dist/bugs/places.d.ts +20 -0
  7. package/dist/bugs/record.d.ts +145 -0
  8. package/dist/bugs/title.d.ts +83 -0
  9. package/dist/bundled/agents/doc-updater.md +17 -3
  10. package/dist/bundled/agents/loop-implementer.md +14 -2
  11. package/dist/bundled/operators/skills/rafa-stretch-pit-stop/SKILL.md +10 -3
  12. package/dist/bundled/operators/skills/rafa-stretch-sweep/SKILL.md +5 -0
  13. package/dist/bundled/skills/dev-planner/SKILL.md +101 -18
  14. package/dist/cli.js +74726 -62960
  15. package/dist/config/entry.d.ts +119 -0
  16. package/dist/config/index.d.ts +36 -0
  17. package/dist/config/index.js +51 -0
  18. package/dist/config/shape.d.ts +232 -0
  19. package/dist/config-registry.d.ts +127 -0
  20. package/dist/config-schema-board-project.d.ts +157 -0
  21. package/dist/config-schema-bugs.d.ts +71 -0
  22. package/dist/config-schema-errors.d.ts +54 -0
  23. package/dist/config-schema-features.d.ts +64 -0
  24. package/dist/config-schema-hub.d.ts +150 -0
  25. package/dist/config-schema-issues.d.ts +95 -0
  26. package/dist/config-schema-logger.d.ts +91 -0
  27. package/dist/config-schema-loop-continue.d.ts +122 -0
  28. package/dist/config-schema-loop-retries.d.ts +94 -0
  29. package/dist/config-schema-release.d.ts +307 -0
  30. package/dist/config-schema-tests.d.ts +170 -0
  31. package/dist/config-schema-triage.d.ts +142 -0
  32. package/dist/config-schema-wrap-up.d.ts +96 -0
  33. package/dist/core/command/command.d.ts +228 -0
  34. package/dist/core/command/confirm.d.ts +67 -0
  35. package/dist/core/command/index.d.ts +112 -0
  36. package/dist/core/command/lazy.d.ts +54 -0
  37. package/dist/core/command/registry-types.d.ts +96 -0
  38. package/dist/core/command/running.d.ts +96 -0
  39. package/dist/core/command/spends.d.ts +39 -0
  40. package/dist/core/command/types.d.ts +92 -0
  41. package/dist/core/command/version.d.ts +4 -0
  42. package/dist/core/config/branch-template.d.ts +20 -0
  43. package/dist/core/config/config-items.d.ts +86 -0
  44. package/dist/core/config/config-load.d.ts +47 -0
  45. package/dist/core/config/config-origins.d.ts +57 -0
  46. package/dist/core/config/config-readers.d.ts +167 -0
  47. package/dist/core/config/config-schema.d.ts +207 -0
  48. package/dist/core/config/config-sections.d.ts +493 -0
  49. package/dist/core/config/config.d.ts +320 -0
  50. package/dist/core/config/core-section.d.ts +39 -0
  51. package/dist/core/config/dangerous.d.ts +58 -0
  52. package/dist/core/config/default-routing.d.ts +16 -0
  53. package/dist/core/config/index.d.ts +141 -0
  54. package/dist/core/config/scope.d.ts +42 -0
  55. package/dist/core/config/section.d.ts +206 -0
  56. package/dist/core/config/sections.d.ts +45 -0
  57. package/dist/core/config/standard-schema.d.ts +27 -0
  58. package/dist/core/git/commit.d.ts +232 -0
  59. package/dist/core/git/gh-runner.d.ts +24 -0
  60. package/dist/core/git/git.d.ts +22 -0
  61. package/dist/core/git/index.d.ts +85 -0
  62. package/dist/core/loop/claude.d.ts +388 -0
  63. package/dist/core/loop/hop-record.d.ts +52 -0
  64. package/dist/core/loop/index.d.ts +179 -0
  65. package/dist/core/loop/session-env.d.ts +20 -0
  66. package/dist/core/loop/session-record-parse.d.ts +63 -0
  67. package/dist/core/loop/sessions.d.ts +408 -0
  68. package/dist/core/loop/suite-failure.d.ts +25 -0
  69. package/dist/core/output/active.d.ts +100 -0
  70. package/dist/core/output/stream.d.ts +20 -0
  71. package/dist/core/output/text.d.ts +55 -0
  72. package/dist/core/plan/block-reader.d.ts +46 -0
  73. package/dist/core/plan/blocks.d.ts +139 -0
  74. package/dist/core/plan/declaration.d.ts +366 -0
  75. package/dist/core/plan/plan-stamp.d.ts +75 -0
  76. package/dist/core/runtime/identity.d.ts +21 -0
  77. package/dist/core/runtime/index.d.ts +46 -0
  78. package/dist/effort/store/bring-forward.d.ts +131 -0
  79. package/dist/effort/store/check-rows.d.ts +31 -0
  80. package/dist/effort/store/commit-stats.d.ts +42 -0
  81. package/dist/effort/store/copy.d.ts +35 -0
  82. package/dist/effort/store/development-build.d.ts +105 -0
  83. package/dist/effort/store/effort-levels.d.ts +13 -0
  84. package/dist/effort/store/findings.d.ts +214 -0
  85. package/dist/effort/store/fix-schema.d.ts +184 -0
  86. package/dist/effort/store/index.js +10 -7
  87. package/dist/effort/store/location.d.ts +44 -0
  88. package/dist/effort/store/merge-commit-gaps.d.ts +68 -0
  89. package/dist/effort/store/merge-conflicts.d.ts +91 -0
  90. package/dist/effort/store/merge-rules.d.ts +82 -0
  91. package/dist/effort/store/merge-store.d.ts +211 -0
  92. package/dist/effort/store/merge-union.d.ts +92 -0
  93. package/dist/effort/store/migrate.d.ts +146 -0
  94. package/dist/effort/store/migrations.d.ts +92 -0
  95. package/dist/effort/store/ndjson-files.d.ts +114 -0
  96. package/dist/effort/store/origins.d.ts +116 -0
  97. package/dist/effort/store/plan-stubs.d.ts +79 -0
  98. package/dist/effort/store/rebuild-aside.d.ts +172 -0
  99. package/dist/effort/store/schema-plan.d.ts +102 -0
  100. package/dist/effort/store/session-row-types.d.ts +64 -0
  101. package/dist/effort/store/settings.d.ts +13 -0
  102. package/dist/effort/store/sqlite.d.ts +340 -0
  103. package/dist/effort/store/store-generation.d.ts +17 -0
  104. package/dist/effort/store/store-identity.d.ts +220 -0
  105. package/dist/effort/store/store-meta.d.ts +305 -0
  106. package/dist/effort/store/store-replaced.d.ts +72 -0
  107. package/dist/effort/store/types.d.ts +223 -0
  108. package/dist/errors/codes.d.ts +56 -0
  109. package/dist/errors/rafa-codes.d.ts +36 -0
  110. package/dist/index-2a7nb3an.js +125 -0
  111. package/dist/{index-r28fzsvc.js → index-39kbcw68.js} +350 -165
  112. package/dist/{index-nv34ptht.js → index-77ajfffn.js} +14 -9
  113. package/dist/index-cy98y87p.js +2597 -0
  114. package/dist/index-gqz4jn6j.js +13447 -0
  115. package/dist/index-gvek4r8m.js +710 -0
  116. package/dist/index-j4k2vdz3.js +1125 -0
  117. package/dist/index-jh1r4kcn.js +1067 -0
  118. package/dist/{index-mgh2s9bj.js → index-ykggr043.js} +58 -455
  119. package/dist/index-z1w83f81.js +4 -0
  120. package/dist/index.js +14715 -21516
  121. package/dist/learning/index.js +5 -6
  122. package/dist/plan/index.js +12 -11
  123. package/dist/plan-prompt.md +3 -1
  124. package/dist/ports/index.d.ts +732 -0
  125. package/dist/ports/learning.d.ts +101 -0
  126. package/dist/ports/log-level.d.ts +13 -0
  127. package/dist/ports/spec-review.d.ts +66 -0
  128. package/dist/pr/checks.d.ts +133 -0
  129. package/dist/pr/types.d.ts +422 -0
  130. package/dist/ready-4f8edezt.js +2016 -0
  131. package/dist/release-templates/release-bot-fragment.yml +153 -0
  132. package/dist/release-templates/release-publish.yml +110 -0
  133. package/dist/release-templates/release-settle.yml +122 -0
  134. package/dist/release-templates/release-tag.yml +102 -0
  135. package/dist/report/parse.d.ts +415 -0
  136. package/dist/schema/project-id.d.ts +79 -0
  137. package/dist/schema/tiers.d.ts +107 -0
  138. package/package.json +41 -3
  139. package/dist/index-hf2k497d.js +0 -16
  140. package/dist/index-nsr78ct2.js +0 -8219
@@ -1,11 +1,12 @@
1
1
  // @bun
2
2
  import {
3
3
  activeOutput,
4
- isStampableStub,
4
+ isStampableStub
5
+ } from "./index-2a7nb3an.js";
6
+ import {
5
7
  messageOf,
6
- parseTaskDeclaration,
7
- readRafaBlocks
8
- } from "./index-mgh2s9bj.js";
8
+ parseTaskDeclaration
9
+ } from "./index-ykggr043.js";
9
10
  // src/preflight/prerequisites-md.ts
10
11
  import { basename, dirname, join } from "path";
11
12
  var SECTION_AUTO_RE = /\[auto\]/i;
@@ -390,14 +391,341 @@ async function runPreflight(items, options) {
390
391
  knownMissing: Object.freeze(knownMissing)
391
392
  });
392
393
  }
393
- // src/utils/tracker.ts
394
- import fs from "fs";
394
+ // packages/rafa/src/core/plan/blocks.ts
395
+ var RAFA_BLOCK_KINDS = [
396
+ "plan",
397
+ "context",
398
+ "stage-context",
399
+ "report"
400
+ ];
401
+ var RAFA_PREFIX = "rafa:";
402
+ var FENCE_RUN = /^( {0,3})(`{3,}|~{3,})/;
403
+ var CLOSING_FENCE = /^ {0,3}(`{3,}|~{3,})[ \t]*$/;
404
+ function isRafaBlockKind(kind) {
405
+ return RAFA_BLOCK_KINDS.includes(kind);
406
+ }
407
+ function linesOf(markdown) {
408
+ const lines = markdown.split(`
409
+ `);
410
+ if (lines[lines.length - 1] === "")
411
+ lines.pop();
412
+ return lines.map((line) => line.endsWith("\r") ? line.slice(0, -1) : line);
413
+ }
414
+ function kindOf(info) {
415
+ const word = info.trim().split(/\s+/)[0] ?? "";
416
+ return word.startsWith(RAFA_PREFIX) ? word.slice(RAFA_PREFIX.length) : null;
417
+ }
418
+ function openingFence(line) {
419
+ const match = FENCE_RUN.exec(line);
420
+ const opener = match?.[0];
421
+ const indent = match?.[1];
422
+ const run = match?.[2];
423
+ if (opener === undefined || indent === undefined || run === undefined) {
424
+ return null;
425
+ }
426
+ const marker = run.charAt(0);
427
+ const info = line.slice(opener.length);
428
+ if (marker === "`" && info.includes("`"))
429
+ return null;
430
+ return { marker, length: run.length, indent: indent.length, kind: kindOf(info) };
431
+ }
432
+ function closes(line, fence) {
433
+ const run = CLOSING_FENCE.exec(line)?.[1];
434
+ return run !== undefined && run.charAt(0) === fence.marker && run.length >= fence.length;
435
+ }
436
+ function closingIndex(lines, from, fence) {
437
+ for (let index = from;index < lines.length; index += 1) {
438
+ if (closes(lines[index] ?? "", fence))
439
+ return index;
440
+ }
441
+ return lines.length;
442
+ }
443
+ function dedent(line, indent) {
444
+ let cut = 0;
445
+ while (cut < indent && line.charAt(cut) === " ")
446
+ cut += 1;
447
+ return line.slice(cut);
448
+ }
449
+ function readRafaBlocks(markdown) {
450
+ const lines = linesOf(markdown);
451
+ const blocks = [];
452
+ let index = 0;
453
+ while (index < lines.length) {
454
+ const fence = openingFence(lines[index] ?? "");
455
+ if (fence === null) {
456
+ index += 1;
457
+ continue;
458
+ }
459
+ const closing = closingIndex(lines, index + 1, fence);
460
+ const closed = closing < lines.length;
461
+ if (fence.kind !== null) {
462
+ const body = lines.slice(index + 1, closing).map((line) => dedent(line, fence.indent)).join(`
463
+ `);
464
+ const last = closed ? closing + 1 : lines.length;
465
+ blocks.push({ kind: fence.kind, body, span: { first: index + 1, last }, closed });
466
+ }
467
+ index = closing + 1;
468
+ }
469
+ return blocks;
470
+ }
471
+ // packages/rafa/src/report/parse.ts
472
+ var REPORT_STATUSES = ["done", "blocked"];
473
+ var FINDING_KINDS = ["gotcha", "pattern", "location", "skill-suggestion"];
474
+ var FINDING_SIGNALS = ["loud", "silent"];
475
+ var FINDING_DOMAINS = [
476
+ "code-style",
477
+ "testing",
478
+ "git",
479
+ "debugging",
480
+ "workflow",
481
+ "security",
482
+ "general-best-practices"
483
+ ];
484
+ var CHANGE_LEVELS = ["patch", "minor", "major", "none"];
485
+ var BUG_KINDS = ["bug", "own-fallout", "own-gap", "convention", "docs", "machine"];
486
+ var DEFAULT_BUG_KIND = "bug";
487
+ var REPORT_KIND = "report";
488
+ var REQUIRED = true;
489
+ var OPTIONAL = false;
490
+ var REPORT_KEYS = [
491
+ "status",
492
+ "feedback",
493
+ "findings",
494
+ "skills_used",
495
+ "blockers",
496
+ "out_of_scope_bugs",
497
+ "changes",
498
+ "stale_docs"
499
+ ];
500
+ var FINDING_KEYS = [
501
+ "trigger",
502
+ "kind",
503
+ "what",
504
+ "cause",
505
+ "resolution",
506
+ "artifact",
507
+ "signal",
508
+ "domain"
509
+ ];
510
+ var BLOCKER_KEYS = ["what", "artifact"];
511
+ var BUG_KEYS = ["what", "artifact", "security", "kind", "module", "action", "reproduce", "cause"];
512
+ var CHANGE_KEYS = ["level", "area", "summary"];
513
+ var STALE_DOC_KEYS = ["where", "what"];
514
+ function isMapping(value) {
515
+ return typeof value === "object" && value !== null && !Array.isArray(value);
516
+ }
517
+ function isOneOf(choices, value) {
518
+ return choices.includes(value);
519
+ }
520
+ function describeValue(value) {
521
+ if (typeof value === "string")
522
+ return JSON.stringify(value);
523
+ if (value === null)
524
+ return "nothing";
525
+ if (Array.isArray(value))
526
+ return "a list";
527
+ if (typeof value === "object")
528
+ return "a mapping";
529
+ return `the ${typeof value} ${String(value)}`;
530
+ }
531
+ function messageOf2(error) {
532
+ return error instanceof Error ? error.message : String(error);
533
+ }
534
+ function reportIssue(reason, field, text) {
535
+ return { reason, field, text };
536
+ }
537
+ function absent(reason, block, text) {
538
+ return { present: false, reason, block, text };
539
+ }
540
+ function scopeOf(mapping, keys, prefix, issues) {
541
+ const fields = new Map;
542
+ const extras = [];
543
+ for (const [key, value] of Object.entries(mapping)) {
544
+ if (keys.includes(key))
545
+ fields.set(key, value);
546
+ else
547
+ extras.push({ key, value });
548
+ }
549
+ return { fields, extras, prefix, issues };
550
+ }
551
+ function valueOf(scope, key, required) {
552
+ const value = scope.fields.get(key) ?? null;
553
+ if (value === null && required) {
554
+ const field = `${scope.prefix}${key}`;
555
+ scope.issues.push(reportIssue("missing-field", field, `${field} is missing`));
556
+ }
557
+ return value;
558
+ }
559
+ function unusable(scope, key, why) {
560
+ const field = `${scope.prefix}${key}`;
561
+ scope.issues.push(reportIssue("unusable-field", field, `${field} ${why}`));
562
+ return null;
563
+ }
564
+ function stringProblem(value) {
565
+ if (typeof value !== "string")
566
+ return `is ${describeValue(value)}, not a string; quote it`;
567
+ if (value.trim().length === 0)
568
+ return "is blank";
569
+ return null;
570
+ }
571
+ function stringField(scope, key, required) {
572
+ const value = valueOf(scope, key, required);
573
+ if (value === null)
574
+ return null;
575
+ const problem = stringProblem(value);
576
+ return problem === null ? value : unusable(scope, key, problem);
577
+ }
578
+ function choiceField(scope, key, choices, required) {
579
+ const value = valueOf(scope, key, required);
580
+ if (value === null || isOneOf(choices, value))
581
+ return value;
582
+ return unusable(scope, key, `is ${describeValue(value)}, not one of ${choices.join(", ")}`);
583
+ }
584
+ function booleanField(scope, key, required) {
585
+ const value = valueOf(scope, key, required);
586
+ if (value === null || typeof value === "boolean")
587
+ return value;
588
+ return unusable(scope, key, `is ${describeValue(value)}, not true or false; write it unquoted`);
589
+ }
590
+ function listField(scope, key, readEntry) {
591
+ const value = valueOf(scope, key, OPTIONAL);
592
+ if (value === null)
593
+ return [];
594
+ if (!Array.isArray(value)) {
595
+ unusable(scope, key, `is ${describeValue(value)}, not a list`);
596
+ return [];
597
+ }
598
+ const entries = [];
599
+ const items = value;
600
+ for (const [index, item] of items.entries()) {
601
+ const entry = readEntry(item, `${scope.prefix}${key}[${index}]`, scope.issues);
602
+ if (entry !== null)
603
+ entries.push(entry);
604
+ }
605
+ return entries;
606
+ }
607
+ function entryScope(item, field, keys, issues) {
608
+ if (isMapping(item))
609
+ return scopeOf(item, keys, `${field}.`, issues);
610
+ const text = `${field} is ${describeValue(item)}, not a mapping of ${keys.join(", ")}; dropped`;
611
+ issues.push(reportIssue("unusable-field", field, text));
612
+ return null;
613
+ }
614
+ function readSkill(item, field, issues) {
615
+ const problem = stringProblem(item);
616
+ if (problem === null)
617
+ return item;
618
+ issues.push(reportIssue("unusable-field", field, `${field} ${problem}; dropped`));
619
+ return null;
620
+ }
621
+ function readFinding(item, field, issues) {
622
+ const scope = entryScope(item, field, FINDING_KEYS, issues);
623
+ if (scope === null)
624
+ return null;
625
+ return {
626
+ trigger: stringField(scope, "trigger", REQUIRED),
627
+ kind: choiceField(scope, "kind", FINDING_KINDS, REQUIRED),
628
+ what: stringField(scope, "what", REQUIRED),
629
+ cause: stringField(scope, "cause", OPTIONAL),
630
+ resolution: stringField(scope, "resolution", OPTIONAL),
631
+ artifact: stringField(scope, "artifact", OPTIONAL),
632
+ signal: choiceField(scope, "signal", FINDING_SIGNALS, REQUIRED),
633
+ domain: choiceField(scope, "domain", FINDING_DOMAINS, OPTIONAL),
634
+ extras: scope.extras
635
+ };
636
+ }
637
+ function readBlocker(item, field, issues) {
638
+ const scope = entryScope(item, field, BLOCKER_KEYS, issues);
639
+ if (scope === null)
640
+ return null;
641
+ return {
642
+ what: stringField(scope, "what", REQUIRED),
643
+ artifact: stringField(scope, "artifact", OPTIONAL),
644
+ extras: scope.extras
645
+ };
646
+ }
647
+ function readBug(item, field, issues) {
648
+ const scope = entryScope(item, field, BUG_KEYS, issues);
649
+ if (scope === null)
650
+ return null;
651
+ return {
652
+ what: stringField(scope, "what", REQUIRED),
653
+ artifact: stringField(scope, "artifact", OPTIONAL),
654
+ security: booleanField(scope, "security", REQUIRED),
655
+ kind: choiceField(scope, "kind", BUG_KINDS, OPTIONAL) ?? DEFAULT_BUG_KIND,
656
+ module: stringField(scope, "module", OPTIONAL),
657
+ action: stringField(scope, "action", OPTIONAL),
658
+ reproduce: stringField(scope, "reproduce", OPTIONAL),
659
+ cause: stringField(scope, "cause", OPTIONAL),
660
+ extras: scope.extras
661
+ };
662
+ }
663
+ function readChange(item, field, issues) {
664
+ const scope = entryScope(item, field, CHANGE_KEYS, issues);
665
+ if (scope === null)
666
+ return null;
667
+ return {
668
+ level: choiceField(scope, "level", CHANGE_LEVELS, REQUIRED),
669
+ area: stringField(scope, "area", OPTIONAL),
670
+ summary: stringField(scope, "summary", REQUIRED),
671
+ extras: scope.extras
672
+ };
673
+ }
674
+ function readStaleDoc(item, field, issues) {
675
+ const scope = entryScope(item, field, STALE_DOC_KEYS, issues);
676
+ if (scope === null)
677
+ return null;
678
+ const where = stringField(scope, "where", OPTIONAL);
679
+ const what = stringField(scope, "what", REQUIRED);
680
+ if (what === null)
681
+ return null;
682
+ return { where, what, extras: scope.extras };
683
+ }
684
+ function readReport(document, issues) {
685
+ const scope = scopeOf(document, REPORT_KEYS, "", issues);
686
+ return {
687
+ status: choiceField(scope, "status", REPORT_STATUSES, REQUIRED),
688
+ feedback: stringField(scope, "feedback", OPTIONAL),
689
+ findings: listField(scope, "findings", readFinding),
690
+ skillsUsed: listField(scope, "skills_used", readSkill),
691
+ blockers: listField(scope, "blockers", readBlocker),
692
+ outOfScopeBugs: listField(scope, "out_of_scope_bugs", readBug),
693
+ changes: listField(scope, "changes", readChange),
694
+ staleDocs: listField(scope, "stale_docs", readStaleDoc),
695
+ extras: scope.extras
696
+ };
697
+ }
698
+ function parseReport(output) {
699
+ const reports = readRafaBlocks(output).filter((block2) => block2.kind === REPORT_KIND);
700
+ const block = reports.at(-1);
701
+ if (block === undefined) {
702
+ return absent("no-block", null, "the session output holds no rafa:report block");
703
+ }
704
+ const line = block.span.first;
705
+ if (!block.closed) {
706
+ return absent("unclosed-block", block, `rafa:report block at line ${line} is never closed, so its body may have been cut short ` + "and is not read");
707
+ }
708
+ let document;
709
+ try {
710
+ document = Bun.YAML.parse(block.body);
711
+ } catch (error) {
712
+ const text = `rafa:report block at line ${line} is not valid YAML (${messageOf2(error)})`;
713
+ return absent("malformed-block", block, text);
714
+ }
715
+ if (!isMapping(document)) {
716
+ const text = `rafa:report block at line ${line} holds ${describeValue(document)}, ` + "not a mapping of report fields";
717
+ return absent("malformed-block", block, text);
718
+ }
719
+ const issues = [];
720
+ const report = readReport(document, issues);
721
+ return { present: true, report, block, issues };
722
+ }
723
+ // packages/rafa/src/core/plan/blocker-comment.ts
395
724
  var BLOCKER_OPEN = "<!-- blocked: ";
396
725
  var REPAIRS_OPEN = "<!-- repairs: ";
397
726
  var BLOCKER_CLOSE = " -->";
398
727
  var BLOCKER_GAP = " ";
399
728
  var TRAILING_COMMENT = /\s<!-- (blocked|repairs): ((?:(?!<!--|-->).)*) -->$/;
400
- var OPEN_TASK_PREFIX = /^- \[(?: |BLOCKED)\] /;
401
729
  var ESCAPE_SEQUENCE = /\\(u[0-9A-Fa-f]{4}|[\s\S])/g;
402
730
  var TAB = 9;
403
731
  var FIRST_PRINTABLE = 32;
@@ -472,154 +800,7 @@ function splitBlockerComment(taskText) {
472
800
  const { text, blocked } = splitTrailingComments(taskText);
473
801
  return { text, blocker: commentText(blocked) };
474
802
  }
475
- function splitCarriageReturn(line) {
476
- return line.endsWith("\r") ? { body: line.slice(0, -1), cr: "\r" } : { body: line, cr: "" };
477
- }
478
- function withoutBlockerComment(line) {
479
- const { body, cr } = splitCarriageReturn(line);
480
- const prefix = OPEN_TASK_PREFIX.exec(body)?.[0];
481
- if (prefix === undefined)
482
- return line;
483
- const found = splitTrailingComments(body.slice(prefix.length));
484
- return found.blocked === null ? line : `${prefix}${found.text}${keptRepairs(found.repairs)}${cr}`;
485
- }
486
- function closedBlockLines(trackerContent) {
487
- const inside = new Set;
488
- for (const block of readRafaBlocks(trackerContent)) {
489
- if (!block.closed)
490
- continue;
491
- for (let line = block.span.first;line <= block.span.last; line += 1) {
492
- inside.add(line - 1);
493
- }
494
- }
495
- return inside;
496
- }
497
- function taskInfoOf(capture, lineNum, status) {
498
- const found = splitTrailingComments(capture.trim());
499
- const blocker = commentText(found.blocked);
500
- const repairs = commentText(found.repairs);
501
- return {
502
- task: found.text,
503
- lineNum,
504
- status,
505
- ...blocker === null ? {} : { blocker },
506
- ...repairs === null ? {} : { repairs }
507
- };
508
- }
509
- var TASK_LINE_STATUSES = [
510
- [/^- \[BLOCKED\] (.+)/, "blocked"],
511
- [/^- \[ \] (.+)/, "unchecked"],
512
- [/^- \[x\] (.+)/, "done"]
513
- ];
514
- var NO_LINES = new Set;
515
- function findNextTask(trackerContent, options = {}) {
516
- const skip = options.skipLines ?? NO_LINES;
517
- const open = listOpenTasks(trackerContent).filter((task) => !skip.has(task.lineNum));
518
- return open.find((task) => task.status === "blocked") ?? open.find((task) => task.status === "unchecked") ?? null;
519
- }
520
- function listTrackerTasks(trackerContent) {
521
- const lines = trackerContent.split(`
522
- `);
523
- const inBlock = closedBlockLines(trackerContent);
524
- const tasks = [];
525
- for (let i = 0;i < lines.length; i++) {
526
- if (inBlock.has(i))
527
- continue;
528
- for (const [pattern, status] of TASK_LINE_STATUSES) {
529
- const capture = lines[i].match(pattern)?.[1];
530
- if (!capture)
531
- continue;
532
- tasks.push(taskInfoOf(capture, i, status));
533
- break;
534
- }
535
- }
536
- return tasks;
537
- }
538
- function isOpenTask(task) {
539
- return task.status !== "done";
540
- }
541
- function listOpenTasks(trackerContent) {
542
- return listTrackerTasks(trackerContent).filter(isOpenTask);
543
- }
544
- function updateTrackerLine(trackerPath, lineNum, newStatus) {
545
- const lines = fs.readFileSync(trackerPath, "utf8").split(`
546
- `);
547
- const line = lines[lineNum];
548
- if (!line)
549
- return;
550
- if (newStatus === "done") {
551
- lines[lineNum] = withoutBlockerComment(line).replace(/^- \[ \]/, "- [x]").replace(/^- \[BLOCKED\]/, "- [x]");
552
- } else {
553
- lines[lineNum] = line.replace(/^- \[ \]/, "- [BLOCKED]");
554
- }
555
- fs.writeFileSync(trackerPath, lines.join(`
556
- `), "utf8");
557
- }
558
- function writeTrackerBlocker(trackerPath, lineNum, blocker) {
559
- const lines = fs.readFileSync(trackerPath, "utf8").split(`
560
- `);
561
- const line = lines[lineNum];
562
- if (line === undefined)
563
- return false;
564
- const { body, cr } = splitCarriageReturn(line);
565
- const prefix = OPEN_TASK_PREFIX.exec(body)?.[0];
566
- if (prefix === undefined)
567
- return false;
568
- const found = splitTrailingComments(body.slice(prefix.length));
569
- const text = found.text.trimEnd();
570
- if (text.trim().length === 0)
571
- return false;
572
- const comment = blocker.trim().length === 0 ? "" : `${BLOCKER_GAP}${blockerComment(blocker)}`;
573
- lines[lineNum] = `- [BLOCKED] ${text}${keptRepairs(found.repairs)}${comment}${cr}`;
574
- fs.writeFileSync(trackerPath, lines.join(`
575
- `), "utf8");
576
- return true;
577
- }
578
- var ANY_TASK_PREFIX = /^- \[(?: |x|BLOCKED)\] /;
579
- var LINE_TERMINATOR = /[\n\r\u2028\u2029]/;
580
- function assertInsertable(entry) {
581
- if (entry.task.trim().length === 0 || LINE_TERMINATOR.test(entry.task)) {
582
- throw new Error("insertTrackerTask: the task text must be one line and not blank");
583
- }
584
- if (entry.declaration.trim().length === 0 || /[{}]/.test(entry.declaration) || LINE_TERMINATOR.test(entry.declaration)) {
585
- throw new Error("insertTrackerTask: the declaration must be one line of entries holding no brace");
586
- }
587
- }
588
- function endOfChecklist(lines, inBlock) {
589
- for (let i = lines.length - 1;i >= 0; i -= 1) {
590
- if (!inBlock.has(i) && ANY_TASK_PREFIX.test(lines[i]))
591
- return i + 1;
592
- }
593
- const last = lines.length - 1;
594
- return lines[last] === "" ? last : lines.length;
595
- }
596
- function insertTrackerTask(trackerPath, entry, beforeLine) {
597
- assertInsertable(entry);
598
- const content = fs.readFileSync(trackerPath, "utf8");
599
- const lines = content.split(`
600
- `);
601
- const inBlock = closedBlockLines(content);
602
- if (beforeLine !== null) {
603
- const target = lines[beforeLine];
604
- if (target === undefined || inBlock.has(beforeLine) || !ANY_TASK_PREFIX.test(target)) {
605
- throw new Error(`insertTrackerTask: line ${beforeLine} is no task line`);
606
- }
607
- }
608
- const at = beforeLine ?? endOfChecklist(lines, inBlock);
609
- const { cr } = splitCarriageReturn(lines[0] ?? "");
610
- const repaired = entry.repairs ?? "";
611
- const repairs = repaired.trim().length === 0 ? "" : `${BLOCKER_GAP}${repairsComment(repaired)}`;
612
- const line = `- [BLOCKED] ${entry.task.trim()}${BLOCKER_GAP}{${entry.declaration.trim()}}` + `${repairs}${BLOCKER_GAP}${blockerComment(entry.blocker)}${cr}`;
613
- const written = [...lines.slice(0, at), line, ...lines.slice(at)];
614
- fs.writeFileSync(trackerPath, written.join(`
615
- `), "utf8");
616
- return at;
617
- }
618
- function trackerPathFor(planPath) {
619
- return planPath.replace(/PLAN(-[^/]*)?\.md$/, (_m, stub) => `PLAN_TRACKER${stub ?? ""}.md`);
620
- }
621
-
622
- // src/core/plan/parse.ts
803
+ // packages/rafa/src/core/plan/parse.ts
623
804
  var PLAN_BLOCK_KINDS = ["plan", "context", "stage-context"];
624
805
  var PLAN_HEADER_FIELDS = ["stub", "issue", "spec", "release"];
625
806
  var PLAN_RELEASE_LEVELS = ["patch", "minor", "major", "none"];
@@ -638,10 +819,10 @@ function isHeaderField(key) {
638
819
  function isReleaseLevel(value) {
639
820
  return PLAN_RELEASE_LEVELS.includes(value);
640
821
  }
641
- function isMapping(value) {
822
+ function isMapping2(value) {
642
823
  return typeof value === "object" && value !== null && !Array.isArray(value);
643
824
  }
644
- function describeValue(value) {
825
+ function describeValue2(value) {
645
826
  if (typeof value === "string")
646
827
  return JSON.stringify(value);
647
828
  if (value === null)
@@ -652,7 +833,7 @@ function describeValue(value) {
652
833
  return "a mapping";
653
834
  return String(value);
654
835
  }
655
- function messageOf2(error) {
836
+ function messageOf3(error) {
656
837
  return error instanceof Error ? error.message : String(error);
657
838
  }
658
839
  function planIssue(reason, line, text) {
@@ -784,10 +965,10 @@ function unusableText(field, value) {
784
965
  return `${subject} is empty; a value opening with # after a space is a YAML comment unless quoted`;
785
966
  }
786
967
  if (field === "release") {
787
- return `${subject} is ${describeValue(value)}, not one of ${PLAN_RELEASE_LEVELS.join(", ")}`;
968
+ return `${subject} is ${describeValue2(value)}, not one of ${PLAN_RELEASE_LEVELS.join(", ")}`;
788
969
  }
789
970
  if (typeof value !== "string") {
790
- return field === "issue" ? `${subject} is ${describeValue(value)}, not a string or a whole number; quote it` : `${subject} is ${describeValue(value)}, not a string; quote it`;
971
+ return field === "issue" ? `${subject} is ${describeValue2(value)}, not a string or a whole number; quote it` : `${subject} is ${describeValue2(value)}, not a string; quote it`;
791
972
  }
792
973
  if (value.trim().length === 0)
793
974
  return `${subject} is blank`;
@@ -831,13 +1012,13 @@ function readHeader(block) {
831
1012
  try {
832
1013
  document = Bun.YAML.parse(block.body);
833
1014
  } catch (error) {
834
- const text = `rafa:plan block is not valid YAML (${messageOf2(error)})`;
1015
+ const text = `rafa:plan block is not valid YAML (${messageOf3(error)})`;
835
1016
  return { header: emptyHeader(), issues: [planIssue("malformed-header", line, text)] };
836
1017
  }
837
1018
  if (document === null)
838
1019
  return { header: emptyHeader(), issues: [] };
839
- if (!isMapping(document)) {
840
- const text = `rafa:plan block holds ${describeValue(document)}, not a mapping of fields`;
1020
+ if (!isMapping2(document)) {
1021
+ const text = `rafa:plan block holds ${describeValue2(document)}, not a mapping of fields`;
841
1022
  return { header: emptyHeader(), issues: [planIssue("malformed-header", line, text)] };
842
1023
  }
843
1024
  return readFields(document, line);
@@ -863,7 +1044,7 @@ function parsePlan(markdown) {
863
1044
  issues
864
1045
  };
865
1046
  }
866
- // src/core/plan/plan-files.ts
1047
+ // packages/rafa/src/core/plan/plan-files.ts
867
1048
  import { statSync } from "fs";
868
1049
  import { basename as basename2, dirname as dirname2, join as join2, resolve } from "path";
869
1050
  function plansDirAt(root, planDir) {
@@ -895,6 +1076,10 @@ function issueLine(file, issue) {
895
1076
  function plural(count, noun) {
896
1077
  return count === 1 ? `${count} ${noun}` : `${count} ${noun}s`;
897
1078
  }
1079
+ // packages/rafa/src/core/plan/tracker-path.ts
1080
+ function trackerPathFor(planPath) {
1081
+ return planPath.replace(/PLAN(-[^/]*)?\.md$/, (_m, stub) => `PLAN_TRACKER${stub ?? ""}.md`);
1082
+ }
898
1083
  // src/plan/inject.ts
899
1084
  var PLAN_CONTEXT_HEADING = "## Plan context";
900
1085
  var STAGE_HEADING_PREFIX = "## Stage: ";
@@ -1036,4 +1221,4 @@ function renderInjection(request) {
1036
1221
  const repair = repairs === undefined ? null : parseTaskDeclaration(task.task).text.trim();
1037
1222
  return { requested: mode, mode, text: RENDERERS[mode](model, { task: location.task, repair }), fallback: null };
1038
1223
  }
1039
- export { escapeBlockerText, splitBlockerComment, findNextTask, listTrackerTasks, listOpenTasks, updateTrackerLine, writeTrackerBlocker, insertTrackerTask, trackerPathFor, PLAN_BLOCK_KINDS, PLAN_HEADER_FIELDS, PLAN_RELEASE_LEVELS, parsePlan, plansDirAt, countTasks, planFileName, stubOfPlanFile, isFile, rejectedPath, issueLine, plural, parsePrerequisites, planPrerequisites, malformedPrerequisiteLines, mergePlanPrerequisites, prerequisitesPathForPlan, loadPlanPrerequisites, PROBE_TIMEOUT_MS, runShellProbe, runPreflight, renderInjection };
1224
+ export { RAFA_BLOCK_KINDS, isRafaBlockKind, readRafaBlocks, REPORT_STATUSES, FINDING_KINDS, FINDING_SIGNALS, FINDING_DOMAINS, CHANGE_LEVELS, BUG_KINDS, parseReport, BLOCKER_GAP, escapeBlockerText, unescapeBlockerText, blockerComment, repairsComment, splitTrailingComments, commentText, keptRepairs, splitBlockerComment, PLAN_BLOCK_KINDS, PLAN_HEADER_FIELDS, PLAN_RELEASE_LEVELS, parsePlan, plansDirAt, countTasks, planFileName, stubOfPlanFile, isFile, rejectedPath, issueLine, plural, trackerPathFor, parsePrerequisites, planPrerequisites, malformedPrerequisiteLines, mergePlanPrerequisites, prerequisitesPathForPlan, loadPlanPrerequisites, PROBE_TIMEOUT_MS, runShellProbe, runPreflight, renderInjection };
@@ -1,12 +1,4 @@
1
1
  // @bun
2
- import {
3
- CONFIDENCE_MAX,
4
- CONFIDENCE_MIN,
5
- GAP,
6
- SOURCE_STEP,
7
- triggerKey
8
- } from "./index-hf2k497d.js";
9
-
10
2
  // src/learning/bless.ts
11
3
  import { createHash } from "crypto";
12
4
  var HUNDREDTHS = 100;
@@ -39,6 +31,19 @@ function bless(held, options) {
39
31
  function promotable(held, options) {
40
32
  return blessedRecords(held, options.minConfidence).filter((each) => each.usage_count >= options.after);
41
33
  }
34
+ // src/learning/identity.ts
35
+ import { createHash as createHash2 } from "crypto";
36
+ var GAP = 0.1;
37
+ var SOURCE_STEP = 0.05;
38
+ var CONFIDENCE_MIN = 0.3;
39
+ var CONFIDENCE_MAX = 0.9;
40
+ var WHITESPACE_RUN = /\s+/g;
41
+ function actionHash(action) {
42
+ return createHash2("sha256").update(action.trim().toLowerCase()).digest("hex");
43
+ }
44
+ function triggerKey(trigger) {
45
+ return trigger.trim().toLowerCase().replace(WHITESPACE_RUN, " ");
46
+ }
42
47
  // src/learning/merge.ts
43
48
  var HUNDREDTHS2 = 100;
44
49
  var GAP_H = Math.round(GAP * HUNDREDTHS2);
@@ -215,4 +220,4 @@ function merge(held, payload, now) {
215
220
  discarded: keys.flatMap((key) => outcomes.get(key).discarded)
216
221
  };
217
222
  }
218
- export { bless, promotable, merge };
223
+ export { bless, promotable, GAP, SOURCE_STEP, CONFIDENCE_MIN, CONFIDENCE_MAX, actionHash, triggerKey, merge };