tldr-experts 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +181 -0
- package/README.md +3 -1
- package/dist/hooks/answer-capture.js +4 -4
- package/dist/hooks/budget-gate.js +3 -3
- package/dist/hooks/{chunk-6ytv36jd.js → chunk-4w03q2kj.js} +9 -5
- package/dist/hooks/{chunk-6405vkzk.js → chunk-8awygmqw.js} +2 -1
- package/dist/hooks/{chunk-ecfqpeyj.js → chunk-f6484ykg.js} +9 -2
- package/dist/hooks/{chunk-b9rjx4qc.js → chunk-fv66tdsm.js} +14 -0
- package/dist/hooks/{chunk-c4p5x1b4.js → chunk-hg43zexg.js} +1 -1
- package/dist/hooks/no-reask.js +3 -3
- package/dist/hooks/session-start.js +6 -6
- package/dist/hooks/statusline.js +5 -5
- package/dist/tldrx.js +2315 -1660
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- /package/dist/hooks/{chunk-37fwvg3x.js → chunk-vyvjbbmb.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,187 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 0.9.2 — 2026-09-07
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- **The Build executor is no longer one 4,351-line file.** `BuildSession` was a single class
|
|
9
|
+
(`:520-3833`) over five subjects — the story pipeline, the reviewer handshake, the fix-list
|
|
10
|
+
round, the base-tree pre-flight and the worktree/branch mechanics — and the methods that
|
|
11
|
+
reached three or more of them were the ones every change had to touch. That is not an
|
|
12
|
+
aesthetic complaint: every remaining hardening fix lands inside this file, and a 4,000-line
|
|
13
|
+
diff context is exactly where the review loop is weakest, because the reviewer reads the
|
|
14
|
+
change and cannot see what the change sits next to. Eight modules now hold the machinery —
|
|
15
|
+
`build/reviewLedger.ts` (`events.jsonl` read once into the bounds a fresh process cannot
|
|
16
|
+
remember), `build/phaseCost.ts` (the handoff's cost line), `build/caps.ts` (the money
|
|
17
|
+
constants and every ceiling), `build/dodRunner.ts` (the story DoD and the #41 base
|
|
18
|
+
pre-flight), `build/worktrees.ts` (the git side of a story), `build/branchClaims.ts` (which
|
|
19
|
+
epic branch this run owns and the two refusals that protect the tree), `build/reviewBundle.ts`
|
|
20
|
+
(the reviewer's bundle on disk) and `build/reviewRound.ts` (one review round, one reviewer
|
|
21
|
+
prompt) — each taking DATA rather than the session, which is the rule the rest of
|
|
22
|
+
`src/core/build/` already kept without exception. The mutable state the orchestrator used to
|
|
23
|
+
hide in private maps is now explicit and passed in: `PreflightCache`, `EpicState` and
|
|
24
|
+
`ReviewCounters` — three counters of three different things, reset on three different events,
|
|
25
|
+
still never merged. `executors/build.ts` is down to ~2.9k lines and keeps the orchestration: the
|
|
26
|
+
entry points, the wave drivers, the story-state cluster, the log and handoff cluster, the
|
|
27
|
+
refusal helpers and `SerialQueue`. Nothing moved that a caller can see — every symbol anything
|
|
28
|
+
imports is still exported from `executors/build.ts`, so the nine importing test files,
|
|
29
|
+
`run/reopenStory.ts` and `facilitator/index.ts` did not change one line of import (the
|
|
30
|
+
re-exports nothing imported were dropped rather than carried, which is the opposite of drift).
|
|
31
|
+
The one test edit is a widening: `build-executor.test.ts`'s #134 pin that no file builds a
|
|
32
|
+
`story/${…}` name by hand now reads `worktrees.ts` and `branchClaims.ts` too, because a
|
|
33
|
+
NEGATIVE pin on one file gets weaker every time code leaves it.
|
|
34
|
+
Zero behaviour change, and it is proved rather than argued. A golden guard captured before the
|
|
35
|
+
first move — `test/build-golden.test.ts`, 18 committed artifacts across three scenarios that
|
|
36
|
+
cannot stand in for one another — freezes byte for byte the developer prompt, the reviewer
|
|
37
|
+
prompt, the `--prepare` bundle's own prompt, the ordered event stream with its payload keys
|
|
38
|
+
and values, `run.yml`'s task rows and the exit codes of a real fake-agent build, and every one
|
|
39
|
+
of the five move steps — and the surface-polish pass after them — had to keep it identical. It
|
|
40
|
+
is kept, because it is the cheapest regression net this file has ever had. The rule while the
|
|
41
|
+
wave ran, and the rule now: a golden byte change means REVERT — never "update the golden" to
|
|
42
|
+
make a diff go away.
|
|
43
|
+
|
|
44
|
+
## 0.9.1 — 2026-09-06
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **The docs site carries the whole CLI, generated from the registry.** The site's
|
|
49
|
+
`reference/cli.md` was a curated map that named about half the flags and pointed at
|
|
50
|
+
`docs/guide/08-cli-reference.md` for the rest — a file the site never builds, because
|
|
51
|
+
`docs/` is not in its `srcDir`. So the "exhaustive version" was not on the website at all,
|
|
52
|
+
and the owner went looking for `--yolo`, the flag that drops per-tool permission prompts,
|
|
53
|
+
and found it only in the changelog. `docs-site/scripts/gen-cli.ts` now writes
|
|
54
|
+
`/reference/cli-flags` and `/es/reference/cli-flags` at build time out of
|
|
55
|
+
`src/cli/helpText.ts` — all 33 commands, every flag with its meaning, every allowed value
|
|
56
|
+
spelled out from where it is enforced, every exit code, the environment variables, and the
|
|
57
|
+
rules that hold everywhere. Generated, gitignored and never hand-edited, for the same
|
|
58
|
+
reason the changelog page is: a second copy of 180 flags drifts on its first edit. The
|
|
59
|
+
Spanish page is framed in Spanish and keeps the meanings in English, like the release notes
|
|
60
|
+
and the sample CLI strings.
|
|
61
|
+
- **`test/docs-cli-coverage.test.ts` — the docs are now a gate.** Nothing asserted that a
|
|
62
|
+
declared flag was EXPLAINED anywhere a reader who is not typing `--help` would look. It now
|
|
63
|
+
asserts both surfaces: the repo guide names every flag inside its own command's section,
|
|
64
|
+
and the generated page carries every command, flag, allowed value and exit code, with
|
|
65
|
+
`--yolo` explained on each of the four commands that take it rather than left bare in a
|
|
66
|
+
usage line. It also holds the env-var table against a grep of `src/` in both directions.
|
|
67
|
+
- **`tldrx facts add` — the command the drive mandate has been naming since 0.8.0 (#161).** The
|
|
68
|
+
mandate tells the driver "a fact that must outlive the turn is `tldrx facts add`, which every
|
|
69
|
+
later prompt DOES read", and no such command was dispatched. What drivers did instead was edit
|
|
70
|
+
`.tldrx/memory/facts.yml` by hand, which walks past `FactsStore.append`'s 2000-character cap,
|
|
71
|
+
past its `…` marker and its `truncated: true` flag, and past `save()`'s validation — and a
|
|
72
|
+
fact cut mid-word with no marker is a record that does not know it is incomplete. It writes
|
|
73
|
+
through the store, under the workspace lock, with `--area` and `--decided-by owner|driver`
|
|
74
|
+
both required — a driver's default is never cited as the owner's decision, so the command
|
|
75
|
+
never lets the caller skip saying which of the two it was. The underlying `source.decided_by`
|
|
76
|
+
field stays additive (rows written before it existed, or by another writer, still validate)
|
|
77
|
+
and renders in every `{{facts}}` block as `· decided by owner` / `· decided by driver`,
|
|
78
|
+
appended only when present. Without `--run` it uses the one open run and refuses to guess
|
|
79
|
+
between several, recording the absence with its reason.
|
|
80
|
+
- **The provider's token split on the `run.yml` task row (#159).** `input_tokens` and `output_tokens`
|
|
81
|
+
were parsed on every provider turn and reached the event log only, so `run.yml` — the file
|
|
82
|
+
every cost report and every resumed run reads — carried a dollar figure with no token figure
|
|
83
|
+
beside it, which is a number nobody can check against a price table. Both fields are additive,
|
|
84
|
+
written only when a turn reported them and only together — a half-reported split is exactly
|
|
85
|
+
as unverifiable as an absent one, so it is dropped rather than have the parse's own zero
|
|
86
|
+
default stand in for a real count — and distinct from `tokens`, which keeps its meaning as a
|
|
87
|
+
host declaration. `version: 1` is unchanged and every older row loads.
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
|
|
91
|
+
- **Two commands the docs told you to run that do not exist.** `tldrx facts add` was
|
|
92
|
+
instructed three times, in `07-claude-code.md`, `10-unattended-mode.md` and
|
|
93
|
+
`08-cli-reference.md`, as the way to record something that must outlive a turn — measured:
|
|
94
|
+
`tldrx facts` is `unknown command 'facts'`, exit 1. A row in `.tldrx/memory/facts.yml` is
|
|
95
|
+
written by answering an open question, so all three now say `tldrx answer <Qid> "…"`. And
|
|
96
|
+
the environment-variable section told you to check that `TLDRX_CLAUDE_BIN` took with
|
|
97
|
+
`tldrx run --dry-run`; `--dry-run` is `next`'s flag, not `run`'s. The guard that found them
|
|
98
|
+
is now part of the suite: every `tldrx …` line inside a code span or a fenced block, on
|
|
99
|
+
every page of the site and the guide plus the README, is parsed and held against the
|
|
100
|
+
registry — an unknown command or a flag its command does not declare fails the build.
|
|
101
|
+
- **Two flags the guide never documented**, found by that test on its first run:
|
|
102
|
+
`tldrx dashboard --serve` (the default mode, and half of the two-modes refusal that
|
|
103
|
+
`--static` is the other half of) and `tldrx run status --verbose` (the two instants behind
|
|
104
|
+
a gate row). Both were real, both were reachable, and neither appeared in the page that
|
|
105
|
+
claims to be exhaustive. The shared spawn flags — `--model`, `--effort`, `--max-usd`,
|
|
106
|
+
`--ui`, `--prepare`/`--commit`, `--yolo` — now point from `run auto`, `seed triage` and
|
|
107
|
+
`expert train` at the one place they are explained, instead of appearing as bare tokens in
|
|
108
|
+
a usage line.
|
|
109
|
+
- **A turn with no provider USD figure is unmetered, not a metered `$0.00` (#159).** `interpret`
|
|
110
|
+
wrote `cost_usd: 0, metered: true` for a Claude result document that carried no
|
|
111
|
+
`total_cost_usd` — contradicting the `metered` field's own contract three lines above it, and
|
|
112
|
+
letting a stage, and then a whole run, read `$0.00` after real turns had run. `metered` is now
|
|
113
|
+
derived from the presence of the figure, so those turns reach `cost_usd: null` +
|
|
114
|
+
`metered: false` and every report that already knows how to say "LOWER BOUND, not a total"
|
|
115
|
+
says it. No new `spendBasis` word: `absent` already meant this, and the fix is to make more
|
|
116
|
+
turns reach it honestly. Codex keeps its pin — its synthesized result document carries a
|
|
117
|
+
`total_cost_usd: 0` that is a placeholder, and reading it as a measurement would be the same
|
|
118
|
+
lie under a different provider.
|
|
119
|
+
- **A refusal no longer discards a cost (#159).** `tldrx next --commit` returned
|
|
120
|
+
`EXIT_AGENT_FAILED` on a `questions.md` the §2.7 parser cannot read BEFORE it recorded the
|
|
121
|
+
task — so a turn that had already been paid for left no row anywhere, and the run's own ledger
|
|
122
|
+
was short by exactly the amount nobody could see. The row lands first and the refusal exits
|
|
123
|
+
after it. Because that refusal deliberately leaves the stage `running` so the operator can fix
|
|
124
|
+
the file and re-run, the banked row is marked `banked_before_refusal`, and the re-run is
|
|
125
|
+
matched to it by session id, declared cost and outputs — against MARKED rows only, so an
|
|
126
|
+
ordinary attempt a gate sent back is never mistaken for a re-read. Two things it deliberately
|
|
127
|
+
does NOT do. A result with no `session_id` is never fingerprinted at all: a null id identifies
|
|
128
|
+
nothing, so the second turn gets its own row carrying `dedupe: "none — no session id"` and the
|
|
129
|
+
reason is in `run.yml`, not only on the console — recording it twice is a smaller lie than
|
|
130
|
+
dropping a turn that ran. And the marker is single-use: the re-run that matches it stamps the
|
|
131
|
+
row `matched by the re-run committed at <at> — the marker is spent`, because a marker left
|
|
132
|
+
armed matched every later turn of the same shape for the life of the stage, and a real retry
|
|
133
|
+
after a gate reject — same session, same outputs, the same `null` cost — was silently dropped
|
|
134
|
+
as already recorded.
|
|
135
|
+
- **An oversized reviewer verdict no longer takes the whole invocation's ledger with it
|
|
136
|
+
(#160).** The 4096-byte payload cap was enforced by `EventLog.append` throwing, nothing
|
|
137
|
+
wrapped the executor call, and the reviewer's verdict prose is the field that overflows — so
|
|
138
|
+
one wordy review escaped past `recordExecutorTasks` and `store.save()`, leaving the epic merge
|
|
139
|
+
on disk and every task's cost gone from `run.yml`. The cap is honoured, never raised: at the
|
|
140
|
+
emit seam the oversized `detail` becomes `detail_omitted`, carrying its own byte count and
|
|
141
|
+
pointing at a sidecar the seam wrote FIRST — `<phase>/log/overflow/<stamp>-<n>-<type>-detail.txt`,
|
|
142
|
+
one file per omission — while the verdict itself survives. It is not the review log: that file
|
|
143
|
+
does not exist yet when the event is built, it later holds only the final verdict's prose, and
|
|
144
|
+
a story that does not settle never gets one, so pointing at it was a promise about a file that
|
|
145
|
+
might never arrive. Around all of it, the executor call is now wrapped: ANY throw out of an
|
|
146
|
+
executor exits 5 with the stage failed by name and the loss said plainly — which rows this
|
|
147
|
+
invocation could not recover — where before the throw simply escaped, leaving the stage
|
|
148
|
+
`running` in a file nobody saved. It attributes that failure to nothing it did not do, either:
|
|
149
|
+
the row it marks `failed` is one THIS invocation recorded, so a retry whose executor throws
|
|
150
|
+
leaves the previous attempt's `done` turn exactly as it was rather than repainting it with an
|
|
151
|
+
error it never produced.
|
|
152
|
+
- **A cached red base is no longer trusted forever (#162).** `04-build/preflight.yml` was
|
|
153
|
+
invalidated only by a base-sha comparison that no-ops when either sha is empty, and
|
|
154
|
+
`checked_at` was written and never read — so a red measured once came back from every later
|
|
155
|
+
`--prepare` in 0 seconds, over a base a live probe would show green, and the
|
|
156
|
+
`.tldrx/workspace.yml` fix that the refusal itself asks the operator to make was the one thing
|
|
157
|
+
the cache could not see. A red is now re-probed when the command hash differs, when the row is
|
|
158
|
+
older than 30 minutes, or always under `--prepare`. The hash covers the command together with
|
|
159
|
+
the workspace's whole declared command list, because the command string was already the join
|
|
160
|
+
key and hashing it alone would have changed nothing. A cached green keeps the rule it had, and
|
|
161
|
+
both new row fields are additive — an absent one invalidates nothing.
|
|
162
|
+
- **`tldrx facts add --run <id>` no longer invents an absence.** `RunStore.resolve` answers
|
|
163
|
+
`{kind: "none"}` both to "no run is open" and to "there is no run by that id", and the command
|
|
164
|
+
took the one branch for both: a typo'd `--run` wrote the fact with `source.run: null` under the
|
|
165
|
+
stdout line "no run recorded: no open run to attribute it to" — a sentence that is false
|
|
166
|
+
whenever a run IS open, over provenance the operator had asked for by name and silently did not
|
|
167
|
+
get. An id nothing in `tldrx-work/` answers to is now refused before the store is opened: exit
|
|
168
|
+
3, nothing written, no event, and the id named back. The other two branches are unchanged —
|
|
169
|
+
one open run is used, several are still never guessed between.
|
|
170
|
+
- **A fix list records the canonical 40-hex sha (#163).** `Resolved: yes <sha>` accepted 7-40
|
|
171
|
+
hex, so a sha that had lost a character read as a deliberate abbreviation: git resolved it,
|
|
172
|
+
the claim verified, and the audit record kept a form no later reader can tell from a prefix of
|
|
173
|
+
a different commit. The grammar is unchanged — demanding 40 would refuse the abbreviation a
|
|
174
|
+
person legitimately types — and the full object id is written back after the verification,
|
|
175
|
+
which is strictly stronger and refuses nobody.
|
|
176
|
+
|
|
177
|
+
### Changed
|
|
178
|
+
|
|
179
|
+
- **A command's subcommands are declared once.** They were written in the command module AND
|
|
180
|
+
needed by the docs generator, which would have made three copies of the same list. They now
|
|
181
|
+
live in `helpText.ts` beside the flags that are scoped by them, `subcommandsOf(name)` reads
|
|
182
|
+
them, and `Command.subcommands` is gone — one derivation, one implementation, per the house
|
|
183
|
+
invariant that the rest of the repo is already held to.
|
|
184
|
+
|
|
4
185
|
## 0.9.0 — 2026-09-06
|
|
5
186
|
|
|
6
187
|
### Added
|
package/README.md
CHANGED
|
@@ -251,7 +251,7 @@ Most run-targeting commands take the id either way, a positional `<run>` or `--r
|
|
|
251
251
|
`cost`, `note`, `gate template`, `questions`, `budget show`, `ship`, `tickets`, and `run attend` ·
|
|
252
252
|
`status` · `estimate` · `auto` · `unlock` · `cancel`. `replay` and `retro` take the positional only
|
|
253
253
|
— `--run` there is an unknown flag. `approve`, `reject`, `answer`, `interview`, `plan`,
|
|
254
|
-
`story reopen`, `watch` and `run gates set` take `--run <id>` only.
|
|
254
|
+
`story reopen`, `facts add`, `watch` and `run gates set` take `--run <id>` only.
|
|
255
255
|
|
|
256
256
|
`tldrx retro --all` goes the other way: it reads **every** run in the workspace and prints one
|
|
257
257
|
table of what keeps catching you — finding class × count × how many runs × one example with its
|
|
@@ -314,6 +314,8 @@ back on the registry is 0.3.0.
|
|
|
314
314
|
|
|
315
315
|
| Version | Date | Status | Contains |
|
|
316
316
|
|---|---|---|---|
|
|
317
|
+
| 0.9.2 | 2026-09-07 | `beta` | the Build executor decomposed: 4,351 lines became an orchestrator plus eight modules under src/core/build/ (review ledger and phase cost, money caps, the DoD runner with its preflight cache, worktrees and epic-branch claims, the reviewer bundle and review round) — a pure refactor proven byte-for-byte by a golden guard over prompts, ordered events, run.yml rows and exit codes across three scenarios; no behaviour changed, every remaining hardening fix now lands in a file a reviewer can hold |
|
|
318
|
+
| 0.9.1 | 2026-09-06 | `beta` | records and money that do not lie: a turn without a provider USD figure is unmetered, never a metered $0.00; a refusal no longer discards the turn's cost (banked first, deduped only against marked rows); an event over the 4096-byte cap spills its text beside the run and names it instead of losing every row of the invocation; preflight rows carry `command_hash` and their own `checked_at`, so a cached red is re-probed when the command changed, after 30 minutes, or under --prepare; the fix list writes back git's canonical 40-hex sha; `tldrx facts add` exists with owner/driver attribution rendered in prompts; run.yml rows carry the provider's token split only when reported |
|
|
317
319
|
| 0.9.0 | 2026-09-06 | `beta` | opt-in stack packs: four language pack bodies and thirteen framework overlays detected from manifests, interrogative by default (Defaults yield to any repo signal, Checks are questions with `verify:` hints), behind one per-project switch (`tldrx expert packs enable`) that materialises into `.tldrx/experts/<lang>-stack/` without touching trained knowledge; the Build reviewer gets `## Stack checks (the repo's own conventions win)`; every stage names the project's `.claude/skills` and the developer may invoke them; workspace.yml records overlays with evidence and skills with a tracked flag, `version: 1` unchanged |
|
|
318
320
|
| 0.8.0 | 2026-09-04 | `beta` | the unattended mandate learns to keep going: a `## Do not stop` section that defines the one thing allowed to end a run early (a strict blocker, named against the work it does not block), product questions parked as **guided** ones with lettered options and a pre-declared fallback, and a budget stop that asks instead of halting — written against 26 `budget.raised` and 26 `question.answered` events on a real ten-run workspace where the owner had to re-authorise "unattended" mid-run. Plus `tldrx drive --tldr`: a reporting contract for runs nobody will audit — the `run status` block plus three bullets of delta, no operator notes, minimal gate evidence, handoffs trimmed of prose but never of the citations `claim-sources` gates on. The ask channel stays the console and the framework names no chat vendor |
|
|
319
321
|
| 0.7.0 | 2026-09-03 | `beta` | Codex as a second honest automated runner: recorded JSONL contract, structured envelopes, role-based sandboxes, token/session provenance, and explicitly unmetered USD accounting; Claude remains the default and the pilot harness. Also absorbs the citation-honesty work previously staged as 0.6.2: a `file` src resolves against the branches the run RECORDED and NAMES the unmerged ref instead of passing in silence or breaking with the temp dir (#140), watcher cards name it the same way (#143), and every run close reports the questions nobody answered (#141) |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
FactsStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-f6484ykg.js";
|
|
5
5
|
import {
|
|
6
6
|
parseHookInput,
|
|
7
7
|
readStdin
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
EventLog,
|
|
11
11
|
PHASE_ID_RE
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-fv66tdsm.js";
|
|
13
13
|
import"./chunk-5w5eg00k.js";
|
|
14
|
-
import"./chunk-
|
|
14
|
+
import"./chunk-8awygmqw.js";
|
|
15
15
|
import {
|
|
16
16
|
MAX_FACT_CHARS,
|
|
17
17
|
detectAnswered,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
recordAnswer,
|
|
20
20
|
replaceBlock,
|
|
21
21
|
serializeQuestions
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-vyvjbbmb.js";
|
|
23
23
|
import"./chunk-39zh2e44.js";
|
|
24
24
|
import {
|
|
25
25
|
PROJECT_WORK_DIR,
|
|
@@ -29,15 +29,15 @@ import {
|
|
|
29
29
|
validateRunBudget,
|
|
30
30
|
wouldExceed,
|
|
31
31
|
wouldExceedHostTokens
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-hg43zexg.js";
|
|
33
33
|
import {
|
|
34
34
|
EventLog
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-fv66tdsm.js";
|
|
36
36
|
import"./chunk-rrkdfk7s.js";
|
|
37
37
|
import"./chunk-5w5eg00k.js";
|
|
38
38
|
import {
|
|
39
39
|
noteDeprecations
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-vyvjbbmb.js";
|
|
41
41
|
import"./chunk-39zh2e44.js";
|
|
42
42
|
import {
|
|
43
43
|
PROJECT_WORK_DIR,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
nowRfc3339,
|
|
8
8
|
openRunViews,
|
|
9
9
|
validateRunBudget
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-hg43zexg.js";
|
|
11
11
|
import {
|
|
12
12
|
EventLog,
|
|
13
13
|
asRunFile,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
isTerminal,
|
|
20
20
|
stageAt,
|
|
21
21
|
validateRunFile
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-fv66tdsm.js";
|
|
23
23
|
import {
|
|
24
24
|
backupPathFor,
|
|
25
25
|
isAlive,
|
|
@@ -28,12 +28,12 @@ import {
|
|
|
28
28
|
workspaceRootOfRunDir,
|
|
29
29
|
writeAtomic,
|
|
30
30
|
yamlScalar
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-8awygmqw.js";
|
|
32
32
|
import {
|
|
33
33
|
noteDeprecations,
|
|
34
34
|
openBlocks,
|
|
35
35
|
parseQuestions
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-vyvjbbmb.js";
|
|
37
37
|
import {
|
|
38
38
|
listRunDirs,
|
|
39
39
|
parseYaml,
|
|
@@ -80,11 +80,15 @@ function task(t, indent) {
|
|
|
80
80
|
const cost = t.cost_usd === null ? "null" : money(t.cost_usd);
|
|
81
81
|
const metered = t.metered === false ? ", metered: false" : "";
|
|
82
82
|
const tokens = t.tokens === undefined ? "" : `, tokens: ${String(t.tokens)}`;
|
|
83
|
+
const inTokens = t.input_tokens === undefined ? "" : `, input_tokens: ${String(t.input_tokens)}`;
|
|
84
|
+
const outTokens = t.output_tokens === undefined ? "" : `, output_tokens: ${String(t.output_tokens)}`;
|
|
83
85
|
return [
|
|
84
|
-
`${indent} - {id: ${yamlScalar(t.id)}, status: ${yamlScalar(t.status)}, expert: ${yamlScalar(t.expert)}, ` + `model: ${yamlScalar(t.model)}, cost_usd: ${cost}${metered}${tokens},`,
|
|
86
|
+
`${indent} - {id: ${yamlScalar(t.id)}, status: ${yamlScalar(t.status)}, expert: ${yamlScalar(t.expert)}, ` + `model: ${yamlScalar(t.model)}, cost_usd: ${cost}${metered}${tokens}${inTokens}${outTokens},`,
|
|
85
87
|
`${inner}error: ${yamlScalar(t.error)}, session_id: ${yamlScalar(t.session_id)},`,
|
|
86
88
|
`${inner}started_at: ${yamlScalar(t.started_at)}, ended_at: ${yamlScalar(t.ended_at)},`,
|
|
87
89
|
...t.stopped_by === undefined || t.stopped_by === null ? [] : [`${inner}stopped_by: ${yamlScalar(t.stopped_by)},`],
|
|
90
|
+
...t.banked_before_refusal === undefined ? [] : [`${inner}banked_before_refusal: true,`],
|
|
91
|
+
...t.dedupe === undefined ? [] : [`${inner}dedupe: ${yamlScalar(t.dedupe)},`],
|
|
88
92
|
`${inner}outputs: ${inlineList(t.outputs)}}`
|
|
89
93
|
].join(`
|
|
90
94
|
`);
|
|
@@ -143,6 +143,7 @@ function inlineList(values) {
|
|
|
143
143
|
}
|
|
144
144
|
function emitFact(fact, indent = " ") {
|
|
145
145
|
const inner = `${indent} `;
|
|
146
|
+
const decidedBy = fact.source.decided_by === undefined ? "" : `, decided_by: ${yamlScalar(fact.source.decided_by)}`;
|
|
146
147
|
const lines = [
|
|
147
148
|
`${indent}- id: ${yamlScalar(fact.id)}`,
|
|
148
149
|
`${inner}fact: ${yamlScalar(fact.fact)}`,
|
|
@@ -150,7 +151,7 @@ function emitFact(fact, indent = " ") {
|
|
|
150
151
|
`${inner}repos: ${inlineList(fact.repos)}`,
|
|
151
152
|
`${inner}kind: ${yamlScalar(fact.kind)}`,
|
|
152
153
|
`${inner}confidence: ${yamlScalar(fact.confidence)}`,
|
|
153
|
-
`${inner}source: {who: ${yamlScalar(fact.source.who)}, when: ${yamlScalar(fact.source.when)}, ` + `run: ${yamlScalar(fact.source.run)}, q: ${yamlScalar(fact.source.q)}}`,
|
|
154
|
+
`${inner}source: {who: ${yamlScalar(fact.source.who)}, when: ${yamlScalar(fact.source.when)}, ` + `run: ${yamlScalar(fact.source.run)}, q: ${yamlScalar(fact.source.q)}${decidedBy}}`,
|
|
154
155
|
`${inner}supersedes: ${yamlScalar(fact.supersedes)}`,
|
|
155
156
|
`${inner}superseded_by: ${yamlScalar(fact.superseded_by)}`
|
|
156
157
|
];
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
withWorkspaceLock,
|
|
4
4
|
workspaceRootOfFactsPath,
|
|
5
5
|
writeAtomic
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-8awygmqw.js";
|
|
7
7
|
import {
|
|
8
8
|
FACT_CONFIDENCES,
|
|
9
9
|
FACT_KINDS,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
isLive,
|
|
15
15
|
isRetired,
|
|
16
16
|
noteDeprecations
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-vyvjbbmb.js";
|
|
18
18
|
import {
|
|
19
19
|
asDocument,
|
|
20
20
|
isRecord,
|
|
@@ -86,6 +86,13 @@ function validateFactsFile(input) {
|
|
|
86
86
|
if (typeof q === "string" && !Q_RE.test(q)) {
|
|
87
87
|
issues.push({ path: `${path}.source.q`, message: `expected ${readableSource(Q_RE)} or null` });
|
|
88
88
|
}
|
|
89
|
+
const decidedBy = row.source.decided_by;
|
|
90
|
+
if (decidedBy !== undefined && decidedBy !== "owner" && decidedBy !== "driver") {
|
|
91
|
+
issues.push({
|
|
92
|
+
path: `${path}.source.decided_by`,
|
|
93
|
+
message: "expected owner, driver or absent"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
89
96
|
} else if (row.source !== undefined) {
|
|
90
97
|
issues.push({ path: `${path}.source`, message: "expected a mapping" });
|
|
91
98
|
}
|
|
@@ -698,6 +698,20 @@ function validateRunFile(input) {
|
|
|
698
698
|
if (task.cost_usd === null && task.metered !== false) {
|
|
699
699
|
issues.push({ path: `${tp}.metered`, message: "a null cost_usd must be marked `metered: false`" });
|
|
700
700
|
}
|
|
701
|
+
if (task.banked_before_refusal !== undefined && task.banked_before_refusal !== true) {
|
|
702
|
+
issues.push({ path: `${tp}.banked_before_refusal`, message: "expected `true` or absent" });
|
|
703
|
+
}
|
|
704
|
+
if (task.dedupe !== undefined && typeof task.dedupe !== "string") {
|
|
705
|
+
issues.push({ path: `${tp}.dedupe`, message: "expected a string" });
|
|
706
|
+
}
|
|
707
|
+
for (const key of ["input_tokens", "output_tokens"]) {
|
|
708
|
+
const value = task[key];
|
|
709
|
+
if (value === undefined)
|
|
710
|
+
continue;
|
|
711
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
712
|
+
issues.push({ path: `${tp}.${key}`, message: "expected a number >= 0" });
|
|
713
|
+
}
|
|
714
|
+
}
|
|
701
715
|
if (typeof task.cost_usd === "number")
|
|
702
716
|
spentFromTasks += task.cost_usd;
|
|
703
717
|
checkOrder(task.started_at, task.ended_at, tp, issues);
|
package/dist/hooks/no-reask.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-cf4az0j5.js";
|
|
8
8
|
import {
|
|
9
9
|
FactsStore
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-f6484ykg.js";
|
|
11
11
|
import {
|
|
12
12
|
allow,
|
|
13
13
|
deny,
|
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
runHook
|
|
18
18
|
} from "./chunk-2y3kwfrx.js";
|
|
19
19
|
import"./chunk-x3zy7zrn.js";
|
|
20
|
-
import"./chunk-
|
|
20
|
+
import"./chunk-8awygmqw.js";
|
|
21
21
|
import {
|
|
22
22
|
openBlocks,
|
|
23
23
|
parseQuestions
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-vyvjbbmb.js";
|
|
25
25
|
import"./chunk-39zh2e44.js";
|
|
26
26
|
import {
|
|
27
27
|
factsPath,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-
|
|
2
|
+
import"./chunk-f6484ykg.js";
|
|
3
3
|
import {
|
|
4
4
|
allow,
|
|
5
5
|
readPayload,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
openQuestions,
|
|
16
16
|
runSnapshot,
|
|
17
17
|
whatIsWaiting
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4w03q2kj.js";
|
|
19
19
|
import {
|
|
20
20
|
evidencePath,
|
|
21
21
|
expertsDir,
|
|
@@ -25,17 +25,17 @@ import {
|
|
|
25
25
|
pathsIntersect,
|
|
26
26
|
readExpertDomain,
|
|
27
27
|
stackExpertNames
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-hg43zexg.js";
|
|
29
29
|
import {
|
|
30
30
|
parseEvidence
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-fv66tdsm.js";
|
|
32
32
|
import"./chunk-rrkdfk7s.js";
|
|
33
33
|
import"./chunk-5w5eg00k.js";
|
|
34
|
-
import"./chunk-
|
|
34
|
+
import"./chunk-8awygmqw.js";
|
|
35
35
|
import {
|
|
36
36
|
openBlocks,
|
|
37
37
|
parseQuestions
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-vyvjbbmb.js";
|
|
39
39
|
import {
|
|
40
40
|
isRecord
|
|
41
41
|
} from "./chunk-39zh2e44.js";
|
package/dist/hooks/statusline.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
bar,
|
|
4
4
|
runSnapshot
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import"./chunk-
|
|
7
|
-
import"./chunk-
|
|
5
|
+
} from "./chunk-4w03q2kj.js";
|
|
6
|
+
import"./chunk-hg43zexg.js";
|
|
7
|
+
import"./chunk-fv66tdsm.js";
|
|
8
8
|
import"./chunk-rrkdfk7s.js";
|
|
9
9
|
import"./chunk-5w5eg00k.js";
|
|
10
|
-
import"./chunk-
|
|
11
|
-
import"./chunk-
|
|
10
|
+
import"./chunk-8awygmqw.js";
|
|
11
|
+
import"./chunk-vyvjbbmb.js";
|
|
12
12
|
import"./chunk-39zh2e44.js";
|
|
13
13
|
import {
|
|
14
14
|
findWorkspaceRoot,
|