@phamvuhoang/otto-core 0.4.1 → 0.6.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.
Files changed (50) hide show
  1. package/dist/branch.d.ts +20 -0
  2. package/dist/branch.d.ts.map +1 -1
  3. package/dist/branch.js +34 -1
  4. package/dist/branch.js.map +1 -1
  5. package/dist/cli-help.d.ts +42 -0
  6. package/dist/cli-help.d.ts.map +1 -1
  7. package/dist/cli-help.js +56 -2
  8. package/dist/cli-help.js.map +1 -1
  9. package/dist/gh-main.d.ts.map +1 -1
  10. package/dist/gh-main.js +1 -0
  11. package/dist/gh-main.js.map +1 -1
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/linear-api.d.ts +1 -0
  17. package/dist/linear-api.d.ts.map +1 -1
  18. package/dist/linear-api.js +6 -1
  19. package/dist/linear-api.js.map +1 -1
  20. package/dist/linear-cli.d.ts.map +1 -1
  21. package/dist/linear-cli.js +11 -3
  22. package/dist/linear-cli.js.map +1 -1
  23. package/dist/linear-main.d.ts.map +1 -1
  24. package/dist/linear-main.js +4 -1
  25. package/dist/linear-main.js.map +1 -1
  26. package/dist/run-bin.d.ts +10 -0
  27. package/dist/run-bin.d.ts.map +1 -1
  28. package/dist/run-bin.js +116 -0
  29. package/dist/run-bin.js.map +1 -1
  30. package/dist/task-key.d.ts +65 -0
  31. package/dist/task-key.d.ts.map +1 -0
  32. package/dist/task-key.js +112 -0
  33. package/dist/task-key.js.map +1 -0
  34. package/dist/watch.d.ts +26 -4
  35. package/dist/watch.d.ts.map +1 -1
  36. package/dist/watch.js +96 -41
  37. package/dist/watch.js.map +1 -1
  38. package/package.json +1 -1
  39. package/templates/acceptance-prompts.md +42 -0
  40. package/templates/apply-review.md +32 -2
  41. package/templates/ghafk-issue.md +4 -2
  42. package/templates/ghafk.md +2 -2
  43. package/templates/ghprompt-workflow.md +9 -0
  44. package/templates/ghprompt.md +2 -0
  45. package/templates/linear-completion.md +10 -0
  46. package/templates/linearprompt.md +3 -1
  47. package/templates/quality-report.md +80 -0
  48. package/templates/review-lens.md +1 -0
  49. package/templates/superpowers.md +23 -10
  50. package/templates/verify.md +17 -21
package/dist/watch.js CHANGED
@@ -4,13 +4,18 @@ import { createLinearClient, resolveLinearAuth, LinearApiError, } from "./linear
4
4
  import { runLoop } from "./loop.js";
5
5
  import { notifyComplete, notifyError } from "./notify.js";
6
6
  import { sleep } from "./pacing.js";
7
+ import { describeScope } from "./task-key.js";
7
8
  import { bold, dim, greenOut, boldOut, dimOut, SYM_OUT, USE_COLOR, } from "./stream-render.js";
