From 2e5628a898f0db4924c27763ffe98624a35a17b6 Mon Sep 17 00:00:00 2001 From: "K.ShivaKumar" Date: Mon, 29 Jun 2026 21:40:57 +0530 Subject: [PATCH 1/2] feat: show elapsed time per step in runner output --- .loopflow/loops/debt-audit.yaml | 33 ++++++++++++++++ .loopflow/loops/docs-sync.yaml | 41 +++++++++++++++++++ .loopflow/loops/release-check.yaml | 63 ++++++++++++++++++++++++++++++ .loopflow/loops/test-and-fix.yaml | 44 +++++++++++++++++++++ .loopflow/memory/test-and-fix.md | 9 +++++ package-lock.json | 34 +--------------- src/commands/run.ts | 5 ++- src/core/runner.ts | 2 + 8 files changed, 198 insertions(+), 33 deletions(-) create mode 100644 .loopflow/loops/debt-audit.yaml create mode 100644 .loopflow/loops/docs-sync.yaml create mode 100644 .loopflow/loops/release-check.yaml create mode 100644 .loopflow/loops/test-and-fix.yaml create mode 100644 .loopflow/memory/test-and-fix.md diff --git a/.loopflow/loops/debt-audit.yaml b/.loopflow/loops/debt-audit.yaml new file mode 100644 index 0000000..577802d --- /dev/null +++ b/.loopflow/loops/debt-audit.yaml @@ -0,0 +1,33 @@ +# A discovery loop: run it on a schedule and it builds a living debt report. +# Memory makes each run aware of what the last run found. +name: debt-audit +description: Audit the codebase for tech debt and maintain a report that evolves run over run. + +budget: + max_usd: 1.50 + max_iterations: 1 + +defaults: + permission_mode: acceptEdits + +steps: + - id: audit + role: > + You are a pragmatic tech-debt auditor. You report what genuinely slows + this team down, not stylistic nitpicks. + prompt: | + Audit this repository for technical debt: + + - TODO/FIXME/HACK comments and how stale they are + - dead code and unused exports + - outdated or vulnerable dependencies + - duplicated logic that should be consolidated + - missing test coverage on load-bearing modules + + Your loop memory contains the findings of previous audits. Compare against + them: note what was fixed since last time, what is new, and what keeps + being ignored. + + Write the full report to `.loopflow/reports/debt-audit.md` (overwrite it), + ordered by impact. End your response with a five-line executive summary — + that summary is what the next run will see in its memory. diff --git a/.loopflow/loops/docs-sync.yaml b/.loopflow/loops/docs-sync.yaml new file mode 100644 index 0000000..e866157 --- /dev/null +++ b/.loopflow/loops/docs-sync.yaml @@ -0,0 +1,41 @@ +# Keeps documentation honest: one agent updates docs to match the code, +# a gate verifies every claim against the actual source. +name: docs-sync +description: Detect documentation that has drifted from the code, fix it, and verify the fixes. + +budget: + max_usd: 2.00 + max_iterations: 2 + +worktree: true + +defaults: + permission_mode: acceptEdits + +steps: + - id: sync + role: > + You are a technical writer who reads source code. You never document + behavior you have not verified in the code itself. + prompt: | + Compare this project's documentation (README and any docs/ directory) + against the actual code: + + - CLI flags, commands, and options that were renamed or removed + - code examples that no longer compile or run + - described behavior that no longer matches the implementation + - new public functionality that is entirely undocumented + + Fix every stale section you find. Keep the existing tone and structure. + List each change you made and the source file that justifies it. + + - id: verify + gate: true + role: > + You are a reviewer who checks documentation claims against source code, + line by line. + prompt: | + A previous agent updated the documentation in this working tree to match + the code. Inspect the diff and verify each changed claim against the + actual source. Fail if any documented flag, example, or behavior still + does not match the implementation. diff --git a/.loopflow/loops/release-check.yaml b/.loopflow/loops/release-check.yaml new file mode 100644 index 0000000..7968d8d --- /dev/null +++ b/.loopflow/loops/release-check.yaml @@ -0,0 +1,63 @@ +# Run before every release cut. One agent fixes everything blocking the +# release; a gate verifies the fixes are genuine before you tag. +# +# Covers: failing tests, lint errors, coverage regression, and debug +# artifacts left in the diff. Adapt the prompts to match your project's +# specific toolchain (e.g. replace "npm test" with "pnpm test", add +# "cargo clippy", etc.). +name: release-check +description: Fix all pre-release blockers — tests, lint, coverage — and verify fixes are real. + +budget: + max_usd: 4.00 + max_iterations: 3 + +defaults: + permission_mode: acceptEdits + +steps: + - id: fix + role: > + You are a careful maintainer preparing a release. You fix root causes — + never symptoms. You never modify test assertions to make a test pass, + and you never delete or skip a test to make coverage look clean. + prompt: | + This project is about to cut a release. Run the full pre-release checklist: + + 1. Run the test suite. Fix any failures at the root cause — not by + modifying tests or lowering thresholds. + 2. Run the linter (if configured). Fix any errors; treat warnings as + errors if they appear on changed lines. + 3. Check that code coverage meets the project threshold. If it has + dropped, add tests for the uncovered paths — do not lower the + threshold. + 4. Scan the diff for anything that should not ship: debug statements, + console.log calls added during development, TODO comments introduced + on this branch, commented-out code blocks. + + Summarize what was failing, the root cause of each issue, and exactly + what you changed. + + - id: verify + gate: true + role: > + You are a skeptical senior engineer doing a final release sign-off. + You did not write these fixes. You verify every claim with evidence — + you never take another agent's word for it. + prompt: | + The previous agent claims the codebase is release-ready. Verify that. + + 1. Run the test suite yourself — confirm it is actually green. + 2. Run git diff — read every changed line in the source files. + 3. For each fix: does it address the root cause, or does it just make + the symptom disappear? Look specifically for: lowered thresholds, + weakened assertions, skipped tests, swallowed exceptions. + 4. Check that no debug code, stray logs, or development artifacts + remain in the diff. + 5. If coverage was an issue: confirm the new tests actually exercise + the logic, not just inflate the line count. + + VERDICT: PASS — if the codebase is genuinely release-ready. + VERDICT: FAIL — if anything is wrong. Be specific: your feedback is + the only instruction the next agent gets, so name the exact file, + line, and issue. diff --git a/.loopflow/loops/test-and-fix.yaml b/.loopflow/loops/test-and-fix.yaml new file mode 100644 index 0000000..dee3995 --- /dev/null +++ b/.loopflow/loops/test-and-fix.yaml @@ -0,0 +1,44 @@ +# The canonical loop: one agent fixes, a different agent verifies. +# The fixer never grades its own homework. +name: test-and-fix +description: Run the test suite, fix any failures, and have an independent reviewer verify the fix. + +budget: + max_usd: 2.00 + max_iterations: 3 + +defaults: + permission_mode: acceptEdits + +steps: + - id: fix + role: > + You are a careful maintainer of this codebase. You make the smallest + change that fixes the problem, and you never weaken or delete a test + to make it pass. + prompt: | + Run this project's test suite. If everything passes, say so and stop. + + If there are failures: + 1. Diagnose the root cause of each failure. + 2. Fix the underlying code (not the test, unless the test itself is wrong — + and if so, explain why). + 3. Re-run the tests to confirm they pass. + + Summarize what was failing, what you changed, and why. + + - id: review + gate: true + role: > + You are a skeptical senior engineer reviewing a change you did not write. + You trust nothing without evidence. + prompt: | + A previous agent claims to have fixed failing tests in this working tree. + Verify the claim: + + 1. Inspect the diff (git diff) and judge whether the changes fix root + causes or merely mask symptoms. + 2. Re-run the test suite yourself and confirm it passes. + 3. Check that no test was weakened, skipped, or deleted to force a pass. + + Pass only if the fix is genuine and the suite is green. diff --git a/.loopflow/memory/test-and-fix.md b/.loopflow/memory/test-and-fix.md new file mode 100644 index 0000000..47f41fe --- /dev/null +++ b/.loopflow/memory/test-and-fix.md @@ -0,0 +1,9 @@ +# Loop memory: test-and-fix + +## Run 2026-06-29T16:06:53.365Z +- Outcome: error (iterations used: 1) +- Cost: $0.00 +- Steps: fix ✗ (error) + +### Notes +step "fix" failed: claude reported an error diff --git a/package-lock.json b/package-lock.json index 1165db0..3bc1a1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "loopflow", + "name": "@loopflow/cli", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "loopflow", + "name": "@loopflow/cli", "version": "0.1.0", "license": "MIT", "dependencies": { @@ -191,9 +191,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -211,9 +208,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -231,9 +225,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -251,9 +242,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -271,9 +259,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -291,9 +276,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -825,9 +807,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -849,9 +828,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -873,9 +849,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -897,9 +870,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/src/commands/run.ts b/src/commands/run.ts index c6cc31b..646ce2b 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -118,8 +118,11 @@ function reporter(options: RunCommandOptions): RunnerEvents { ? pc.red("gate FAIL") : pc.green("done") : pc.red("ERROR"); + const duration = typeof run.durationMs === 'number' && run.durationMs > 0 + ? ` · ${pc.dim(`${(run.durationMs / 1000).toFixed(1)}s`)}` + : ''; const resume = run.sessionId ? pc.dim(` · resume: claude --resume ${run.sessionId}`) : ""; - console.log(` ${icon} ${status} · ${pc.dim(`$${run.costUsd.toFixed(2)}`)}${resume}`); + console.log(` ${icon} ${status} · ${pc.dim(`$${run.costUsd.toFixed(2)}`)}${duration}${resume}`); }, onGateFail(_stepId: string, feedback: string) { diff --git a/src/core/runner.ts b/src/core/runner.ts index 9d93ad7..aa4415e 100644 --- a/src/core/runner.ts +++ b/src/core/runner.ts @@ -16,6 +16,7 @@ export interface StepRun { gatePassed?: boolean; costUsd: number; sessionId: string | undefined; + durationMs?: number; } export interface RunResult { @@ -128,6 +129,7 @@ export async function runLoop(loop: LoopConfig, options: RunOptions): Promise Date: Wed, 1 Jul 2026 18:59:29 +0530 Subject: [PATCH 2/2] chore: remove local artifacts and align with project style --- .loopflow/loops/debt-audit.yaml | 33 ---------------- .loopflow/loops/docs-sync.yaml | 41 ------------------- .loopflow/loops/release-check.yaml | 63 ------------------------------ .loopflow/loops/test-and-fix.yaml | 44 --------------------- .loopflow/memory/test-and-fix.md | 9 ----- package-lock.json | 34 +++++++++++++++- src/commands/run.ts | 4 +- src/core/runner.ts | 4 +- 8 files changed, 36 insertions(+), 196 deletions(-) delete mode 100644 .loopflow/loops/debt-audit.yaml delete mode 100644 .loopflow/loops/docs-sync.yaml delete mode 100644 .loopflow/loops/release-check.yaml delete mode 100644 .loopflow/loops/test-and-fix.yaml delete mode 100644 .loopflow/memory/test-and-fix.md diff --git a/.loopflow/loops/debt-audit.yaml b/.loopflow/loops/debt-audit.yaml deleted file mode 100644 index 577802d..0000000 --- a/.loopflow/loops/debt-audit.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# A discovery loop: run it on a schedule and it builds a living debt report. -# Memory makes each run aware of what the last run found. -name: debt-audit -description: Audit the codebase for tech debt and maintain a report that evolves run over run. - -budget: - max_usd: 1.50 - max_iterations: 1 - -defaults: - permission_mode: acceptEdits - -steps: - - id: audit - role: > - You are a pragmatic tech-debt auditor. You report what genuinely slows - this team down, not stylistic nitpicks. - prompt: | - Audit this repository for technical debt: - - - TODO/FIXME/HACK comments and how stale they are - - dead code and unused exports - - outdated or vulnerable dependencies - - duplicated logic that should be consolidated - - missing test coverage on load-bearing modules - - Your loop memory contains the findings of previous audits. Compare against - them: note what was fixed since last time, what is new, and what keeps - being ignored. - - Write the full report to `.loopflow/reports/debt-audit.md` (overwrite it), - ordered by impact. End your response with a five-line executive summary — - that summary is what the next run will see in its memory. diff --git a/.loopflow/loops/docs-sync.yaml b/.loopflow/loops/docs-sync.yaml deleted file mode 100644 index e866157..0000000 --- a/.loopflow/loops/docs-sync.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Keeps documentation honest: one agent updates docs to match the code, -# a gate verifies every claim against the actual source. -name: docs-sync -description: Detect documentation that has drifted from the code, fix it, and verify the fixes. - -budget: - max_usd: 2.00 - max_iterations: 2 - -worktree: true - -defaults: - permission_mode: acceptEdits - -steps: - - id: sync - role: > - You are a technical writer who reads source code. You never document - behavior you have not verified in the code itself. - prompt: | - Compare this project's documentation (README and any docs/ directory) - against the actual code: - - - CLI flags, commands, and options that were renamed or removed - - code examples that no longer compile or run - - described behavior that no longer matches the implementation - - new public functionality that is entirely undocumented - - Fix every stale section you find. Keep the existing tone and structure. - List each change you made and the source file that justifies it. - - - id: verify - gate: true - role: > - You are a reviewer who checks documentation claims against source code, - line by line. - prompt: | - A previous agent updated the documentation in this working tree to match - the code. Inspect the diff and verify each changed claim against the - actual source. Fail if any documented flag, example, or behavior still - does not match the implementation. diff --git a/.loopflow/loops/release-check.yaml b/.loopflow/loops/release-check.yaml deleted file mode 100644 index 7968d8d..0000000 --- a/.loopflow/loops/release-check.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# Run before every release cut. One agent fixes everything blocking the -# release; a gate verifies the fixes are genuine before you tag. -# -# Covers: failing tests, lint errors, coverage regression, and debug -# artifacts left in the diff. Adapt the prompts to match your project's -# specific toolchain (e.g. replace "npm test" with "pnpm test", add -# "cargo clippy", etc.). -name: release-check -description: Fix all pre-release blockers — tests, lint, coverage — and verify fixes are real. - -budget: - max_usd: 4.00 - max_iterations: 3 - -defaults: - permission_mode: acceptEdits - -steps: - - id: fix - role: > - You are a careful maintainer preparing a release. You fix root causes — - never symptoms. You never modify test assertions to make a test pass, - and you never delete or skip a test to make coverage look clean. - prompt: | - This project is about to cut a release. Run the full pre-release checklist: - - 1. Run the test suite. Fix any failures at the root cause — not by - modifying tests or lowering thresholds. - 2. Run the linter (if configured). Fix any errors; treat warnings as - errors if they appear on changed lines. - 3. Check that code coverage meets the project threshold. If it has - dropped, add tests for the uncovered paths — do not lower the - threshold. - 4. Scan the diff for anything that should not ship: debug statements, - console.log calls added during development, TODO comments introduced - on this branch, commented-out code blocks. - - Summarize what was failing, the root cause of each issue, and exactly - what you changed. - - - id: verify - gate: true - role: > - You are a skeptical senior engineer doing a final release sign-off. - You did not write these fixes. You verify every claim with evidence — - you never take another agent's word for it. - prompt: | - The previous agent claims the codebase is release-ready. Verify that. - - 1. Run the test suite yourself — confirm it is actually green. - 2. Run git diff — read every changed line in the source files. - 3. For each fix: does it address the root cause, or does it just make - the symptom disappear? Look specifically for: lowered thresholds, - weakened assertions, skipped tests, swallowed exceptions. - 4. Check that no debug code, stray logs, or development artifacts - remain in the diff. - 5. If coverage was an issue: confirm the new tests actually exercise - the logic, not just inflate the line count. - - VERDICT: PASS — if the codebase is genuinely release-ready. - VERDICT: FAIL — if anything is wrong. Be specific: your feedback is - the only instruction the next agent gets, so name the exact file, - line, and issue. diff --git a/.loopflow/loops/test-and-fix.yaml b/.loopflow/loops/test-and-fix.yaml deleted file mode 100644 index dee3995..0000000 --- a/.loopflow/loops/test-and-fix.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# The canonical loop: one agent fixes, a different agent verifies. -# The fixer never grades its own homework. -name: test-and-fix -description: Run the test suite, fix any failures, and have an independent reviewer verify the fix. - -budget: - max_usd: 2.00 - max_iterations: 3 - -defaults: - permission_mode: acceptEdits - -steps: - - id: fix - role: > - You are a careful maintainer of this codebase. You make the smallest - change that fixes the problem, and you never weaken or delete a test - to make it pass. - prompt: | - Run this project's test suite. If everything passes, say so and stop. - - If there are failures: - 1. Diagnose the root cause of each failure. - 2. Fix the underlying code (not the test, unless the test itself is wrong — - and if so, explain why). - 3. Re-run the tests to confirm they pass. - - Summarize what was failing, what you changed, and why. - - - id: review - gate: true - role: > - You are a skeptical senior engineer reviewing a change you did not write. - You trust nothing without evidence. - prompt: | - A previous agent claims to have fixed failing tests in this working tree. - Verify the claim: - - 1. Inspect the diff (git diff) and judge whether the changes fix root - causes or merely mask symptoms. - 2. Re-run the test suite yourself and confirm it passes. - 3. Check that no test was weakened, skipped, or deleted to force a pass. - - Pass only if the fix is genuine and the suite is green. diff --git a/.loopflow/memory/test-and-fix.md b/.loopflow/memory/test-and-fix.md deleted file mode 100644 index 47f41fe..0000000 --- a/.loopflow/memory/test-and-fix.md +++ /dev/null @@ -1,9 +0,0 @@ -# Loop memory: test-and-fix - -## Run 2026-06-29T16:06:53.365Z -- Outcome: error (iterations used: 1) -- Cost: $0.00 -- Steps: fix ✗ (error) - -### Notes -step "fix" failed: claude reported an error diff --git a/package-lock.json b/package-lock.json index 3bc1a1b..1165db0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@loopflow/cli", + "name": "loopflow", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@loopflow/cli", + "name": "loopflow", "version": "0.1.0", "license": "MIT", "dependencies": { @@ -191,6 +191,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -208,6 +211,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -225,6 +231,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -242,6 +251,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -259,6 +271,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -276,6 +291,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -807,6 +825,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -828,6 +849,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -849,6 +873,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -870,6 +897,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/src/commands/run.ts b/src/commands/run.ts index 646ce2b..50d43db 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -118,9 +118,9 @@ function reporter(options: RunCommandOptions): RunnerEvents { ? pc.red("gate FAIL") : pc.green("done") : pc.red("ERROR"); - const duration = typeof run.durationMs === 'number' && run.durationMs > 0 + const duration = typeof run.durationMs === "number" && run.durationMs > 0 ? ` · ${pc.dim(`${(run.durationMs / 1000).toFixed(1)}s`)}` - : ''; + : ""; const resume = run.sessionId ? pc.dim(` · resume: claude --resume ${run.sessionId}`) : ""; console.log(` ${icon} ${status} · ${pc.dim(`$${run.costUsd.toFixed(2)}`)}${duration}${resume}`); }, diff --git a/src/core/runner.ts b/src/core/runner.ts index aa4415e..7b5a4a1 100644 --- a/src/core/runner.ts +++ b/src/core/runner.ts @@ -16,7 +16,7 @@ export interface StepRun { gatePassed?: boolean; costUsd: number; sessionId: string | undefined; - durationMs?: number; + durationMs?: number; } export interface RunResult { @@ -129,7 +129,7 @@ export async function runLoop(loop: LoopConfig, options: RunOptions): Promise