Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/release-loop-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Release loop-gate

on:
push:
tags:
- 'loop-gate-v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish (e.g. loop-gate-v1.0.0)'
required: true
type: string

permissions:
contents: read
id-token: write

jobs:
test-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', github.event.inputs.tag) || github.ref }}

- uses: actions/setup-node@v7
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
cache: 'npm'
cache-dependency-path: tools/loop-gate/package-lock.json

- name: Ensure npm supports trusted publishing (OIDC)
run: npm install -g npm@latest

- name: Install, build, test
working-directory: tools/loop-gate
run: |
npm ci
npm run build
npm test

- name: Skip if version already published
id: check
working-directory: tools/loop-gate
run: |
VERSION=$(node -p "require('./package.json').version")
if npm view "@cobusgreyling/loop-gate@${VERSION}" version 2>/dev/null; then
echo "Version ${VERSION} already on npm — skipping publish."
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "Publishing @cobusgreyling/loop-gate@${VERSION}"
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish to npm
if: steps.check.outputs.skip != 'true'
working-directory: tools/loop-gate
run: npm publish --access public --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
21 changes: 16 additions & 5 deletions STATE.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
# Loop State — loop-engineering reference

Last run: 2026-07-17T09:41:37Z (automated daily-triage workflow)
Last run: 2026-07-19T18:55:00Z (scheduled maintenance)

## High Priority (loop is acting or waiting on human)

- Maintain loop readiness score ≥ 58 (current: **100**, level **L3**).
- Keep npm packages current after tool changes (tag `loop-audit-v*`, `loop-init-v*`, `loop-cost-v*` — see docs/RELEASE.md).

- npm publish in flight after this run: `loop-gate` 1.0.0, `loop-audit` 1.6.1, `loop-mcp-server` 1.1.0 (tags after merge).
- Configure npm trusted publisher / `NPM_TOKEN` for `@cobusgreyling/loop-gate` if first publish fails.

## Watch List

