@pimmesz/afterburner 1.0.12 → 1.0.14
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/README.md +1 -0
- package/afterburner.config.example.ts +2 -1
- package/dist/{chunk-4TD2KS3A.js → chunk-HAERJCAI.js} +5 -2
- package/dist/cli/index.js +11 -12
- package/dist/core/index.d.ts +14 -11
- package/dist/core/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -256,6 +256,7 @@ writes `.mjs` by default. There's a commented example in
|
|
|
256
256
|
| `agent.modelByCategory` | sonnet/opus/haiku mix | Per-category model routing. Plain strings, so a new model never breaks the config. |
|
|
257
257
|
| `agent.maxTaskTokens` | `200_000` | Hard per-task ceiling in Sonnet-equivalent tokens |
|
|
258
258
|
| `agent.allowFable` | `false` | Explicit opt-in for Fable-family models |
|
|
259
|
+
| `notify.desktop` | `false` | Desktop banner per completed run (macOS/Linux/Windows), opt-in; the PR stays the primary signal |
|
|
259
260
|
| `taskCategories` | all enabled, weighted | Per-category enable/disable plus a ranking weight |
|
|
260
261
|
|
|
261
262
|
Task categories are `security`, `tests`, `types-lint`, `dead-code`, `perf`, `infra`, and
|
|
@@ -72,7 +72,8 @@ const config = {
|
|
|
72
72
|
backend: 'dry-run',
|
|
73
73
|
// Per-category model routing. Plain strings on purpose, so a new model
|
|
74
74
|
// can't break the config. Omitted categories use the built-in defaults
|
|
75
|
-
// (sonnet for
|
|
75
|
+
// (sonnet for security and tests, opus for perf and infra, haiku for the
|
|
76
|
+
// simple end: types-lint, dead-code, docs).
|
|
76
77
|
modelByCategory: {
|
|
77
78
|
perf: 'claude-opus-4-8',
|
|
78
79
|
docs: 'claude-haiku-4-5',
|
|
@@ -495,7 +495,7 @@ function createBudgetProvider(config, opts = {}) {
|
|
|
495
495
|
|
|
496
496
|
// src/core/scheduler/gate.ts
|
|
497
497
|
function shouldIgnite(budget, estCostSonnetTokens, config) {
|
|
498
|
-
if (!Number.isFinite(budget.weeklyRemainingPct) || !Number.isFinite(budget.weeklyRemainingTokensEst) || !Number.isFinite(estCostSonnetTokens) || !Number.isFinite(config.safetyMarginTokens)) {
|
|
498
|
+
if (!Number.isFinite(budget.weeklyRemainingPct) || !Number.isFinite(budget.weeklyRemainingTokensEst) || !Number.isFinite(estCostSonnetTokens) || !Number.isFinite(config.safetyMarginTokens) || !Number.isFinite(config.minWeeklyHeadroomPct)) {
|
|
499
499
|
return { go: false, reason: "budget or estimate is not a finite number; refusing to ignite" };
|
|
500
500
|
}
|
|
501
501
|
if (config.requireSessionAvailable && !budget.sessionAvailable) {
|
|
@@ -514,7 +514,10 @@ function shouldIgnite(budget, estCostSonnetTokens, config) {
|
|
|
514
514
|
reason: `weekly cap: task needs ~${needed.toLocaleString("en-US")} Sonnet-eq tokens (incl. ${config.safetyMarginTokens.toLocaleString("en-US")} safety margin) but only ~${budget.weeklyRemainingTokensEst.toLocaleString("en-US")} remain`
|
|
515
515
|
};
|
|
516
516
|
}
|
|
517
|
-
return {
|
|
517
|
+
return {
|
|
518
|
+
go: true,
|
|
519
|
+
reason: `${budget.sessionAvailable ? "session available" : "session check waived"} and estimated cost fits within weekly headroom`
|
|
520
|
+
};
|
|
518
521
|
}
|
|
519
522
|
|
|
520
523
|
// src/core/scheduler/native.ts
|
package/dist/cli/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
shouldIgnite,
|
|
26
26
|
startWatch,
|
|
27
27
|
writeUsageCache
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-HAERJCAI.js";
|
|
29
29
|
import {
|
|
30
30
|
MCP_STUB_MESSAGE
|
|
31
31
|
} from "../chunk-2NSOEZWY.js";
|
|
@@ -36,7 +36,7 @@ import { Command } from "commander";
|
|
|
36
36
|
// package.json
|
|
37
37
|
var package_default = {
|
|
38
38
|
name: "@pimmesz/afterburner",
|
|
39
|
-
version: "1.0.
|
|
39
|
+
version: "1.0.14",
|
|
40
40
|
description: "Convert idle Claude subscription quota into shippable engineering work: budget-aware trigger, bounded task selection, PR-only output.",
|
|
41
41
|
license: "Apache-2.0",
|
|
42
42
|
publishConfig: {
|
|
@@ -485,7 +485,7 @@ ${nextCmd(cmd("doctor"))}`;
|
|
|
485
485
|
const repoLine = repoNames.length <= 2 ? repoNames.join(", ") : `${repoNames.slice(0, 2).join(", ")} (and ${repoNames.length - 2} more)`;
|
|
486
486
|
const engineLine = config.agent.backend === "dry-run" ? "dry-run \u2014 simulation only; set agent.backend: 'claude-code' in the config to do real work" : config.agent.backend === "claude-code" ? "claude-code \u2014 spends subscription quota you already pay for; PRs only with --live" : "api-key \u2014 bills your Anthropic API account per token (real money); PRs only with --live";
|
|
487
487
|
const budgetLine = config.budget.provider === "manual" ? "manual \u2014 trusts budget.manual (automatic option: `afterburner statusline install`, then budget.provider: 'claude-usage')" : config.budget.provider === "claude-usage" ? "claude-usage \u2014 reads your real usage via the status line hook" : "claude-code-transcripts \u2014 estimates from local Claude Code session logs";
|
|
488
|
-
const nextNote = config.agent.backend === "dry-run" ? "previews the next task; nothing is executed or spent" : `previews the next task (live execution ships in a future release; ${cmd("run-once --live")} currently
|
|
488
|
+
const nextNote = config.agent.backend === "dry-run" ? "previews the next task; nothing is executed or spent" : `previews the next task (live execution ships in a future release; ${cmd("run-once --live")} currently arms LIVE then exits with a not-implemented error \u2014 no PR is opened)`;
|
|
489
489
|
const stopLine = `\`afterburner schedule uninstall\` (or Ctrl-C for watch); ${cmd("log")} lists every past run`;
|
|
490
490
|
if (opts.summary) {
|
|
491
491
|
return `${section(emoji.flame, "Ready")}
|
|
@@ -922,12 +922,11 @@ ${artifacts.removalHint}`);
|
|
|
922
922
|
}
|
|
923
923
|
|
|
924
924
|
// src/cli/commands/init.ts
|
|
925
|
-
var
|
|
925
|
+
var OFFERED_BACKENDS = ["dry-run", "claude-code"];
|
|
926
926
|
var BUDGET_PROVIDERS = ["manual", "claude-usage", "claude-code-transcripts"];
|
|
927
927
|
var ENGINE_CHOICES = {
|
|
928
928
|
"dry-run": "simulates everything, spends nothing. The safe default.",
|
|
929
|
-
"claude-code": "your Claude subscription via the local `claude` login. No extra money; it spends quota you already pay for."
|
|
930
|
-
"api-key": "bills your Anthropic API account per token. Every run costs real money."
|
|
929
|
+
"claude-code": "your Claude subscription via the local `claude` login. No extra money; it spends quota you already pay for."
|
|
931
930
|
};
|
|
932
931
|
var ENGINE_NOTES = {
|
|
933
932
|
"dry-run": "dry-run (simulates everything, spends nothing)",
|
|
@@ -1123,13 +1122,13 @@ async function collectAnswers(rl, opts, cwd = process.cwd()) {
|
|
|
1123
1122
|
let targetDir = cwd;
|
|
1124
1123
|
let target = join2(targetDir, "afterburner.config.mjs");
|
|
1125
1124
|
console.log(
|
|
1126
|
-
"Afterburner turns unused Claude subscription quota into small, reviewed pull requests.\nDry-run first: nothing executes or spends until a live engine is set in the config\nAND you pass --live. Three questions, then an optional health check.\n"
|
|
1125
|
+
"Afterburner turns unused Claude subscription quota into small, reviewed pull requests.\nDry-run first: nothing executes or spends until a live engine is set in the config\nAND you pass --live. (No run can open a PR yet \u2014 live execution ships in a future\nrelease.) Three questions, then an optional health check.\n"
|
|
1127
1126
|
);
|
|
1128
1127
|
console.log(bold("Step 1 of 3 \u2014 Engine (who does the work, and what it can spend)"));
|
|
1129
|
-
|
|
1128
|
+
OFFERED_BACKENDS.forEach((name, i) => {
|
|
1130
1129
|
console.log(` ${i + 1}. ${name}: ${ENGINE_CHOICES[name]}`);
|
|
1131
1130
|
});
|
|
1132
|
-
const backend =
|
|
1131
|
+
const backend = OFFERED_BACKENDS[await askChoice(rl, "Engine [1]: ", OFFERED_BACKENDS.length)] ?? "dry-run";
|
|
1133
1132
|
console.log(step("Engine", backend));
|
|
1134
1133
|
console.log(`
|
|
1135
1134
|
${bold("Step 2 of 3 \u2014 Repository (the allowlist of what it may touch)")}`);
|
|
@@ -1355,7 +1354,7 @@ function registerMcp(program2) {
|
|
|
1355
1354
|
// src/cli/commands/run-once.ts
|
|
1356
1355
|
function registerRunOnce(program2) {
|
|
1357
1356
|
program2.command("run-once").description(
|
|
1358
|
-
"Run one ignition cycle: pick at most one bounded task per
|
|
1357
|
+
"Run one ignition cycle: pick at most one bounded task per run (dry-run by default)"
|
|
1359
1358
|
).option("--config <path>", "path to a config file").option("--dry-run", "force a dry run (this is the default behavior)").option(
|
|
1360
1359
|
"--live",
|
|
1361
1360
|
"arm live execution; only takes effect when agent.backend is also a live engine in the config (two-part opt-in)"
|
|
@@ -1443,7 +1442,7 @@ ${section(emoji.rocket, "Next")}`);
|
|
|
1443
1442
|
console.log(
|
|
1444
1443
|
config.agent.backend === "dry-run" ? ` This was a preview. Live execution ships in a future release; once it does,
|
|
1445
1444
|
set agent.backend: 'claude-code' in ${filepath}, then: ${liveCmd}` : ` This was a preview. Live execution ships in a future release;
|
|
1446
|
-
${liveCmd} currently
|
|
1445
|
+
${liveCmd} currently arms LIVE then exits with a not-implemented error (no PR is opened).`
|
|
1447
1446
|
);
|
|
1448
1447
|
}
|
|
1449
1448
|
});
|
|
@@ -1911,7 +1910,7 @@ function renderWelcome(configPath) {
|
|
|
1911
1910
|
cmd("afterburner run-once --dry-run", "preview the next task (no changes made)"),
|
|
1912
1911
|
cmd(
|
|
1913
1912
|
"afterburner run-once --live",
|
|
1914
|
-
"real PRs (stubbed in this version;
|
|
1913
|
+
"real PRs (stubbed in this version; arms LIVE then errors out, no PR opened)"
|
|
1915
1914
|
),
|
|
1916
1915
|
cmd("afterburner log", "recent run history")
|
|
1917
1916
|
);
|
package/dist/core/index.d.ts
CHANGED
|
@@ -53,8 +53,8 @@ declare const budgetConfigSchema: z.ZodPrefault<z.ZodObject<{
|
|
|
53
53
|
}, z.core.$strip>>;
|
|
54
54
|
declare const agentConfigSchema: z.ZodPrefault<z.ZodObject<{
|
|
55
55
|
backend: z.ZodDefault<z.ZodEnum<{
|
|
56
|
-
"dry-run": "dry-run";
|
|
57
56
|
"claude-code": "claude-code";
|
|
57
|
+
"dry-run": "dry-run";
|
|
58
58
|
"api-key": "api-key";
|
|
59
59
|
}>>;
|
|
60
60
|
modelByCategory: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodEnum<{
|
|
@@ -115,8 +115,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
115
115
|
}, z.core.$strip>>;
|
|
116
116
|
agent: z.ZodPrefault<z.ZodObject<{
|
|
117
117
|
backend: z.ZodDefault<z.ZodEnum<{
|
|
118
|
-
"dry-run": "dry-run";
|
|
119
118
|
"claude-code": "claude-code";
|
|
119
|
+
"dry-run": "dry-run";
|
|
120
120
|
"api-key": "api-key";
|
|
121
121
|
}>>;
|
|
122
122
|
modelByCategory: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodEnum<{
|
|
@@ -673,10 +673,12 @@ declare class JsonlRunStore implements RunStore {
|
|
|
673
673
|
}
|
|
674
674
|
|
|
675
675
|
/**
|
|
676
|
-
* Notification seam.
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
676
|
+
* Notification seam. ConsoleNotifier always runs — its line is the audit trail
|
|
677
|
+
* that reaches the scheduler's stdout log — and an opt-in DesktopNotifier
|
|
678
|
+
* (OS-native banner, gated by notify.desktop) layers on top via
|
|
679
|
+
* CompositeNotifier/createNotifier. The pull request stays the real
|
|
680
|
+
* notification and the run store the source of truth. Notifiers shell out to
|
|
681
|
+
* platform tools; vendor SDKs are never bundled into core.
|
|
680
682
|
*/
|
|
681
683
|
interface Notifier {
|
|
682
684
|
notify(record: RunRecord): Promise<void>;
|
|
@@ -748,11 +750,12 @@ interface GateDecision {
|
|
|
748
750
|
reason: string;
|
|
749
751
|
}
|
|
750
752
|
/**
|
|
751
|
-
* Both-caps gate
|
|
752
|
-
*
|
|
753
|
-
*
|
|
754
|
-
*
|
|
755
|
-
*
|
|
753
|
+
* Both-caps gate encoded as a pure function: only fire when the estimated cost
|
|
754
|
+
* plus the safety margin fits inside the remaining weekly budget (with the
|
|
755
|
+
* configured headroom) — the non-negotiable weekly cap — AND, when
|
|
756
|
+
* config.requireSessionAvailable is set (the default), a 5-hour session window
|
|
757
|
+
* is also free. Reasons are returned, not just booleans, so every skipped run
|
|
758
|
+
* is explainable in the log.
|
|
756
759
|
*/
|
|
757
760
|
declare function shouldIgnite(budget: Budget, estCostSonnetTokens: number, config: GateConfig): GateDecision;
|
|
758
761
|
|
package/dist/core/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pimmesz/afterburner",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Convert idle Claude subscription quota into shippable engineering work: budget-aware trigger, bounded task selection, PR-only output.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|