8
- /** Poll open issues carrying `label`, via gh. Never throws. */
9
- export function pollOpenIssues(label, cwd) {
9
+ /**
10
+ * Poll open issues carrying `label`, via gh. Never throws. When `repo`
11
+ * (`owner/name`) is given the poll is confined to that repository (watch
12
+ * scoping) instead of the workspace's default repo.
13
+ */
14
+ export function pollOpenIssues(label, cwd, repo) {
10
15
  try {
11
- // execFileSync (no shell) so `label` is passed as a literal argv entry — a
12
- // value like `$(rm -rf ~)` can never be shell-evaluated. See SECURITY.md.
13
- // stderr is piped (not ignored) so a failure's message can be classified.
16
+ // execFileSync (no shell) so `label`/`repo` are passed as literal argv
17
+ // entries — a value like `$(rm -rf ~)` can never be shell-evaluated. See
18
+ // SECURITY.md. stderr is piped (not ignored) so failures can be classified.
14
19
  const out = execFileSync("gh", [
15
20
  "issue",
16
21
  "list",
@@ -18,6 +23,7 @@ export function pollOpenIssues(label, cwd) {
18
23
  "open",
19
24
  "--label",
20
25
  label,
26
+ ...(repo ? ["--repo", repo] : []),
21
27
  "--json",
22
28
  "number",
23
29
  ], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
@@ -58,6 +64,7 @@ export async function pollLinearIssues(deps) {
58
64
  const issues = await client.listIssues({
59
65
  label: deps.label,
60
66
  team: deps.team,
67
+ project: deps.project,
61
68
  limit: deps.limit ?? 50,
62
69
  });
63
70
  return { ok: true, count: issues.length };
@@ -71,7 +78,28 @@ export async function pollLinearIssues(deps) {
71
78
  }
72
79
  const GH_PROVIDER = { name: "gh", authCmd: "gh auth login" };
73
80
  export async function runWatch(opts) {
74
- const { stages, iterations, workspaceDir, packageDir, watchIntervalSec, watchLabel, budgetUsd, cooldownMs, maxRetries, reviewLenses, notify = false, bin = "otto-ghafk", pollIssues = pollOpenIssues, provider = GH_PROVIDER, } = opts;
81
+ const { stages, iterations, workspaceDir, packageDir, watchIntervalSec, watchLabel, budgetUsd, cooldownMs, maxRetries, reviewLenses, notify = false, bin = "otto-ghafk", pollIssues = pollOpenIssues, provider = GH_PROVIDER, scope, scopes, } = opts;
82
+ // The scopes this daemon rotates through each cycle. Multi-target watch
83
+ // passes `scopes`; otherwise a single `scope` (or the workspace default,
84
+ // represented by a lone `undefined`).
85
+ const scopeList = scopes && scopes.length > 0 ? scopes : [scope];
86
+ // Derive the gh `--repo` filter from a github scope; other providers (Linear)
87
+ // carry their scope in the label/team the poller already honors.
88
+ const ghRepoOf = (s) => s?.provider === "github" && s.owner && s.repo
89
+ ? `${s.owner}/${s.repo}`
90
+ : undefined;
91
+ // The Linear project for a scope. Unlike github (which gets a poll `--repo`
92
+ // arg), the Linear poller reads OTTO_LINEAR_PROJECT from the env, so the
93
+ // daemon pins it before each poll/run to confine that scope.
94
+ const linearProjectOf = (s) => s?.provider === "linear" && s.project ? s.project : undefined;
95
+ // Human-readable scope prefix for a poll line (e.g. "github acme/web ").
96
+ const labelOf = (s) => s ? `${describeScope(s)} ` : "";
97
+ // The banner names every scope so a maintainer sees the exact watch surface.
98
+ const bannerScope = scopeList
99
+ .filter((s) => !!s)
100
+ .map(describeScope)
101
+ .join(", ");
102
+ const scopeLabel = bannerScope ? `${bannerScope} ` : "";
75
103
  const releaser = acquire({ reason: `${bin} watch` });
76
104
  let released = false;
77
105
  const releaseOnce = () => {
@@ -92,7 +120,7 @@ export async function runWatch(opts) {
92
120
  const onSigterm = onSig(143);
93
121
  process.on("SIGINT", onSigint);
94
122
  process.on("SIGTERM", onSigterm);
95
- process.stderr.write(`${USE_COLOR ? dim("watching") + " " + bold(`label:${watchLabel} every ${watchIntervalSec}s`) : `watching label:${watchLabel} every ${watchIntervalSec}s`}\n`);
123
+ process.stderr.write(`${USE_COLOR ? dim("watching") + " " + bold(`${scopeLabel}label:${watchLabel} every ${watchIntervalSec}s`) : `watching ${scopeLabel}label:${watchLabel} every ${watchIntervalSec}s`}\n`);
96
124
  let cumulativeCost = 0;
97
125
  // Track idle state so the "no open issues" line prints only on the
98
126
  // idle→busy→idle transition, not on every empty poll — otherwise an
@@ -107,42 +135,69 @@ export async function runWatch(opts) {
107
135
  notifyComplete(0, false);
108
136
  return;
109
137
  }
110
- const poll = await pollIssues(watchLabel, workspaceDir);
111
- if (!poll.ok) {
112
- // Broken poll say *why*, distinctly from an idle queue, and keep
113
- // polling (auth may get fixed / a transient failure may clear).
114
- wasIdle = false;
115
- const suffix = poll.detail ? ` — ${poll.detail}` : "";
116
- const why = poll.auth
117
- ? `${provider.name} not authenticated — run '${provider.authCmd}' (label ${watchLabel})${suffix}`
118
- : `${provider.name} issue poll failed (label ${watchLabel})${suffix}`;
119
- process.stderr.write(`${dim(why)}\n`);
120
- }
121
- else if (poll.count > 0) {
122
- wasIdle = false;
123
- process.stderr.write(`${dim(`${poll.count} open issue(s) labelled ${watchLabel} running loop`)}\n`);
124
- const remaining = budgetUsd != null ? budgetUsd - cumulativeCost : undefined;
125
- const outcome = await runLoop({
126
- stages,
127
- inputs: "",
128
- iterations,
129
- workspaceDir,
130
- packageDir,
131
- budgetUsd: remaining,
132
- cooldownMs,
133
- maxRetries,
134
- reviewLenses,
135
- noKeepAlive: true,
136
- signal: daemonAbort.signal,
137
- bin,
138
- cliVersion: opts.cliVersion,
139
- });
140
- cumulativeCost += outcome.costUsd;
141
- process.stderr.write(`${dim(`watch run done — cumulative $${cumulativeCost.toFixed(2)}`)}\n`);
138
+ // Poll every scope this cycle. Run one loop for the FIRST scope with
139
+ // work, then break back to the sleep+repoll — one loop at a time, no
140
+ // parallel mutation of the workspace. A failed poll for one scope is
141
+ // logged and skipped so it never blocks polling the others.
142
+ let ran = false;
143
+ let allIdle = true;
144
+ for (const s of scopeList) {
145
+ const sRepo = ghRepoOf(s);
146
+ const sProject = linearProjectOf(s);
147
+ const sLabel = labelOf(s);
148
+ // Pin the Linear project before polling so the poller (which reads it
149
+ // from the inherited env, not a poll arg) is confined to this scope;
150
+ // it also stays pinned for the loop run below. GitHub uses the sRepo
151
+ // poll arg instead and pins OTTO_GITHUB_REPO only on the run.
152
+ if (sProject)
153
+ process.env.OTTO_LINEAR_PROJECT = sProject;
154
+ const poll = await pollIssues(watchLabel, workspaceDir, sRepo);
155
+ if (!poll.ok) {
156
+ // Broken poll — say *why*, distinctly from an idle queue, and keep
157
+ // polling (auth may get fixed / a transient failure may clear).
158
+ allIdle = false;
159
+ wasIdle = false;
160
+ const suffix = poll.detail ? ` — ${poll.detail}` : "";
161
+ const why = poll.auth
162
+ ? `${sLabel}${provider.name} not authenticated — run '${provider.authCmd}' (label ${watchLabel})${suffix}`
163
+ : `${sLabel}${provider.name} issue poll failed (label ${watchLabel})${suffix}`;
164
+ process.stderr.write(`${dim(why)}\n`);
165
+ continue;
166
+ }
167
+ if (poll.count > 0) {
168
+ allIdle = false;
169
+ wasIdle = false;
170
+ process.stderr.write(`${dim(`${sLabel}${poll.count} open issue(s) labelled ${watchLabel} — running loop`)}\n`);
171
+ // Confine this loop's `gh` commands (render-time tags + the spawned
172
+ // agent) to the selected scope by pinning OTTO_GITHUB_REPO before the
173
+ // run; single-target left it set in run-bin, this covers multi-target.
174
+ if (sRepo)
175
+ process.env.OTTO_GITHUB_REPO = sRepo;
176
+ const remaining = budgetUsd != null ? budgetUsd - cumulativeCost : undefined;
177
+ const outcome = await runLoop({
178
+ stages,
179
+ inputs: "",
180
+ iterations,
181
+ workspaceDir,
182
+ packageDir,
183
+ budgetUsd: remaining,
184
+ cooldownMs,
185
+ maxRetries,
186
+ reviewLenses,
187
+ noKeepAlive: true,
188
+ signal: daemonAbort.signal,
189
+ bin,
190
+ cliVersion: opts.cliVersion,
191
+ });
192
+ cumulativeCost += outcome.costUsd;
193
+ process.stderr.write(`${dim(`${sLabel}watch run done — cumulative $${cumulativeCost.toFixed(2)}`)}\n`);
194
+ ran = true;
195
+ break;
196
+ }
142
197
  }
143
- else if (!wasIdle) {
198
+ if (!ran && allIdle && !wasIdle) {
144
199
  // First empty poll after activity — announce idle once, then stay quiet
145
- // until the queue becomes non-empty (or a poll fails) and idles again.
200
+ // until a queue becomes non-empty (or a poll fails) and idles again.
146
201
  wasIdle = true;
147
202
  process.stderr.write(`${dim(`no open issues labelled ${watchLabel} — idle, next poll in ${watchIntervalSec}s`)}\n`);
148
203
  }
package/dist/watch.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phamvuhoang/otto-core",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Claude Code AFK orchestration: iteration loop, native-sandbox runner, template renderer.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,42 @@
1
+ <!--
2
+ Per-mode human-acceptance prompts for the Otto quality report. Included ONCE by
3
+ quality-report.md, so every run mode inherits the same set through the single
4
+ existing contract include — never re-describe these per template (the same
5
+ drift-proofing as the contract itself). The generic Human Acceptance Checklist
6
+ stays; these add the task-fulfillment questions specific to the run's Mode.
7
+ -->
8
+
9
+ **Mode-specific acceptance prompts.** Beyond the generic checklist, fold the
10
+ prompts for **your Mode** (from Task Source) into the Human Acceptance Checklist.
11
+ Answer each with cited evidence, or mark it an explicit gap — never drop one
12
+ silently.
13
+
14
+ ### afk — plan/PRD completion
15
+
16
+ - [ ] Every PRD acceptance criterion is met or explicitly deferred.
17
+ - [ ] All plan tasks are checked off, or the unchecked ones are recorded as gaps.
18
+ - [ ] The product behavior is demonstrable, not just coded.
19
+
20
+ ### ghafk — GitHub issue burn-down
21
+
22
+ - [ ] The change resolves what the issue actually asked, not an adjacent reading.
23
+ - [ ] Work is scoped to this issue; unrelated changes are called out.
24
+ - [ ] The issue will close cleanly when the PR merges (PR/issue links cited).
25
+
26
+ ### linear-afk — Linear issue burn-down
27
+
28
+ - [ ] The change resolves the Linear issue's stated intent.
29
+ - [ ] The comment cites the branch/PR and the explicit human next step.
30
+ - [ ] The issue is left in the correct state (OPEN for PR-based repos).
31
+
32
+ ### apply-review — external review repair
33
+
34
+ - [ ] Every CONFIRMED finding was actually fixed, not just acknowledged.
35
+ - [ ] The fixes introduced no regression (suites re-run green).
36
+ - [ ] Deferred / rejected findings are recorded with a reason.
37
+
38
+ ### verify — read-only verification
39
+
40
+ - [ ] Each task's claimed status matches committed reality (evidence cited).
41
+ - [ ] Suite results are current, not stale.
42
+ - [ ] Gaps and deferrals are honest, not optimistic.
@@ -28,7 +28,17 @@
28
28
 
29
29
  `<review-doc>` names a code-review document (a file path). `Read` it. It contains findings, usually with severities. Your job is to fix the actionable ones — ONE finding per iteration — and track the rest.
30
30
 
31
- When every actionable finding has been addressed (fixed, or already fixed in git, or recorded as a follow-up), output `<promise>NO MORE TASKS</promise>`.
31
+ When every actionable finding has been addressed (fixed, or already fixed in git, or recorded as a follow-up), produce the completion report (see COMPLETION REPORT below), then output `<promise>NO MORE TASKS</promise>`.
32
+
33
+ # TASK KEY
34
+
35
+ Per-task artifacts (spec, plan, follow-ups) live together under
36
+ `.otto/tasks/<task-key>/`, so everything Otto knows about a task is in one place.
37
+ Resolve the task key for THIS run from the current git branch: run
38
+ `git branch --show-current` and take the **final path segment** (the part after the
39
+ last `/`) — e.g. `otto/issue-21` → `issue-21`, `feat/gh-acme-web-14` →
40
+ `gh-acme-web-14`. If the branch name has no `/`, use it whole. Use this key in the
41
+ follow-ups path below.
32
42
 
33
43
  # TRIAGE
34
44
 
@@ -56,7 +66,9 @@ Pick the highest-value actionable finding not yet addressed. Implement the fix.
56
66
 
57
67
  # RECORD FOLLOW-UPS
58
68
 
59
- For each Deferred / follow-up finding, append a terse entry to `./.otto/review-followups.md` (create it lazily). Use a dated `##` heading for this review, then one bullet per finding with its severity and why it is deferred. This file is git-tracked commit it WITH the related fix (do not make a separate commit just for it).
69
+ For each Deferred / follow-up finding, append a terse entry to the **task-local** follow-ups file `./.otto/tasks/<task-key>/followups.md` (create it and its parent dir lazily), using the task key resolved above. Use a dated `##` heading for this review, then one bullet per finding with its severity and why it is deferred. Keeping follow-ups beside the task's spec/plan means everything Otto knows about a task is in one place, while staying globally summarizable by globbing `.otto/tasks/*/followups.md`.
70
+
71
+ Read the task-local file first (it may already hold this task's prior deferrals). The legacy global `./.otto/review-followups.md` is still READ as a fallback for older runs (see `<existing-followups>`) for one release, but do NOT append new entries there. This file is git-tracked — commit it WITH the related fix (do not make a separate commit just for it).
60
72
 
61
73
  # COMMIT
62
74
 
@@ -66,6 +78,24 @@ Make a single `git commit -am` with a short message:
66
78
  - Body: which finding (and its review section), key decision, and a one-line note of any follow-ups recorded.
67
79
  - No file lists, no `Co-Authored-By`.
68
80
 
81
+ # COMPLETION REPORT
82
+
83
+ Only on the final iteration — when every actionable finding has been addressed
84
+ and you are about to output the sentinel — hand the maintainer one readable
85
+ summary of the whole review-fix round. Do NOT emit it per-iteration. Map the
86
+ contract below onto this round:
87
+
88
+ - **What Changed / Evidence:** the findings you CONFIRMED and fixed, each with
89
+ its `fix(review):` commit SHA and the review section it came from; the
90
+ feedback loops you ran (tests / typecheck) and their result.
91
+ - **Gaps And Follow-Ups:** findings you DEFERRED to
92
+ `./.otto/tasks/<task-key>/followups.md` (with why), and any REJECTED / won't-fix
93
+ findings with their reason. Verdict
94
+ defaults to **Needs human review** when any actionable finding was left
95
+ unfixed.
96
+
97
+ @include:quality-report.md
98
+
69
99
  # FINAL RULES
70
100
 
71
101
  ONLY ADDRESS A SINGLE FINDING per iteration.
@@ -12,12 +12,14 @@
12
12
 
13
13
  <issue>
14
14
 
15
- !?`gh issue view "$OTTO_ISSUE" --json number,title,state|||Issue not found`
15
+ !?`gh issue view "$OTTO_ISSUE" ${OTTO_GITHUB_REPO:+--repo "$OTTO_GITHUB_REPO"} --json number,title,state|||Issue not found`
16
16
 
17
- Full issue body + comments spilled to: @spill?:issue.json=`gh issue view "$OTTO_ISSUE" --json number,title,body,comments,state|||[]`
17
+ Full issue body + comments spilled to: @spill?:issue.json=`gh issue view "$OTTO_ISSUE" ${OTTO_GITHUB_REPO:+--repo "$OTTO_GITHUB_REPO"} --json number,title,body,comments,state|||[]`
18
18
 
19
19
  `Read` that file to get the full body and comments before acting on the issue.
20
20
 
21
+ If `$OTTO_GITHUB_REPO` is set (run scoped with `--repo owner/name`), pass `--repo "$OTTO_GITHUB_REPO"` to every `gh` command you run yourself (issue comment, pr create) so completion targets that repo. If unset, `gh` uses the workspace's own repo.
22
+
21
23
  </issue>
22
24
 
23
25
  # THE TASK
@@ -14,13 +14,13 @@
14
14
 
15
15
  <issues-summary>
16
16
 
17
- `gh issue list --state open --limit 50 --json number,title,labels`
17
+ `gh issue list ${OTTO_GITHUB_REPO:+--repo "$OTTO_GITHUB_REPO"} --state open --limit 50 --json number,title,labels`
18
18
 
19
19
  </issues-summary>
20
20
 
21
21
  <issues-full-file>
22
22
 
23
- Full issue bodies + comments spilled to: @spill?:issues.json=`gh issue list --state open --limit 50 --json number,title,body,labels,comments|||[]`
23
+ Full issue bodies + comments spilled to: @spill?:issues.json=`gh issue list ${OTTO_GITHUB_REPO:+--repo "$OTTO_GITHUB_REPO"} --state open --limit 50 --json number,title,body,labels,comments|||[]`
24
24
 
25
25
  Read that file with `Read` (use `offset`/`limit` if it is large) to get bodies and comments before picking a task. The `<issues-summary>` block above is the lean index for triage.
26
26
 
@@ -59,6 +59,15 @@ Committing the code is NOT necessarily the end of the run. How work "ships" depe
59
59
 
60
60
  When unsure which applies, prefer leaving the issue OPEN and surfacing the branch — never close an issue whose work has not landed on the default branch.
61
61
 
62
+ ## Quality report (completion handoff)
63
+
64
+ Whatever the completion surface, hand the maintainer **one readable Otto quality report** so they can accept, reject, or request follow-up without replaying the run log — green tests alone are not the handoff. Emit it into the completion surface and cite concrete links/SHAs:
65
+
66
+ - **PR-based repo:** put the report in the **PR description** (create or refresh it there) and reference it from any issue comment. Cite the PR URL, the issue link, and the commit SHAs on this branch.
67
+ - **Commit-to-branch repo:** put the report in the **issue comment**, citing the branch and the commit SHAs.
68
+
69
+ @include:quality-report.md
70
+
62
71
  # LEARNINGS
63
72
 
64
73
  The repo's accumulated learnings are in the `<learnings>` block — durable, reusable knowledge from prior iterations (conventions, gotchas, decisions and their why, dead ends). Consult it during EXPLORATION and IMPLEMENTATION so you don't relearn what's known or repeat a dead end.
@@ -7,6 +7,8 @@ Two views of open GitHub issues are provided at the start of context:
7
7
 
8
8
  You will work on the AFK issues only, not the HITL ones. Label filtering uses the `labels` field in the summary.
9
9
 
10
+ **Repo scope.** If the `$OTTO_GITHUB_REPO` environment variable is set (the run was scoped with `--repo owner/name`), the issue list above is already confined to that repo — work only on those issues, and pass `--repo "$OTTO_GITHUB_REPO"` to every `gh` command you run yourself (e.g. `gh issue comment`, `gh pr create`) so completion targets the same repo. If it is unset, `gh` uses the workspace's own repo as before.
11
+
10
12
  You've also been passed a file containing the last few commits. Review these to understand what work has been done.
11
13
 
12
14
  If all AFK tasks are complete, output <promise>NO MORE TASKS</promise>.
@@ -15,3 +15,13 @@ every Linear write — never raw GraphQL, and never `gh`:
15
15
  the issue for a human to move.
16
16
 
17
17
  When unsure which convention applies, comment and leave the issue OPEN.
18
+
19
+ ## Quality report placement (Linear)
20
+
21
+ The FINISHING handoff above already defines the **Otto quality report** shape —
22
+ do not re-describe it here. On Linear the **comment body IS that report**: write
23
+ the full quality report (verdict, task source, what changed, evidence, human
24
+ acceptance checklist, gaps/follow-ups) to a file and post it with
25
+ `otto-linear comment <ref> --body-file <path>`, citing the branch/PR, the commit
26
+ SHAs, the checks run, and the explicit human next step. For this PR-based repo
27
+ that comment is the handoff surface — the issue stays OPEN until the PR merges.
@@ -9,7 +9,9 @@ Two views of open Linear issues are provided at the start of context:
9
9
  large) once you have picked an issue you want to act on.
10
10
 
11
11
  Issue selection is already filtered to open Linear issues carrying the `otto`
12
- label (override via `OTTO_LINEAR_LABEL`, narrow to a team via `OTTO_LINEAR_TEAM`).
12
+ label (override via `OTTO_LINEAR_LABEL`, narrow to a team via `OTTO_LINEAR_TEAM`,
13
+ and narrow to a project via `OTTO_LINEAR_PROJECT`). Work only on the issues the
14
+ list shows — they are already confined to the configured team/project scope.
13
15
 
14
16
  You've also been passed a file containing the last few commits. Review these to
15
17
  understand what work has been done.
@@ -0,0 +1,80 @@
1
+ <!--
2
+ The Otto quality report contract. ONE readable verification artifact, reused
3
+ across every run mode (verify / afk / ghafk / linear-afk / apply-review) by
4
+ @include — never re-describe the shape per template, or the provider workflows
5
+ drift apart. Readable first; every claim cites concrete proof.
6
+ -->
7
+
8
+ Produce an **Otto quality report** with the exact section headings below. Rules:
9
+
10
+ - **Readable first.** Keep it short enough to review in a couple of minutes — a
11
+ maintainer should not have to replay the run log. Specific beats exhaustive.
12
+ - **Cite evidence for every claim.** A `file:line`, a commit SHA, a command +
13
+ its result, a report section, or an issue/PR link — never a vague assertion.
14
+ - **Tests are evidence, not the verdict.** Green checks go in the Evidence
15
+ section; they do not by themselves make the verdict Accepted.
16
+ - **Pick one honest verdict. When evidence is thin, scope is uncertain, or you
17
+ are unsure, choose _Needs human review_ — never self-declare _Accepted_.**
18
+ Model self-evaluation does not replace human review.
19
+
20
+ ```markdown
21
+ # Otto quality report
22
+
23
+ ## Verdict
24
+
25
+ One of — **Accepted** · **Accepted with follow-ups** · **Needs human review** · **Rejected**
26
+ (when uncertain, choose **Needs human review**)
27
+
28
+ ## Task Source
29
+
30
+ - Mode: <afk | ghafk | linear-afk | apply-review | verify>
31
+ - Source: <plan/PRD path, GitHub issue #, or Linear ref>
32
+ - Issue or plan: <link or path>
33
+
34
+ ## What Changed
35
+
36
+ - Summary: <one or two sentences — what was actually done>
37
+ - Commits: <SHAs on this branch>
38
+ - Files: <paths touched>
39
+
40
+ ## Evidence
41
+
42
+ - Implementation evidence: <file:line or commit proving each claim>
43
+ - Test/typecheck evidence: <commands run + pass/fail counts>
44
+ - Manual or acceptance evidence: <what was observed, or "none">
45
+
46
+ ## Human Acceptance Checklist
47
+
48
+ - [ ] Solves the stated problem.
49
+ - [ ] Behavior is observable or explained.
50
+ - [ ] Scope is appropriate.
51
+ - [ ] Docs/examples are updated when needed.
52
+ - [ ] Risks and assumptions are clear.
53
+
54
+ ## Gaps And Follow-Ups
55
+
56
+ - Gap: <known gap that remains, or "none">
57
+ - Deferred: <intentionally not done in this run + why, or "none">
58
+ - Recommended next action: <what a maintainer should do next>
59
+ ```
60
+
61
+ ### Human verdict trail
62
+
63
+ Prior **human** verdicts on past Otto runs (most recent last) — consult them so a
64
+ recurring reason ("scope creep", "thin evidence") informs *this* run's Verdict
65
+ and *Recommended next action* before you commit to one:
66
+
67
+ <verdict-trail>
68
+
69
+ !?`cat ./.otto/verdicts.md|||_No human verdicts recorded yet._`
70
+
71
+ </verdict-trail>
72
+
73
+ **Maintainer:** after reviewing this report, append your verdict to
74
+ `./.otto/verdicts.md` (create it lazily) — a dated `##` heading plus one line:
75
+ the human verdict (**Accepted** · **Accepted with follow-ups** · **Rejected** ·
76
+ **Needs investigation**) and *why* (what was accepted with caveats, or the
77
+ concrete reason it was rejected). The file is git-tracked; it feeds the existing
78
+ learning loop, so future runs see what was accepted or rejected and why.
79
+
80
+ @include:acceptance-prompts.md
@@ -27,6 +27,7 @@ You review the most recent commit (HEAD) through ONE lens only: **{{ LENS }}**.
27
27
  - `correctness` — bugs, regressions, broken logic, unhandled edge cases.
28
28
  - `security` — input validation, secrets, injection, auth bypass.
29
29
  - `tests` — coverage gaps for the changed code; missing/weak assertions.
30
+ - `task-fit` — did the change solve the **right problem**? Does it map back to the source plan/issue, stay in scope (no unrequested extras, no missed sub-task), and leave a reviewer-useful trail (clear commit, evidence, surfaced gaps)? Flag scope drift, unaddressed acceptance criteria, and work that is mechanically correct but doesn't fulfil the task.
30
31
 
31
32
  If `<head>` shows `(no commits)`, output `<lens>SKIP</lens>` and stop.
32
33
 
@@ -10,29 +10,41 @@ If the `superpowers:brainstorming`, `superpowers:writing-plans`, and
10
10
  fuller guidance. If they are not installed, follow the inline protocol below —
11
11
  it is self-contained.
12
12
 
13
- ## 0. Resolve the task key
13
+ ## 0. Resolve the task key and artifact paths
14
14
 
15
15
  - GitHub issue run → task-key = `issue-<issue number>`.
16
16
  - Plan/PRD run → task-key = a stable slug from the primary plan-file basename
17
17
  (e.g. `docs/plans/foo.md` → `foo`). If inputs are inline text, use a short
18
18
  kebab-case of the task title.
19
19
 
20
- Spec path: `.otto/specs/<task-key>-design.md`
21
- Plan path: `.otto/plans/<task-key>.md`
20
+ Per-task artifacts live together under one task directory, so everything Otto
21
+ knows about a task is in one place:
22
+
23
+ - Task dir: `.otto/tasks/<task-key>/`
24
+ - Spec path: `.otto/tasks/<task-key>/spec.md`
25
+ - Plan path: `.otto/tasks/<task-key>/plan.md`
26
+
27
+ Always **WRITE** the new task-grouped layout. The legacy flat layout
28
+ (`.otto/specs/<task-key>-design.md` + `.otto/plans/<task-key>.md`) is still
29
+ **READ** as a fallback (see the CLARITY GATE), so a task created before this
30
+ layout continues without re-brainstorming.
22
31
 
23
32
  ## 1. CLARITY GATE
24
33
 
25
- Check whether `.otto/specs/<task-key>-design.md` already exists.
34
+ Check whether the spec already exists — look under the new task dir
35
+ `.otto/tasks/<task-key>/spec.md` first, then fall back to the legacy flat path
36
+ `.otto/specs/<task-key>-design.md`.
26
37
 
27
- - **Spec exists** → skip brainstorming. Read the spec and
28
- `.otto/plans/<task-key>.md`, pick the next unchecked task, and go to
38
+ - **Spec exists** → skip brainstorming. Read the spec and its matching plan
39
+ (`.otto/tasks/<task-key>/plan.md`, or legacy `.otto/plans/<task-key>.md`),
40
+ pick the next unchecked task, and go to
29
41
  TDD IMPLEMENT (section 3). If every plan task is checked AND the feedback
30
42
  loops pass, output `<promise>NO MORE TASKS</promise>`.
31
43
  - **No spec** → judge the input's clarity. It is UNCLEAR if any of: no
32
44
  plan/PRD provided; a vague directive ("make it better"); missing acceptance
33
45
  criteria; multiple plausible interpretations; internal contradictions.
34
46
  - Clear enough → go straight to TDD IMPLEMENT (section 3). Optionally jot a
35
- short plan to `.otto/plans/<task-key>.md` first.
47
+ short plan to `.otto/tasks/<task-key>/plan.md` first.
36
48
  - Unclear → AUTONOMOUS BRAINSTORM (section 2).
37
49
 
38
50
  ## 2. AUTONOMOUS BRAINSTORM (no human in the loop)
@@ -43,10 +55,10 @@ Play both sides of a brainstorming session:
43
55
  scope, constraints, success criteria, edge cases).
44
56
  2. Answer each one yourself with the most reasonable default given the repo's
45
57
  existing patterns. Prefer the simplest viable option (YAGNI).
46
- 3. Write `.otto/specs/<task-key>-design.md` containing: Problem, Approach, an
58
+ 3. Write `.otto/tasks/<task-key>/spec.md` containing: Problem, Approach, an
47
59
  **Assumptions** section listing each `question → chosen answer → rationale`,
48
60
  and Testing notes.
49
- 4. Write `.otto/plans/<task-key>.md` as an ordered checklist of bite-sized,
61
+ 4. Write `.otto/tasks/<task-key>/plan.md` as an ordered checklist of bite-sized,
50
62
  testable tasks (one `- [ ]` per task).
51
63
  5. Do NOT wait for approval — the written assumptions are the record.
52
64
 
@@ -63,7 +75,8 @@ Implement exactly one task, test-first:
63
75
  2. Run it; confirm it fails for the right reason.
64
76
  3. Write the minimal code to make it pass.
65
77
  4. Run the feedback loops described below until green.
66
- 5. Update `.otto/plans/<task-key>.md`: check off the task. If a new durable,
78
+ 5. Update the plan you read (`.otto/tasks/<task-key>/plan.md`, or its legacy
79
+ fallback `.otto/plans/<task-key>.md`): check off the task. If a new durable,
67
80
  reusable learning emerged, append it to `.otto/LEARNINGS.md`.
68
81
 
69
82
  Commit the code, the updated spec/plan, and LEARNINGS together in the single
@@ -45,30 +45,26 @@ Put every task in exactly one bucket:
45
45
 
46
46
  # REPORT
47
47
 
48
- Write your report to `.otto-tmp/verify-report.md` using the `Write` tool (this path is gitignored scratch — it is the one write you may make). Structure it:
48
+ Write your report to `.otto-tmp/verify-report.md` using the `Write` tool (this path is gitignored scratch — it is the one write you may make). Use the Otto quality report contract below: fold the RECONCILE/CLASSIFY results into it — DONE tasks (with their `file:line`/SHA evidence) into **What Changed** + **Evidence**, the suite pass/fail counts into the Test/typecheck evidence line, and GAP/DEFERRED tasks into **Gaps And Follow-Ups**.
49
49
 
50
- ```
51
- # Verify report
50
+ @include:quality-report.md
52
51
 
53
- ## Verdict
52
+ # CROSS-RUN QUALITY SUMMARY (READ-ONLY)
54
53
 
55
- <one-line: all done / N gaps / N deferred>
54
+ Beyond *this* run, give the maintainer a quality rollup **across** runs so they can
55
+ spot recurring output-quality failures without reading every NDJSON log. `Read`
56
+ `./.otto/verdicts.md` (the git-tracked human-verdict trail). If it is absent, skip
57
+ this section. Otherwise append a short `## Cross-Run Quality Summary` block to the
58
+ same report file (`.otto-tmp/verify-report.md`) with:
56
59
 
57
- ## Done
60
+ - **Completions:** how many runs recorded a verdict, and the tally per verdict
61
+ (Accepted / Accepted with follow-ups / Rejected / Needs investigation).
62
+ - **Common causes:** recurring reasons behind rejections or follow-ups (e.g.
63
+ "scope creep", "thin evidence"), most frequent first.
64
+ - **Outstanding gaps & deferred work:** gaps and deferred items still open across
65
+ runs, so a maintainer can turn them into follow-up issues.
58
66
 
59
- - <task> <evidence: file:line or commit>
67
+ Keep it to a few lines and cite the trail entries you counted. This is read-only —
68
+ do not edit or commit the trail.
60
69
 
61
- ## Gaps
62
-
63
- - <task> — <what is missing>
64
-
65
- ## Deferred
66
-
67
- - <task> — <why>
68
-
69
- ## Suites
70
-
71
- - <command> — <pass/fail counts>
72
- ```
73
-
74
- Also print the Verdict + section counts to your final message. Do not commit.
70
+ Also print the Verdict + a one-line tally of done/gap/deferred to your final message. Do not commit.