- Expand contributor failure stories (dependency sweeper, multi-loop).
- Collect a production story for Post-Merge Cleanup.
- Remaining Cursor doc gaps: [#220](https://github.com/cobusgreyling/loop-engineering/issues/220), [#223](https://github.com/cobusgreyling/loop-engineering/issues/223), [#224](https://github.com/cobusgreyling/loop-engineering/issues/224).
- Validate `loop-init` scaffolds on fresh projects across all patterns.
- Optional: StackMap outreach [#300](https://github.com/cobusgreyling/loop-engineering/issues/300).

## Housekeeping (2026-07-19 maintenance)

- Merged [#307](https://github.com/cobusgreyling/loop-engineering/pull/307) (Devin appendix → closes #200), [#302](https://github.com/cobusgreyling/loop-engineering/pull/302) (starter loop-gate), [#303](https://github.com/cobusgreyling/loop-engineering/pull/303) (MCP loop-gate), [#308](https://github.com/cobusgreyling/loop-engineering/pull/308) (audit/MCP cost fixes).
- Landed `release-loop-gate.yml` + RELEASE.md docs (supersedes conflicted [#305](https://github.com/cobusgreyling/loop-engineering/pull/305)).
- Landed loop-worktree week-two story from [#299](https://github.com/cobusgreyling/loop-engineering/pull/299) (story only; matrix noise dropped).
- Closed draft [#304](https://github.com/cobusgreyling/loop-engineering/pull/304) as superseded.
- Pruned automated star-history / daily-triage remote branches.

## Recent Noise (ignored this run)

- Star-history automation PRs (#309, #310) already merged.
- StackMap marketing issue #300.

---
Run log: Updated by `.github/workflows/daily-triage.yml`. See `LOOP.md` for cadence and gates.
Run log: Updated by `.github/workflows/daily-triage.yml`. See `LOOP.md` for cadence and gates.
10 changes: 8 additions & 2 deletions docs/RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Release playbook — npm packages

This repo ships eight public npm packages from `tools/`:
This repo ships nine public npm packages from `tools/`:

| Package | Directory | Release tag |
|---------|-----------|-------------|
Expand All @@ -11,6 +11,7 @@ This repo ships eight public npm packages from `tools/`:
| `@cobusgreyling/loop-context` | `tools/loop-context` | `loop-context-v*` |
| `@cobusgreyling/loop-mcp-server` | `tools/mcp-server` | `loop-mcp-server-v*` |
| `@cobusgreyling/loop-worktree` | `tools/loop-worktree` | `loop-worktree-v*` |
| `@cobusgreyling/loop-gate` | `tools/loop-gate` | `loop-gate-v*` |
| `@cobusgreyling/goal-audit` | `tools/goal-audit` | `goal-audit-v*` |

## One-time setup (trusted publishing — recommended)
Expand All @@ -26,6 +27,7 @@ Link npm to GitHub, then for **each package** on [npmjs.com](https://www.npmjs.c
| `@cobusgreyling/loop-context` | `cobusgreyling/loop-engineering` | `release-loop-context.yml` |
| `@cobusgreyling/loop-mcp-server` | `cobusgreyling/loop-engineering` | `release-loop-mcp-server.yml` |
| `@cobusgreyling/loop-worktree` | `cobusgreyling/loop-engineering` | `release-loop-worktree.yml` |
| `@cobusgreyling/loop-gate` | `cobusgreyling/loop-engineering` | `release-loop-gate.yml` |
| `@cobusgreyling/goal-audit` | `cobusgreyling/loop-engineering` | `release-goal-audit.yml` |

Names must match **exactly** (case-sensitive). No `NPM_TOKEN` secret is required when trusted publishing is configured.
Expand Down Expand Up @@ -73,12 +75,16 @@ git push origin loop-mcp-server-v1.0.0
git tag loop-worktree-v1.0.0
git push origin loop-worktree-v1.0.0

# loop-gate (path denylist + auto-merge allowlist)
git tag loop-gate-v1.0.0
git push origin loop-gate-v1.0.0

# goal-audit (Goal Engineering readiness scorer — companion repo)
git tag goal-audit-v1.0.2
git push origin goal-audit-v1.0.2
```

Workflows: `.github/workflows/release-loop-audit.yml`, `.github/workflows/release-loop-init.yml`, `.github/workflows/release-loop-cost.yml`, `.github/workflows/release-loop-sync.yml`, `.github/workflows/release-loop-context.yml`, `.github/workflows/release-loop-mcp-server.yml`, `.github/workflows/release-loop-worktree.yml`, `.github/workflows/release-goal-audit.yml`.
Workflows: `.github/workflows/release-loop-audit.yml`, `.github/workflows/release-loop-init.yml`, `.github/workflows/release-loop-cost.yml`, `.github/workflows/release-loop-sync.yml`, `.github/workflows/release-loop-context.yml`, `.github/workflows/release-loop-mcp-server.yml`, `.github/workflows/release-loop-worktree.yml`, `.github/workflows/release-loop-gate.yml`, `.github/workflows/release-goal-audit.yml`.

## Verify after publish

Expand Down
1 change: 1 addition & 0 deletions stories/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Real-world loop engineering — including failures. Contribute yours via [CONTRI
| [quant-loop-the-verifier-problem.md](./quant-loop-the-verifier-problem.md) | Quant research (domain) | Numerical checker beats LLM-as-verifier for backtests |
| [quant-loop-out-of-time.md](./quant-loop-out-of-time.md) | Quant research (domain) | Strategy passed research, failed out-of-time data |
| [ky-cut-surface-generation-vs-consequence.md](./ky-cut-surface-generation-vs-consequence.md) | Philosophy → loop bridge | Generation ≠ consequence; preserve the cut surface |
| [loop-worktree-week-two.md](./loop-worktree-week-two.md) | PR Babysitter + loop-worktree | Pair worktrees with `loop-context --check`; exact `outcome: failure` enum |

**Template for new stories:**

Expand Down
83 changes: 83 additions & 0 deletions stories/loop-worktree-week-two.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Week Two with loop-worktree: PR Babysitter, one fix at a time

**Pattern:** PR Babysitter
**Tool:** loop-worktree (paired with loop-context)

## What I was doing

I was running a small PR Babysitter loop: watch a PR, try a fix in isolation,
verify it, and only escalate to a human if the fix doesn't land. The part I
wanted to get right this week was making retries safe — if attempt #1 fails,
attempt #2 shouldn't be fighting attempt #1 for the same branch.

## The workflow

For each fix attempt, I create an isolated worktree keyed to the run:

```
npx @cobusgreyling/loop-worktree create --run-id pr-42-fix-1 --pattern pr-babysitter
```

That gives me a fresh checkout under `.loop-worktrees/pr-42-fix-1` on its own
branch (`loop/pr-42-fix-1`), tracked in `.loop-worktrees/manifest.json` — so
nothing touches the branch another attempt might still be using.

Once the verifier rejects an attempt, I mark it rather than deleting it
immediately — that keeps the audit trail intact:

```
npx @cobusgreyling/loop-worktree mark --run-id pr-42-fix-1 --status rejected
```

`list` gives me a quick read on what's currently tracked:

```
npx @cobusgreyling/loop-worktree list
```

And periodically I sweep anything rejected or escalated:

```
npx @cobusgreyling/loop-worktree cleanup --status rejected --older-than 24h
```

## Pairing with loop-context --check

Before letting the loop retry again, I run the ledger through
`loop-context --check` so a stuck fix doesn't just keep burning attempts:

```
npx @cobusgreyling/loop-context --check --ledger run.json --stagnation 3 --json
```

With three identical failures in a row it stayed green (`shouldContinue: true`),
but on the fourth repeat of the same error it correctly flipped to
`escalate: true` with exit code 2 — which is the signal I use to stop the loop
and hand the PR back to a human instead of trying a fifth time.

## The surprise

The gotcha that cost me the most time: `--check`'s stagnation trigger only
recognizes attempts with `"outcome": "failure"` exactly. I'd first logged
attempts as `"outcome": "fail"` — `--summary` and `--status` happily counted
those as failures and showed the repeated error, so everything *looked*
right, but `--check` never escalated no matter how many times the same error
repeated. Nothing errors out to tell you the value was wrong; the breaker
just quietly stays at "continue." Since the whole point of pairing
loop-worktree with loop-context is to stop a bad retry loop before it wastes
a worktree (and tokens) on a fix that isn't working, a silently-inert circuit
breaker is exactly the failure mode you don't want.

Separately, a smaller but good surprise: `cleanup --older-than 24h` refused
to remove a worktree I'd just marked rejected seconds earlier — it only acts
once the attempt is actually old enough (or you pass `--force`). That's the
right default; I just didn't expect it on first try and thought the command
had silently no-op'd.

## What I'd change

I'd want `--check` to validate the `outcome` field against the documented
enum and fail loudly (or at least warn) on an unrecognized value, instead of
silently treating it as a no-op for the stagnation/no-progress triggers while
`--summary` keeps counting it as a failure. Right now the two commands can
disagree about the same ledger without telling you.
2 changes: 1 addition & 1 deletion tools/loop-audit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cobusgreyling/loop-audit",
"version": "1.6.0",
"version": "1.6.1",
"description": "Loop engineering readiness auditor. Compute Loop Readiness Score (L0-L3), detect activity, and get actionable suggestions. npx @cobusgreyling/loop-audit . --suggest",
"type": "module",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion tools/mcp-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cobusgreyling/loop-mcp-server",
"version": "1.0.0",
"version": "1.1.0",
"description": "MCP server for loop-engineering — exposes patterns, skills, state, and audit tools as runtime-queryable resources for AI agents",
"type": "module",
"bin": {
Expand Down