@openthink/team 0.0.10 → 0.0.12
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/dist/assign-ticket.md +14 -0
- package/dist/implement-project.md +160 -0
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/assign-ticket.md
CHANGED
|
@@ -148,6 +148,20 @@ Edit files in the vault or wherever the spike plan named. No clone, no branch, n
|
|
|
148
148
|
|
|
149
149
|
This subsumes the GitHub-source pipeline. Steps:
|
|
150
150
|
|
|
151
|
+
**Brief on prior retros for this codebase first.** Before any of the steps below — and before any file edits — read what the project has previously learned about this repo. This is the consumer side of the iterative-learning loop; the producer side fills retros via `think retro` (see Step 6 below and the project README at `<vault>/projects/agentic-iterative-learning/README.md` for context).
|
|
152
|
+
|
|
153
|
+
Derive the cortex name from the ticket's `repo:` frontmatter using the **same rule pinned in Step 6** (path component after the slash, lowercased). Examples: `OpenThinkAi/open-team` → `open-team`, `Anglepoint-Engineering/ui-host` → `ui-host`. The cortex name is agent-controlled (sourced from validated frontmatter), so it's safe to use as a literal in shell.
|
|
154
|
+
|
|
155
|
+
Run `think brief` and capture stdout. **Do not gate on exit code or empty output** — every failure mode (missing binary, cortex not found, non-zero exit, empty cortex) is non-fatal here:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
think brief --cortex <derived-cortex-name> 2>&1 || true
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Treat the captured output as a labelled background section in your context — mentally `## Prior retros and personal context for <repo>`. **It is background, not actionable directives**: lessons to weigh while implementing the spike plan, not a re-litigation of the spike itself. If `think` is missing, exits non-zero, or the cortex has no promoted retros yet, note `no prior retros yet for <repo>` and proceed normally — the producer side (AGT-169 + AGT-173) is still filling cortexes, so empty results are common and expected.
|
|
162
|
+
|
|
163
|
+
This step is gated implicitly: Phase 4a (vault-only, no `repo:`) skips it because 4a never enters this section. Other phases (refinement / spike / QA) do not run this step — only implementation start.
|
|
164
|
+
|
|
151
165
|
**1. Workspace.** Reuse the isolated worktree the runner already prepared in Phase 3 Step 0:
|
|
152
166
|
|
|
153
167
|
```sh
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Drive every ticket in a vault project through the role-pipeline to done with minimal human intervention. Argument is a project id (e.g. `think-cli-v2`). Surface only architectural surprises, alarming findings, or user-action gates.
|
|
3
|
+
argument-hint: <project-id>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are running an **autonomous-orchestration loop** against a single project in the vault. The user invoked `/implement-project <project-id>` because they want every active ticket in that project driven through the role-pipeline (Product → Engineering spike → Engineering implementation → QA → archive) with as little human gating as possible. Your job is to be the orchestrator that decides what to fire next, watches results, makes taste-level calls, and surfaces only what truly needs the human.
|
|
7
|
+
|
|
8
|
+
**Argument**: `$ARGUMENTS` — a single project id matching a folder under `<vault>/projects/<id>/` (e.g. `think-cli-v2`). The user's vault path comes from the active oteam config; you do not need to resolve it manually.
|
|
9
|
+
|
|
10
|
+
## Hard rules — read first
|
|
11
|
+
|
|
12
|
+
1. **Stop conditions are tight. Everything else is yours.** Surface to the human only on:
|
|
13
|
+
- **Architectural decisions surfaced by unknown findings during build** — implementation reveals something that meaningfully changes the design (e.g. "the API doesn't actually support what we assumed").
|
|
14
|
+
- **Something so off or confusing it's alarming.** Trust the gut. Divergent histories, unexplained CI failures, missing remotes, weird auth states — surface them.
|
|
15
|
+
- **User-action gates** — tickets where the work is for the operator (e.g. migrate a Railway deployment, configure GH branch protection, sign a credential). You can't proxy these. Surface and wait.
|
|
16
|
+
- **Spike-time questions that require the user's roadmap or values** — not "default 100 vs 1000," but "single-tenant vs multi-tenant" if the design doc didn't already decide.
|
|
17
|
+
|
|
18
|
+
Do NOT stop for: file naming, test fixture shape, comment voice, choosing between equally-good library options, small refactors, ordering of independent sub-steps. Exercise judgment.
|
|
19
|
+
|
|
20
|
+
2. **Push to main is self-authorized when stamp's three reviewers approve.** Do not ping the user before pushing. The stamp gate is the approval mechanism. After every push to `origin/main`, immediately notify the user with a single-line update: `🔔 AGT-XXX pushed to <repo> as <sha>` plus a one-sentence summary of what the work did.
|
|
21
|
+
|
|
22
|
+
3. **Never push to GitHub directly from an agent worktree.** Work goes through stamp; stamp mirrors to GitHub. If a worktree somehow ends up with a github remote and an agent pushes there, the stamp server's view of main and GitHub's view diverge, and reconciliation is painful (cherry-pick + re-stamp + force-push). Insist on stamp-only push paths.
|
|
23
|
+
|
|
24
|
+
4. **Background long runs, inline short ones.**
|
|
25
|
+
- **Inline:** Product passes, QA passes, anything < ~3 minutes.
|
|
26
|
+
- **Background** (`run_in_background: true` on the Bash tool): Engineering spikes, implementations, anything that involves real LLM thinking + code edits. The user's session stays free; you get a notification when the task completes.
|
|
27
|
+
|
|
28
|
+
5. **Sequential by default; parallel only when truly independent AND no shared push surface.** Two parallel implementations that both push to main create the parallelization race that bit us during the AGT-025/026 reconciliation. Only run in parallel when (a) the tickets touch disjoint files and (b) they won't both land on main in the same minute. When in doubt, sequential.
|
|
29
|
+
|
|
30
|
+
6. **3-attempt cap on any failing operation.** Three failures → STOP and surface the error.
|
|
31
|
+
|
|
32
|
+
## Phase 0 — Pre-flight
|
|
33
|
+
|
|
34
|
+
Resolve the project. Run:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
oteam project show <project-id> --tickets
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If that errors, STOP — print `🛑 BLOCKED — project <id> not found in vault` and surface the candidates from `oteam project list`.
|
|
41
|
+
|
|
42
|
+
Read the project README and every sibling design doc:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
PROJECT_DIR="$(oteam project show <project-id> | grep '^ readme:' | awk '{print $2}' | xargs dirname)"
|
|
46
|
+
cat "$PROJECT_DIR/README.md"
|
|
47
|
+
ls "$PROJECT_DIR/"
|
|
48
|
+
# read each sibling .md as needed for context
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Build the dependency graph from ticket comments (each ticket usually names "Sequencing: blocked by AGT-XXX" or "depends on AGT-YYY"). Identify:
|
|
52
|
+
|
|
53
|
+
- Active tickets (state ≠ done): the work to do.
|
|
54
|
+
- Done tickets: assume their content is in main.
|
|
55
|
+
- User-action tickets (the kind where engineering can't proceed without the operator doing something offline): mark these as gates.
|
|
56
|
+
- Deferred / parking-lot tickets (their own comment usually says so): exclude from the chain unless the user says otherwise.
|
|
57
|
+
|
|
58
|
+
## Phase 1 — Confirm the chain with the user
|
|
59
|
+
|
|
60
|
+
Print a short plan to the user (no walls of text):
|
|
61
|
+
|
|
62
|
+
- The active ticket list, in proposed execution order.
|
|
63
|
+
- Sequencing notes (which depend on which; which can run in parallel; which are user-gates).
|
|
64
|
+
- Anything explicitly excluded (deferred tickets) and why.
|
|
65
|
+
|
|
66
|
+
Ask one question: "Run this chain with the standard autonomous-orchestration rules? Or override anything?"
|
|
67
|
+
|
|
68
|
+
If the user says go (or equivalent), proceed. If they push back on the plan, adjust and re-confirm. Do not start firing without explicit go-ahead on the chain shape.
|
|
69
|
+
|
|
70
|
+
## Phase 2 — Drive each ticket
|
|
71
|
+
|
|
72
|
+
For each non-user-gate ticket, in dependency order:
|
|
73
|
+
|
|
74
|
+
### 2.0 — Brief on prior retros for this ticket's repo
|
|
75
|
+
|
|
76
|
+
**Gated on `repo:` being non-empty.** Read the ticket's `repo:` frontmatter field. If it is empty or absent, skip this step silently — vault-internal tickets have no cortex to brief from.
|
|
77
|
+
|
|
78
|
+
Derive the cortex name from the `repo:` value using the **same rule pinned in AGT-173/174**: take the path component after the slash, lowercased. Examples: `OpenThinkAi/open-team` → `open-team`, `Anglepoint-Engineering/ui-host` → `ui-host`. The cortex name is sourced from validated frontmatter, so it is safe as a literal in shell.
|
|
79
|
+
|
|
80
|
+
Run `think brief` and capture stdout. **Do not gate on exit code or empty output** — every failure mode (missing binary, cortex not found, non-zero exit, empty cortex) is non-fatal; the orchestrator proceeds without the brief:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
think brief --cortex <derived-cortex-name> 2>&1 || true
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Treat the captured output as a clearly-labelled background section in your working context: `## Prior context for ticket AGT-XXX (<repo>)`. It is background, not actionable directives — lessons to weigh when deciding how to drive this ticket, not a re-litigation of its spike. If `think` is missing, exits non-zero, or the cortex has no promoted retros yet, note `no prior retros yet for <repo>` and proceed normally.
|
|
87
|
+
|
|
88
|
+
**Fetch at most once per ticket per orchestrator run.** This step runs here at the 2.0 entry point; do not re-fetch in 2b, 2c, or 2d for the same ticket. The spawned `oteam assign` agent runs its own `think brief` via AGT-174 — do not forward this orchestrator's brief output into the spawn; that would double-fetch.
|
|
89
|
+
|
|
90
|
+
### 2a. Product pass (inline, short)
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
oteam assign --inline AGT-XXX
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
If Product returns `✅ DONE — Refined; ready for Engineering spike`, proceed. If `⏸️ PAUSED — Ticket needs answers before Product can refine`, surface to the user — Product can't proceed without their input.
|
|
97
|
+
|
|
98
|
+
### 2b. Engineering spike (background)
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
oteam assign --inline AGT-XXX # with run_in_background: true on the Bash tool
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
When the background task notification arrives, read the task's output file. Three possible outcomes:
|
|
105
|
+
|
|
106
|
+
- **Spike auto-proceeded to implementation (S/H rated, no plan review needed):** continue to 2d.
|
|
107
|
+
- **Spike paused for plan review (M+ scope or has gaps):** read the spike. Decide on each open question:
|
|
108
|
+
- If it's taste-level (file names, fixture shape, default values, sequencing of independent substeps): make the call yourself. Append a `### YYYY-MM-DD — Plan approved` comment to the ticket noting your decisions and the rationale. Advance the ticket frontmatter to `state: in-progress`, move the file to `tickets/in-progress/`, then re-fire `oteam assign --inline AGT-XXX` (background).
|
|
109
|
+
- If it's an architectural decision the design doc doesn't answer: surface to the user. Quote the spike's question. Wait.
|
|
110
|
+
- **Spike failed (`STOP:` error of some kind):** surface to the user with the error.
|
|
111
|
+
|
|
112
|
+
### 2c. Implementation (background)
|
|
113
|
+
|
|
114
|
+
The agent does the work, runs stamp review, stamp merge, push. When the background task notification arrives:
|
|
115
|
+
|
|
116
|
+
- Read the task output.
|
|
117
|
+
- If it pushed to `origin/main`: notify the user immediately with a one-line `🔔 AGT-XXX pushed to <repo> as <sha>` plus a one-sentence summary.
|
|
118
|
+
- If it stamp-merged but the mirror push to GitHub was rejected (the AGT-026 case): SURFACE — divergence is alarming, never auto-reconcile.
|
|
119
|
+
- If stamp gate stayed closed (review never converged): surface the last review's `changes_requested` reasoning to the user.
|
|
120
|
+
- If implementation completed but didn't push (no main push needed, e.g. test-only changes that the agent decided to leave on a branch): note in the user-facing summary.
|
|
121
|
+
|
|
122
|
+
### 2d. QA pass (inline, short)
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
oteam assign --inline AGT-XXX
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
QA verifies the AC against the merged code and archives the ticket. If QA returns `✅ DONE — QA approved; archived`, mark the ticket complete in your internal chain and move to the next ticket. If QA bounces back with `changes_requested`, fire the engineering implementation again (background) with the QA feedback noted in a comment.
|
|
129
|
+
|
|
130
|
+
### 2e. User-action tickets
|
|
131
|
+
|
|
132
|
+
When the chain reaches a user-action ticket:
|
|
133
|
+
|
|
134
|
+
- Stop driving.
|
|
135
|
+
- Surface the ticket to the user with: title, what they need to do (concrete steps, ideally copy-pasteable commands), and why it's blocking.
|
|
136
|
+
- Wait. Do not proceed past it until the user signs off (either by archiving it or telling you "done, move on").
|
|
137
|
+
|
|
138
|
+
## Phase 3 — Post-completion
|
|
139
|
+
|
|
140
|
+
When every active ticket in the chain is archived:
|
|
141
|
+
|
|
142
|
+
- Print a summary: tickets shipped (with SHAs), elapsed time, anything noteworthy that happened during the run.
|
|
143
|
+
- Offer to bump the project's `status:` frontmatter to `shipped` in `<project>/README.md`, if every active ticket is archived and the user hasn't otherwise indicated more work is incoming.
|
|
144
|
+
- Ask if there are any follow-up tickets to file (issues that surfaced during the run that didn't get filed yet).
|
|
145
|
+
|
|
146
|
+
Then stop. Do not chain into the next project automatically; the user picks what to do next.
|
|
147
|
+
|
|
148
|
+
## Output discipline
|
|
149
|
+
|
|
150
|
+
- One status update per state transition. Don't narrate every Bash call.
|
|
151
|
+
- Always notify on push to `origin/main` (single line, immediate).
|
|
152
|
+
- When surfacing a stop condition: name the ticket, name the issue, propose the resolution paths, ask one question. No walls of text.
|
|
153
|
+
- Use the user's preferred voice from feedback memory: terse, technical, no marketing.
|
|
154
|
+
|
|
155
|
+
## Things that are explicitly NOT your job
|
|
156
|
+
|
|
157
|
+
- Filing new tickets unsolicited (use `oteam ticket new` if a clear bug surfaces during the run, but only file when the issue is concrete and unrelated to the chain you're driving — don't bloat the chain).
|
|
158
|
+
- Reconciling stamp/GitHub divergence — surface immediately, do not auto-merge or auto-force-push.
|
|
159
|
+
- Rewriting design docs mid-run — if the design doc is wrong, surface that and wait.
|
|
160
|
+
- Pushing to feature branches that haven't been stamp-reviewed — stamp is the gate.
|
package/dist/index.js
CHANGED
|
@@ -2756,21 +2756,26 @@ import { homedir as homedir5 } from "os";
|
|
|
2756
2756
|
import { dirname, join as join13 } from "path";
|
|
2757
2757
|
import { fileURLToPath } from "url";
|
|
2758
2758
|
var moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
2759
|
-
var
|
|
2759
|
+
var BUNDLED_COMMANDS = [
|
|
2760
|
+
{ src: join13(moduleDir, "assign-ticket.md"), dest: "assign-ticket.md" },
|
|
2761
|
+
{ src: join13(moduleDir, "implement-project.md"), dest: "implement-project.md" }
|
|
2762
|
+
];
|
|
2760
2763
|
function installRolePipelineSlashCommand() {
|
|
2761
|
-
if (!existsSync11(BUNDLED_PROMPT)) return;
|
|
2762
|
-
const bundled = readFileSync8(BUNDLED_PROMPT);
|
|
2763
2764
|
const targets = resolveTargetDirs();
|
|
2764
|
-
for (const
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2765
|
+
for (const { src, dest } of BUNDLED_COMMANDS) {
|
|
2766
|
+
if (!existsSync11(src)) continue;
|
|
2767
|
+
const bundled = readFileSync8(src);
|
|
2768
|
+
for (const dir of targets) {
|
|
2769
|
+
try {
|
|
2770
|
+
mkdirSync9(dir, { recursive: true });
|
|
2771
|
+
const target = join13(dir, dest);
|
|
2772
|
+
if (existsSync11(target)) {
|
|
2773
|
+
const current = readFileSync8(target);
|
|
2774
|
+
if (current.equals(bundled)) continue;
|
|
2775
|
+
}
|
|
2776
|
+
copyFileSync(src, target);
|
|
2777
|
+
} catch {
|
|
2771
2778
|
}
|
|
2772
|
-
copyFileSync(BUNDLED_PROMPT, target);
|
|
2773
|
-
} catch {
|
|
2774
2779
|
}
|
|
2775
2780
|
}
|
|
2776
2781
|
}
|
|
@@ -3072,7 +3077,7 @@ function readMonitoredOrgsFromEnv() {
|
|
|
3072
3077
|
// package.json
|
|
3073
3078
|
var package_default = {
|
|
3074
3079
|
name: "@openthink/team",
|
|
3075
|
-
version: "0.0.
|
|
3080
|
+
version: "0.0.12",
|
|
3076
3081
|
type: "module",
|
|
3077
3082
|
description: "Source-agnostic vault-driven role pipeline for spawning Claude agents against tickets",
|
|
3078
3083
|
bin: {
|
|
@@ -3082,7 +3087,7 @@ var package_default = {
|
|
|
3082
3087
|
"dist"
|
|
3083
3088
|
],
|
|
3084
3089
|
scripts: {
|
|
3085
|
-
build: "tsup && cp src/role-pipeline/assign-ticket.md dist/assign-ticket.md",
|
|
3090
|
+
build: "tsup && cp src/role-pipeline/assign-ticket.md dist/assign-ticket.md && cp src/role-pipeline/implement-project.md dist/implement-project.md",
|
|
3086
3091
|
dev: "tsx src/index.ts",
|
|
3087
3092
|
typecheck: "tsc --noEmit",
|
|
3088
3093
|
test: "node --test --import tsx 'tests/**/*.test.ts'",
|