@cobusgreyling/loop-init 1.3.3 → 1.4.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.
- package/README.md +6 -0
- package/dist/cli.js +20 -0
- package/package.json +1 -1
- package/templates/SKILL.md.loop-guard +15 -17
- package/templates/SKILL.md.loop-intake +71 -0
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Scaffold loop engineering starters into your project by pattern and tool.
|
|
|
4
4
|
|
|
5
5
|
**npx @cobusgreyling/loop-init . --pattern daily-triage --tool grok** works immediately.
|
|
6
6
|
|
|
7
|
+
See [docs/loop-init-validation.md](../../docs/loop-init-validation.md) for a validated pattern × --tool matrix.
|
|
8
|
+
|
|
7
9
|
## Install & Run
|
|
8
10
|
|
|
9
11
|
```bash
|
|
@@ -38,6 +40,10 @@ Fix-capable patterns (`pr-babysitter`, `ci-sweeper`, `dependency-sweeper`, `post
|
|
|
38
40
|
|
|
39
41
|
The ledger's `pattern`/`level` let `loop-guard` size the breaker's `--token-budget` from [`loop-cost`](../loop-cost)'s realistic per-run estimate instead of a hand-typed number. The breaker escalates (same error N× in a row, too many consecutive failures, token budget, or iteration cap) instead of looping in vain. Report-only patterns skip it.
|
|
40
42
|
|
|
43
|
+
Patterns that act on human-authored, often underspecified input (`issue-triage`) also get an **intake** skill:
|
|
44
|
+
|
|
45
|
+
- `loop-intake` skill — when a work item is too vague to verify "done", it asks one question at a time, pushes for exact values, and writes an open question + `needs-human` escalation instead of guessing. Clarifying up front keeps the loop from burning fix attempts on a goal that was never well defined.
|
|
46
|
+
|
|
41
47
|
Every scaffold also creates:
|
|
42
48
|
|
|
43
49
|
- `loop-budget.md` — pattern-specific daily caps and kill switch
|
package/dist/cli.js
CHANGED
|
@@ -30,6 +30,12 @@ const PATTERNS_NEEDING_FIX = new Set([
|
|
|
30
30
|
'dependency-sweeper',
|
|
31
31
|
'post-merge-cleanup',
|
|
32
32
|
]);
|
|
33
|
+
/**
|
|
34
|
+
* Patterns that act on human-authored, often underspecified input (issues).
|
|
35
|
+
* They get the loop-intake skill so the loop clarifies a vague item or escalates
|
|
36
|
+
* it instead of guessing and burning fix attempts.
|
|
37
|
+
*/
|
|
38
|
+
const PATTERNS_NEEDING_INTAKE = new Set(['issue-triage']);
|
|
33
39
|
const STATE_FILES = {
|
|
34
40
|
'daily-triage': 'STATE.md',
|
|
35
41
|
'pr-babysitter': 'pr-babysitter-state.md',
|
|
@@ -190,6 +196,15 @@ async function scaffoldCircuitBreaker(pattern, tool, targetDir, templatesRoot, d
|
|
|
190
196
|
await writeFile(ledgerPath, seed);
|
|
191
197
|
console.log(' created: loop-ledger.json (circuit breaker)');
|
|
192
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Scaffold the loop-intake skill for patterns that receive ambiguous human
|
|
201
|
+
* input, so the loop sharpens the goal (or escalates) before acting on it.
|
|
202
|
+
*/
|
|
203
|
+
async function scaffoldIntake(pattern, tool, targetDir, templatesRoot, dryRun) {
|
|
204
|
+
if (!PATTERNS_NEEDING_INTAKE.has(pattern))
|
|
205
|
+
return;
|
|
206
|
+
await copyTemplateSkill(templatesRoot, 'SKILL.md.loop-intake', targetDir, tool, 'loop-intake', dryRun);
|
|
207
|
+
}
|
|
193
208
|
function formatTokenCap(n) {
|
|
194
209
|
if (n >= 1_000_000)
|
|
195
210
|
return `${n / 1_000_000}M`;
|
|
@@ -492,6 +507,7 @@ Examples:
|
|
|
492
507
|
await copyL2Templates(pattern, tool, targetDir, templatesRoot, dryRun);
|
|
493
508
|
await scaffoldCircuitBreaker(pattern, tool, targetDir, templatesRoot, dryRun);
|
|
494
509
|
await scaffoldObservability(pattern, tool, targetDir, templatesRoot, dryRun);
|
|
510
|
+
await scaffoldIntake(pattern, tool, targetDir, templatesRoot, dryRun);
|
|
495
511
|
await scaffoldConstraints(targetDir, templatesRoot, tool, dryRun);
|
|
496
512
|
if (tool !== 'opencode' && !dryRun && !(await exists(path.join(targetDir, 'AGENTS.md')))) {
|
|
497
513
|
const agentsTemplate = `# AGENTS.md
|
|
@@ -529,6 +545,10 @@ npm run lint
|
|
|
529
545
|
console.log('Circuit breaker wired (loop-guard skill + loop-ledger.json):');
|
|
530
546
|
console.log(' npx @cobusgreyling/loop-context --check --ledger loop-ledger.json');
|
|
531
547
|
}
|
|
548
|
+
if (PATTERNS_NEEDING_INTAKE.has(pattern)) {
|
|
549
|
+
console.log('');
|
|
550
|
+
console.log('Intake wired (loop-intake skill): clarify a vague item or escalate before acting.');
|
|
551
|
+
}
|
|
532
552
|
console.log('');
|
|
533
553
|
console.log(`First loop (${tool}):`);
|
|
534
554
|
console.log(` ${firstLoopCommand(pattern, tool)}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobusgreyling/loop-init",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Scaffold loop engineering patterns and starters into any project. Supports Grok, Claude Code, Codex, Opencode and more. npx @cobusgreyling/loop-init . --pattern daily-triage --tool opencode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,30 +38,27 @@ After every iteration, append what you just tried:
|
|
|
38
38
|
`outcome` is `success | failure | noop`. Always include `error` on failures —
|
|
39
39
|
that is how the breaker detects a repeated (stagnant) failure.
|
|
40
40
|
|
|
41
|
-
## Size the token budget from the pattern
|
|
41
|
+
## Size the token budget from the pattern
|
|
42
42
|
|
|
43
|
-
Don't hand-type a token cap — derive it from the
|
|
44
|
-
|
|
45
|
-
[`loop-cost`](https://github.com/cobusgreyling/loop-engineering/tree/main/tools/loop-cost)
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
Don't hand-type a token cap — `loop-context` can derive it directly from the
|
|
44
|
+
pattern's realistic per-run cost
|
|
45
|
+
([`loop-cost`](https://github.com/cobusgreyling/loop-engineering/tree/main/tools/loop-cost)
|
|
46
|
+
computes this from `patterns/registry.yaml`) so the breaker trips on genuine
|
|
47
|
+
cost blowup, not a made-up number. Substitute the ledger's own `pattern`/`level`
|
|
48
|
+
(here: `ci-sweeper` / `L2`):
|
|
48
49
|
|
|
49
50
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>process.stdout.write(String(JSON.parse(d).scenarios.realistic.tokensPerRun)))')
|
|
51
|
+
npx @cobusgreyling/loop-context --check --ledger loop-ledger.json \
|
|
52
|
+
--budget-from-pattern ci-sweeper --budget-level L2
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
`scenarios.realistic.tokensPerRun` is a rounded integer, so it feeds
|
|
56
|
-
`--token-budget` directly. The two tools stay independent — this is shell
|
|
57
|
-
wiring, not a code dependency.
|
|
58
|
-
|
|
59
55
|
## Before each iteration
|
|
60
56
|
|
|
61
57
|
1. Append the previous attempt to `loop-ledger.json`.
|
|
62
58
|
2. Run the breaker with the resolved budget:
|
|
63
59
|
```bash
|
|
64
|
-
npx @cobusgreyling/loop-context --check --ledger loop-ledger.json
|
|
60
|
+
npx @cobusgreyling/loop-context --check --ledger loop-ledger.json \
|
|
61
|
+
--budget-from-pattern ci-sweeper --budget-level L2
|
|
65
62
|
```
|
|
66
63
|
3. Act on the exit code:
|
|
67
64
|
- **0** → continue. Optionally trim the next prompt first:
|
|
@@ -83,12 +80,13 @@ wiring, not a code dependency.
|
|
|
83
80
|
- Never widen thresholds just to keep looping — escalation is a feature, not a failure.
|
|
84
81
|
- Never edit the ledger to hide a repeated error; the breaker exists to catch it.
|
|
85
82
|
- Defaults: 3× same error, 5 consecutive failures, 10 iterations. Tune with
|
|
86
|
-
`--stagnation`, `--no-progress`, `--max-iterations`,
|
|
83
|
+
`--stagnation`, `--no-progress`, `--max-iterations`, or an explicit
|
|
84
|
+
`--token-budget` (wins over `--budget-from-pattern` if both are given).
|
|
87
85
|
|
|
88
86
|
## Interaction with other skills
|
|
89
87
|
|
|
90
88
|
- `minimal-fix` / `ci-triage` — record each attempt's outcome + error in the ledger.
|
|
91
89
|
- `loop-verifier` — a verifier rejection is a `failure`; log it so repeats trip the breaker.
|
|
92
90
|
- `loop-constraints` — honors "escalate after N attempts"; this skill makes it mechanical.
|
|
93
|
-
- `loop-budget` — the per-run
|
|
94
|
-
|
|
91
|
+
- `loop-budget` — the per-run budget here comes from `--budget-from-pattern`;
|
|
92
|
+
loop-budget.md still governs the *daily* cap across runs.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: loop-intake
|
|
3
|
+
description: >
|
|
4
|
+
Clarify an ambiguous goal or work item BEFORE the loop acts on it. Runs at the
|
|
5
|
+
front of a run when the assigned task is underspecified. Ask one question at a
|
|
6
|
+
time, push for exact values, and escalate instead of guessing.
|
|
7
|
+
user_invocable: true
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Loop Intake - Clarify Before You Act
|
|
11
|
+
|
|
12
|
+
Autonomous loops waste attempts (and budget) when they guess at a vague goal.
|
|
13
|
+
This skill runs FIRST, before triage or any action skill, whenever the item the
|
|
14
|
+
loop is about to work on is not specific enough to verify "done".
|
|
15
|
+
|
|
16
|
+
## When to run
|
|
17
|
+
|
|
18
|
+
Run intake when the goal or work item is missing any of:
|
|
19
|
+
|
|
20
|
+
- a single, testable definition of done
|
|
21
|
+
- the exact scope (which repo / branch / paths / tickets)
|
|
22
|
+
- concrete values a fix would depend on (error text, thresholds, versions)
|
|
23
|
+
|
|
24
|
+
If the goal is already specific and verifiable, skip intake and proceed.
|
|
25
|
+
|
|
26
|
+
## How to clarify (one question at a time)
|
|
27
|
+
|
|
28
|
+
1. Read the current state file and the item (issue, PR, request) in full. Do NOT
|
|
29
|
+
re-ask anything already answered there.
|
|
30
|
+
2. Ask the SINGLE most decision-blocking question. Wait for the answer.
|
|
31
|
+
3. Push for an exact value. "It should be fast" becomes "What p95 latency, in
|
|
32
|
+
ms?". "Add a limit" becomes "How many per minute?". Re-ask once if the answer
|
|
33
|
+
is still vague.
|
|
34
|
+
4. Stop as soon as the goal is verifiable. Do not interrogate for its own sake.
|
|
35
|
+
|
|
36
|
+
Ask in behavior terms, not implementation: what the system must do, what the user
|
|
37
|
+
sees, which values matter. Not: which function, table, or endpoint.
|
|
38
|
+
|
|
39
|
+
## When an answer stays vague
|
|
40
|
+
|
|
41
|
+
Do not guess. Record it and move on:
|
|
42
|
+
|
|
43
|
+
- Write the gap as an open question in the state file: `- [ ] OQ: <question>`.
|
|
44
|
+
- Mark the item `needs-human` (escalate per the loop's handoff rule).
|
|
45
|
+
- If NO blocking question can be resolved, escalate the whole item and stop.
|
|
46
|
+
Acting on a guess burns attempts the circuit breaker should not have to catch.
|
|
47
|
+
|
|
48
|
+
## Output
|
|
49
|
+
|
|
50
|
+
Append a short, sharpened goal to the state file (or the item):
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Goal (clarified): <one testable sentence>
|
|
54
|
+
Done when: <verifiable condition>
|
|
55
|
+
Open questions: <N> (needs-human) - <list>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Hand back to triage or the action skill only if "Done when" is now verifiable.
|
|
59
|
+
|
|
60
|
+
## Interaction with other skills
|
|
61
|
+
|
|
62
|
+
- Runs BEFORE `loop-triage` / `issue-triage` and any action skill.
|
|
63
|
+
- Feeds `loop-verifier`: the "Done when" line becomes the verifier's check.
|
|
64
|
+
- Pairs with `loop-guard` (circuit breaker): intake prevents wasted attempts on a
|
|
65
|
+
goal that was never well defined; the breaker catches the ones that slip through.
|
|
66
|
+
- Respects `loop-constraints`: never ask for, or act on, denylisted scope.
|
|
67
|
+
|
|
68
|
+
## Default behavior
|
|
69
|
+
|
|
70
|
+
Report-only in week one: propose the clarified goal and open questions, but let a
|
|
71
|
+
human confirm before the loop acts on the sharpened goal.
|