@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
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The plan marker the loop stamps onto every prompt it dispatches.
3
+ *
4
+ * Effort attribution used to reach a session's plan through its BRANCH
5
+ * NAME, which works only while a run happens on a branch whose stub
6
+ * resolves. Measured after one run executed on `main`: all 74 of its
7
+ * sessions attributed to the `main` branch group instead of the plan,
8
+ * and the group they landed in mixes every main-branch session ever
9
+ * recorded, so the plan's figures were not recoverable from the store
10
+ * without knowing the run's wall-clock window by hand.
11
+ *
12
+ * Two of those sessions in three could not have been recovered by any
13
+ * derivation either. A task session carries the tracker line it was
14
+ * dispatched with, so its plan is at least derivable from the tracker
15
+ * text; a compaction and a wrap-up session carried neither the plan
16
+ * path nor the stub anywhere in their prompts, measured across both
17
+ * shapes before the wrap-up was handed its plan.
18
+ * So the signal did not exist to be inferred, and the fix is to WRITE
19
+ * one rather than to guess better.
20
+ *
21
+ * The marker is an HTML comment because every prompt this loop builds
22
+ * is markdown handed to a model: a comment carries no instruction, and
23
+ * a model that echoes the prompt back cannot turn it into one.
24
+ *
25
+ * It is APPENDED and never prepended, and that is load-bearing rather
26
+ * than cosmetic. `effort/classify.ts` buckets a session by
27
+ * `content.startsWith(shape.prefix)` over the WHOLE prompt, so one
28
+ * line above the body re-buckets every one of the four shapes as
29
+ * `other` — silently, because that module's drift guard is a
30
+ * containment check that would stay green. `start/wrap-up.ts` states
31
+ * the same rule at its wrap-up builder: add lines after line 1, never
32
+ * before it. {@link planStubFromPrompt} therefore SEARCHES rather than
33
+ * matching a prefix, which is what lets the marker sit at the end.
34
+ *
35
+ * A stub is written verbatim and matched against the same character
36
+ * class `readPlanStubs` derives from a filename, so a stamp can never
37
+ * name a stub the store could not also have resolved from a branch.
38
+ */
39
+ /** True when the text is usable as a stamped stub. */
40
+ export declare function isStampableStub(stub: string): boolean;
41
+ /**
42
+ * Builds the marker line for one plan stub.
43
+ *
44
+ * Throws on a stub the pattern would not match, rather than writing a
45
+ * marker {@link planStubFromPrompt} could not read back. A stamp that
46
+ * silently fails to parse is worse than no stamp: it reports as an
47
+ * unattributed session while looking like it was handled.
48
+ */
49
+ export declare function planStampLine(stub: string): string;
50
+ /**
51
+ * Reads the stub back out of a dispatched prompt, or null.
52
+ *
53
+ * Null for absent content, for a prompt carrying no marker, and for a
54
+ * marker whose stub does not match the class — the three cases a
55
+ * caller treats alike, since each means the session has no stamped
56
+ * plan and must fall back to its branch.
57
+ */
58
+ export declare function planStubFromPrompt(content: string | null | undefined): string | null;
59
+ /**
60
+ * Appends the marker to a prompt the loop is about to dispatch.
61
+ *
62
+ * Never prepends: the first line is a classifier key, and the module
63
+ * note above carries the measurement.
64
+ */
65
+ export declare function stampPrompt(stub: string, prompt: string): string;
66
+ /**
67
+ * Derives a plan stub from a plan or tracker path.
68
+ *
69
+ * `PLAN-q16a-compose-n8n.md` and `PLAN_TRACKER-q16a-compose-n8n.md`
70
+ * both answer `q16a-compose-n8n`; a bare `PLAN.md` answers null,
71
+ * having no stub to name. Null rather than a fallback string: an
72
+ * unstubbed plan is exactly the case a stamp must not invent a group
73
+ * for, and the caller reports it instead.
74
+ */
75
+ export declare function planStubFromPath(planPath: string): string | null;
@@ -0,0 +1,21 @@
1
+ /** An installed runtime: a runtime copy, or the package installed from npm. */
2
+ export interface InstalledIdentity {
3
+ readonly kind: 'installed';
4
+ /** The entry file, through its real path when it exists. */
5
+ readonly entry: string;
6
+ }
7
+ /** A development build: rafa run from a checkout. */
8
+ export interface DevelopmentIdentity {
9
+ readonly kind: 'development';
10
+ /** The entry file, through its real path when it exists. */
11
+ readonly entry: string;
12
+ /** The checkout's root, the directory holding its `package.json` and `src/rafa.ts`. */
13
+ readonly checkout: string;
14
+ }
15
+ /** Which build is running; see the module note. */
16
+ export type RuntimeIdentity = InstalledIdentity | DevelopmentIdentity;
17
+ /**
18
+ * Which build runs from `entry`, `Bun.main` by default. See the module
19
+ * note for the walk.
20
+ */
21
+ export declare function readRuntimeIdentity(entry?: string): RuntimeIdentity;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The barrel over the runtime identity: every name `identity.ts`
3
+ * exports, and nothing else.
4
+ *
5
+ * A file outside `packages/rafa/src/core/` imports this file and never the one behind
6
+ * it (`scripts/survey/core-barrels.ts` measures that, and
7
+ * `src/tests/core-barrels.sweep.test.ts` holds it against the tree). A
8
+ * file inside `packages/rafa/src/core/` imports `identity.ts` directly and never this
9
+ * file. The effort store under `packages/rafa/src/effort/store/` is core by
10
+ * assignment and not by folder, so it is outside `packages/rafa/src/core/` for the
11
+ * rule and imports this file.
12
+ *
13
+ * ## What sits behind it
14
+ *
15
+ * `identity.ts` alone: {@link readRuntimeIdentity}, which reads whether
16
+ * the running build is an installed runtime or a development build run
17
+ * from a checkout, and the three types it answers with. It moved here
18
+ * from `src/runtime/identity.ts` (#1088), so the effort store, which
19
+ * asks it before it migrates a live store, imports nothing above core
20
+ * for it.
21
+ *
22
+ * ## Why one barrel can hold it
23
+ *
24
+ * A barrel that groups a file with a file outside `packages/rafa/src/core/` that
25
+ * imports the barrel back by value is a runtime cycle. `identity.ts`
26
+ * imports `node:fs`, `node:path` and the root `package.json`, and no
27
+ * file under `src/`, so no file behind this barrel reaches a file that
28
+ * imports it back.
29
+ *
30
+ * ## The old path
31
+ *
32
+ * `src/runtime/identity.ts` re-exported this file's names under the same
33
+ * names until core moved into its package (#1090), which deleted it and
34
+ * pointed its importers at `@open-tomato/rafa/core/runtime`.
35
+ *
36
+ * ## What it exports
37
+ *
38
+ * Each name is spelled, types apart from values, as the other core
39
+ * barrels spell theirs. No name here is part of the published surface:
40
+ * `src/index.ts` re-exports nothing from this file.
41
+ *
42
+ * `index.test.ts` holds the list to the file: every name `identity.ts`
43
+ * exports is here once, as the same binding, and no other name is here.
44
+ */
45
+ export type { DevelopmentIdentity, InstalledIdentity, RuntimeIdentity } from './identity.js';
46
+ export { readRuntimeIdentity } from './identity.js';
@@ -0,0 +1,131 @@
1
+ /**
2
+ * The log-aware open: bring a SQLite store to this build's migrations,
3
+ * recording each one in the store's migration log, or refuse it.
4
+ *
5
+ * ## The migration log
6
+ *
7
+ * `schema_migrations` holds one row per migration the store holds: its
8
+ * id, the sha256 of its SQL, what it `breaks` as a JSON array of words,
9
+ * when it was applied and by which rafa. {@link bringForward} creates the
10
+ * table in the same transaction as the rows it first records, so a store
11
+ * never holds an empty log it was not given in that transaction.
12
+ *
13
+ * ## What an open does
14
+ *
15
+ * {@link bringForward} reads the log and `user_version`, and hands them
16
+ * to `planSchema` (`schema-plan.ts`), which decides. A refusal is thrown
17
+ * as a {@link SchemaRefusedError} carrying the plan's reason, message and
18
+ * next step, and nothing is written. A plan with nothing to adopt or
19
+ * apply returns at once, taking no lock and writing nothing, so a read
20
+ * open of a current store never writes.
21
+ *
22
+ * Otherwise the open takes the write lock with `BEGIN IMMEDIATE`, reads
23
+ * the store again and plans again, since another process may have
24
+ * brought the store forward, or recorded a migration this build does
25
+ * not know, while this one waited. Under that second plan, and in one
26
+ * transaction, it:
27
+ *
28
+ * - creates `schema_migrations` when the store has none;
29
+ * - adopts a store with no log: the legacy entries its `user_version`
30
+ * counts are logged with this build's checksums and not run, since
31
+ * a shipped entry is frozen and so is what ran;
32
+ * - runs each pending migration's SQL and logs it, in catalogue order;
33
+ * - sets `user_version` to the gate the plan answers.
34
+ *
35
+ * A throw anywhere rolls all of it back, `user_version` included, and
36
+ * leaves the store as it was found. The second plan can find nothing
37
+ * left to do, which is the answer when another process applied the same
38
+ * migrations first; the transaction then writes nothing.
39
+ *
40
+ * A store with a log and nothing pending keeps the `user_version` it
41
+ * holds, even when its log would give another gate: only a transaction
42
+ * that records a migration moves the gate.
43
+ *
44
+ * ## A development build never migrates the live store
45
+ *
46
+ * Between the first plan and the lock, an open with something to write
47
+ * asks `refuseUnownedDevelopmentWrite` (`development-build.ts`), which
48
+ * throws a `DevelopmentBuildRefusedError` when this rafa is a
49
+ * development build and the store lies outside the temporary directory
50
+ * and `RAFA_EFFORT_DIR`. The refusal comes before the lock and before
51
+ * any write, adoption included, so the store keeps its bytes. With
52
+ * nothing to write the open returns before that question is asked, so
53
+ * a development build uses a current store as any rafa does. That
54
+ * module's note says which stores it owns and what the text names.
55
+ *
56
+ * An open with {@link BringForwardOptions.builtAside} set skips that
57
+ * question: its file is one the caller built beside a store, which
58
+ * reaches the store only through the build-aside swap
59
+ * (`rebuild-aside.ts`), so the caller asks the question of the swap.
60
+ * `fix-schema.ts` builds its rebuild this way, since the parallel file
61
+ * sits in the project's store directory where the question would
62
+ * otherwise refuse even a dry run.
63
+ *
64
+ * ## What this module does not decide
65
+ *
66
+ * `planSchema` owns every refusal and its text. Which rafa counts as the
67
+ * one applying a migration is the caller's to say through
68
+ * {@link BringForwardOptions.appliedBy}; with none given it is this
69
+ * build's package version.
70
+ */
71
+ import type { DevelopmentProbe } from './development-build.js';
72
+ import type { SqliteMigration } from './migrations.js';
73
+ import type { RefusalReason, SchemaCaller, SchemaRefusal, SchemaUse, StoreAccess, StoreSchema } from './schema-plan.js';
74
+ import type { Database } from 'bun:sqlite';
75
+ /** The migration log's table. */
76
+ export declare const MIGRATION_LOG_TABLE = "schema_migrations";
77
+ /** A store refused by `planSchema`, carrying the plan's answer. */
78
+ export declare class SchemaRefusedError extends Error {
79
+ /** Which of the seven refusals this is. */
80
+ readonly reason: RefusalReason;
81
+ /** The one command to run next, which the message also ends with. */
82
+ readonly nextStep: string;
83
+ constructor(refusal: SchemaRefusal);
84
+ }
85
+ /**
86
+ * What an open may vary; each field has the running build's default.
87
+ * The {@link DevelopmentProbe} fields say which build runs and which
88
+ * stores it owns (`development-build.ts`).
89
+ */
90
+ export interface BringForwardOptions extends DevelopmentProbe {
91
+ /** The catalogue to bring the store to; a test passes a synthetic tail here. */
92
+ readonly migrations?: readonly SqliteMigration[];
93
+ /** The `applied_by` of every row this open logs; this build's version by default. */
94
+ readonly appliedBy?: string;
95
+ /** The clock `applied_at` is read from. */
96
+ readonly now?: () => Date;
97
+ /**
98
+ * True when `db` is a file the caller built beside a store and swaps
99
+ * in only through the build-aside steps; the development-build
100
+ * question is then the caller's, and this open does not ask it.
101
+ */
102
+ readonly builtAside?: boolean;
103
+ }
104
+ /** What an open wrote. Both lists are empty when it wrote nothing. */
105
+ export interface BroughtForward {
106
+ /** Legacy ids logged without running, in catalogue order. */
107
+ readonly adopted: readonly string[];
108
+ /** Ids whose SQL ran and was logged, in the order it ran. */
109
+ readonly applied: readonly string[];
110
+ /** The store's `user_version` once the open is done. */
111
+ readonly userVersion: number;
112
+ }
113
+ /**
114
+ * Bring the store open on `db` to this build's migrations for an open
115
+ * with `access` from `caller`, or throw {@link SchemaRefusedError}.
116
+ * `path` is what a refusal names the store as. The module note says
117
+ * what is written, and when.
118
+ */
119
+ export declare function bringForward(db: Database, path: string, access: StoreAccess, caller: SchemaCaller, options?: BringForwardOptions): BroughtForward;
120
+ /**
121
+ * The store's `user_version` and its migration log, or a null log when
122
+ * it has no `schema_migrations` table. Reads only.
123
+ */
124
+ export declare function readStoreSchema(db: Database, path: string): StoreSchema;
125
+ /**
126
+ * What a plan's write would record: the log first when it adopts, then
127
+ * each pending id. Empty when the plan writes nothing. `rafa effort
128
+ * schema` names the same list when it asks the development-build
129
+ * question an open would ask (`schema-report.ts`).
130
+ */
131
+ export declare function writeNames(plan: SchemaUse): readonly string[];
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The check rows of a pull request and the verdict over them, which the
3
+ * store's plan CI writer (`./plan-ci.ts`) reads and `src/pr/checks.ts`
4
+ * re-exports for the poll and the provider that parse and wait on them.
5
+ *
6
+ * They sit in core so the store reads a verdict without importing the
7
+ * `pr` module above it.
8
+ */
9
+ /** Whether a single check has passed, failed, or is still in flight. */
10
+ export type CheckOutcome = 'pass' | 'fail' | 'pending';
11
+ /** One row of `gh pr checks --json name,state,link`. */
12
+ export interface CheckRow {
13
+ name: string;
14
+ /** GitHub's raw state, kept verbatim so an unknown one stays reportable. */
15
+ state: string;
16
+ link: string;
17
+ outcome: CheckOutcome;
18
+ }
19
+ /**
20
+ * The verdict over every row: `none` when the PR has no checks at all,
21
+ * which is the shape a conflicting PR produces, and the shape of a head
22
+ * pushed seconds ago whose first check has not registered yet.
23
+ */
24
+ export type ChecksVerdict = 'green' | 'red' | 'pending' | 'none';
25
+ /**
26
+ * Reduces rows to one verdict. Pending outranks failure so a run that is
27
+ * still going is never reported as red on a partial reading.
28
+ */
29
+ export declare function verdictOf(rows: readonly CheckRow[]): ChecksVerdict;
30
+ /** Rows the caller should act on: the failing ones, for a repair prompt. */
31
+ export declare function failingRows(rows: readonly CheckRow[]): CheckRow[];
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The commit row of the effort store and the gap arithmetic its rows
3
+ * carry.
4
+ *
5
+ * Moved down from `src/effort/commits.ts`, which parses `git log` into
6
+ * these rows and re-exports both names under the same names: the
7
+ * store's row types (`types.ts`), the merge's gap recompute
8
+ * (`merge-commit-gaps.ts`) and its scenario fixtures
9
+ * (`testdata/merge-scenarios.ts`) need the row and the arithmetic but
10
+ * not the parser, so they import them here and the store imports
11
+ * nothing above core for them. The parser's module note in
12
+ * `commits.ts` still describes how each field is read from the log.
13
+ */
14
+ /** One row per commit. */
15
+ export interface CommitStats {
16
+ /** Full 40-character sha, and the store's key projection. */
17
+ sha: string;
18
+ /** Author date, ISO 8601 with offset, as `%aI` emits it. */
19
+ timestamp: string;
20
+ /** Subject line only. No commit message body reaches the row. */
21
+ subject: string;
22
+ /** Author name, as `%an` emits it. */
23
+ author: string;
24
+ /** Ref the walk reached this commit from, or null for `HEAD`. */
25
+ branch: string | null;
26
+ /** Numstat lines attributed to the commit, binary files included. */
27
+ filesChanged: number;
28
+ /** Summed added lines; a binary file contributes zero. */
29
+ insertions: number;
30
+ /** Summed removed lines; a binary file contributes zero. */
31
+ deletions: number;
32
+ /** Parents. Two or more is a merge, which prints no diff. */
33
+ parentCount: number;
34
+ /** Minutes since the preceding commit in time order, or null. */
35
+ minutesSincePrevious: number | null;
36
+ }
37
+ /**
38
+ * Minutes between two ISO timestamps, or null when either fails to
39
+ * parse. Rounded to {@link ELAPSED_DECIMALS}; never negative, because
40
+ * the caller orders the pair before asking.
41
+ */
42
+ export declare function minutesBetween(earlier: string, later: string): number | null;
@@ -0,0 +1,35 @@
1
+ /** The store files a directory can hold, the SQLite file first. */
2
+ export declare const EFFORT_COPY_FILE_NAMES: readonly string[];
3
+ /** A copy that was never started; nothing was made. */
4
+ export declare class EffortCopyRefusal extends Error {
5
+ readonly name = "EffortCopyRefusal";
6
+ }
7
+ /** A read or a write that failed once the copy started; what it made is removed. */
8
+ export declare class EffortCopyFailure extends Error {
9
+ readonly name = "EffortCopyFailure";
10
+ }
11
+ /** What one copy is handed. */
12
+ export interface EffortCopyRequest {
13
+ /** The store directory copied from. */
14
+ readonly source: string;
15
+ /** The directory copied into: absent, or an empty directory. */
16
+ readonly target: string;
17
+ }
18
+ /** What one copy did. */
19
+ export interface EffortCopyResult {
20
+ /** The store directory copied from, resolved. */
21
+ readonly source: string;
22
+ /** The directory copied into, resolved. */
23
+ readonly directory: string;
24
+ /** The store files copied, by name, in {@link EFFORT_COPY_FILE_NAMES} order. */
25
+ readonly files: readonly string[];
26
+ }
27
+ /** Writes `source`'s SQLite store to `target` as one snapshot, reading only. */
28
+ export declare function vacuumInto(source: string, target: string): void;
29
+ /**
30
+ * Copies the store in `request.source` into `request.target`, answering
31
+ * what it copied. Throws {@link EffortCopyRefusal} with nothing made, and
32
+ * {@link EffortCopyFailure} with what it made removed; see the module
33
+ * note.
34
+ */
35
+ export declare function copyEffortStore(request: EffortCopyRequest): EffortCopyResult;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * A development build never migrates the live store: the refusal
3
+ * `bringForward` (`bring-forward.ts`) raises before it writes a store
4
+ * this build does not own.
5
+ *
6
+ * ## When it refuses
7
+ *
8
+ * `bringForward` asks {@link refuseUnownedDevelopmentWrite} once its
9
+ * first plan leaves something to write: a store to adopt, or a pending
10
+ * migration. It refuses when both hold:
11
+ *
12
+ * - the running rafa is a development build, as `readRuntimeIdentity`
13
+ * (`packages/rafa/src/core/runtime/identity.ts`) reads it: `bun src/rafa.ts`, a
14
+ * checkout's `dist/cli.js` or a `bun test` process;
15
+ * - the store is not one it owns ({@link isOwnedStore}).
16
+ *
17
+ * A plan with nothing to write never gets here, so a development build
18
+ * reads and writes the live store as it always did while the store is
19
+ * current. An installed runtime is never refused here. Adoption counts
20
+ * as a write, so a development build never adopts the live store
21
+ * either, and the refusal names `schema_migrations` for it, ahead of
22
+ * the pending ids.
23
+ *
24
+ * ## The stores a development build owns
25
+ *
26
+ * A store under the temporary directory (`tmpdir()`, read at each call,
27
+ * or its real path), which is where every test's store is, and a store
28
+ * under the directory `RAFA_EFFORT_DIR` names, which is where a copy
29
+ * made by `rafa effort copy` is. A store that sits in a project's own
30
+ * `<root>/.rafa/effort/` directory is owned under the temporary
31
+ * directory only, never through the variable: a variable naming a
32
+ * directory above a project would otherwise let branch code migrate
33
+ * that project's live store. `location.ts` already refuses a variable
34
+ * naming the project's own store where it resolves the directory, and
35
+ * a relative value, which counts for nothing here.
36
+ *
37
+ * ## The text
38
+ *
39
+ * The spec's, verbatim, naming the ids and the checkout:
40
+ *
41
+ * effort store: <path> needs migration <ids> and this rafa is a
42
+ * development build (<checkout>); a development build migrates only
43
+ * a store under the temp directory or RAFA_EFFORT_DIR. Copy it with
44
+ * 'rafa effort copy' and run this command with
45
+ * RAFA_EFFORT_DIR=<the copy>.
46
+ *
47
+ * When the store is a project's own (`<root>/.rafa/effort/`), each loop
48
+ * record under `<root>/.rafa/runs/` that reads `running` or `paused`
49
+ * with its pid alive (`readSessions`, `packages/rafa/src/core/loop/sessions.ts`) adds
50
+ * ` Loop <sessionId> (pid <pid>, plan <stub>) is running on this
51
+ * store.`, oldest first; a record with no stub names its plan's path.
52
+ * When the records cannot be read, the text says so and names the
53
+ * error, rather than dropping the sentence in silence. The refusal is
54
+ * thrown before any write, so the store's bytes are left as they were.
55
+ */
56
+ import type { StoreEnvironment } from './location.js';
57
+ import type { PidProbe } from '../../core/loop/index.js';
58
+ import type { RuntimeIdentity } from '../../core/runtime/index.js';
59
+ /** The command a refused development build is sent to. */
60
+ export declare const DEVELOPMENT_NEXT_STEP = "rafa effort copy";
61
+ /** What the refusal names in place of an id when the write would adopt the store. */
62
+ export declare const ADOPTION_NAME = "schema_migrations";
63
+ /** What the refusal reads about the process it runs in; each field has a default. */
64
+ export interface DevelopmentProbe {
65
+ /** Which build is running; `readRuntimeIdentity()` by default. */
66
+ readonly identity?: RuntimeIdentity;
67
+ /** The environment `RAFA_EFFORT_DIR` is read from; `process.env` by default. */
68
+ readonly env?: StoreEnvironment;
69
+ /** The temporary directory; `tmpdir()` by default. */
70
+ readonly tempDir?: string;
71
+ /** Whether a loop record's pid is alive; `isPidAlive` by default. */
72
+ readonly isAlive?: PidProbe;
73
+ }
74
+ /** What follows the version in the `applied_by` of a row a development build logged, ahead of its checkout. */
75
+ export declare const DEVELOPMENT_MARK = "+dev:";
76
+ /**
77
+ * The running rafa as a migration log's `applied_by` names it: its
78
+ * version for an installed runtime, and `<version>+dev:<checkout>` for a
79
+ * development build, so a row a checkout logged says which one.
80
+ */
81
+ export declare function appliedByName(identity: RuntimeIdentity): string;
82
+ /** A development build refused a write to a store it does not own. */
83
+ export declare class DevelopmentBuildRefusedError extends Error {
84
+ /** The store refused. */
85
+ readonly path: string;
86
+ /** The one command to run next. */
87
+ readonly nextStep: string;
88
+ constructor(path: string, message: string);
89
+ }
90
+ /**
91
+ * The project root a store file sits in, when its directory is that
92
+ * project's `<root>/.rafa/effort/`, and null for a store anywhere else.
93
+ */
94
+ export declare function storeProjectRoot(path: string): string | null;
95
+ /** True when the store at `path` is one a development build may write; see the module note. */
96
+ export declare function isOwnedStore(path: string, env: StoreEnvironment, tempDir: string): boolean;
97
+ /** The refusal's text; see the module note. */
98
+ export declare function developmentRefusalText(path: string, needs: readonly string[], checkout: string, loops: string): string;
99
+ /**
100
+ * Throws {@link DevelopmentBuildRefusedError} when a development build
101
+ * would write the store at `path`, which it does not own, and does
102
+ * nothing otherwise. `needs` names what the write would record, in the
103
+ * order it would record it. Reads, and writes nothing.
104
+ */
105
+ export declare function refuseUnownedDevelopmentWrite(path: string, needs: readonly string[], probe?: DevelopmentProbe): void;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The effort levels a task's declaration may name, held in core so the
3
+ * store's dispatch writer (`dispatches.ts`) can type a declared effort
4
+ * without importing the declaration parser above core.
5
+ *
6
+ * The declaration parser, `core/plan/declaration.ts`, imports
7
+ * `EffortLevel` from here, and is where a task line's `effort=` value is
8
+ * read and checked.
9
+ */
10
+ /** Levels `--effort` accepts, taken from the CLI's own help text. */
11
+ export declare const EFFORT_LEVELS: readonly ["low", "medium", "high", "xhigh", "max"];
12
+ /** One of the five levels `--effort` accepts. */
13
+ export type EffortLevel = (typeof EFFORT_LEVELS)[number];