@drawbridge/drawbridge-agents 0.1.76 → 0.1.78
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.
|
@@ -15,17 +15,27 @@ refused while it shows a failed scenario.
|
|
|
15
15
|
1. One or more story files under `drawbridge-docs/user-stories/`. The **Scenarios** section
|
|
16
16
|
is the checklist; **Expectations** says how each thing should look.
|
|
17
17
|
2. The Asana task id the feature belongs to.
|
|
18
|
-
3. The
|
|
18
|
+
3. The organization id to walk under.
|
|
19
|
+
4. The target: `local` (a release being built on the developer's laptop: dashboard at
|
|
20
|
+
`http://localhost:3000`, the Local database) or `dev`. A release's QA runs on `local`
|
|
21
|
+
before its pull request, so the fixes land in the same pull request; `dev` is for a
|
|
22
|
+
feature already merged.
|
|
19
23
|
|
|
20
24
|
## How to walk a screen
|
|
21
25
|
|
|
22
26
|
From `drawbridge-tests`, every page is opened with
|
|
23
27
|
|
|
24
28
|
```sh
|
|
25
|
-
npm run walk -- /organizations/<org id>/<path>
|
|
26
|
-
npm run walk --
|
|
29
|
+
npm run walk -- /organizations/<org id>/<path> # dashboard on dev
|
|
30
|
+
npm run walk -- --local /organizations/<org id>/<path> # dashboard on the laptop
|
|
31
|
+
npm run walk -- <full url> # share page, website
|
|
27
32
|
```
|
|
28
33
|
|
|
34
|
+
On `local`, every script you write runs the same way, under the api's Local Environment:
|
|
35
|
+
`node lib/target.js local -- node <your script>` from `drawbridge-tests`. The seeding helper
|
|
36
|
+
and the saved session then point at the laptop too (`e2e/.auth/user.local.json`). A local
|
|
37
|
+
walk needs the api, sync and the dashboard running (`npm run local` in each).
|
|
38
|
+
|
|
29
39
|
It signs in, saves a screenshot and prints the headings, buttons, links, inputs and table
|
|
30
40
|
headers on the page. **Read the screenshot file with the Read tool every time.** What you
|
|
31
41
|
report as seen is what is on that image and in that printed list, nothing else. Setup and
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: drawbridge-release
|
|
3
|
+
description: Use when someone gives you a release task from the Asana project "Drawbridge - Releases" and says to run, open, build or promote it — the only way a release moves from Planned to Released. Also use when asked what state a release is in or what its next step is.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run a release
|
|
7
|
+
|
|
8
|
+
One Asana release task is the unit. Its id names everything: the `release/<id>` branch in every app the release touches, `drawbridge-api/scripts/migration-<id>.js` when it moves data, `drawbridge-docs/releases/<id>.md`, and the band on the dev dashboard. The task moves Planned → Building → Review → QA → Approved → Released; every state change is a section move in that project and nothing else records state.
|
|
9
|
+
|
|
10
|
+
The ten lines below are the release, as Darren confirmed them on 2026-10-22. The skill owns lines 1 to 5 and 10 and runs them without anyone present once line 2 has its yes. A developer owns 6 and 9. A QA person owns 7 and 8. The skill never does a developer's or a tester's line for them.
|
|
11
|
+
|
|
12
|
+
1. A person gives the skill the release task link. The skill checks `gh auth status`.
|
|
13
|
+
2. The skill reads the task and subtasks, writes the stories, sends ONE numbered list and waits for the yes.
|
|
14
|
+
3. Task → Building: branches, the release document, the band.
|
|
15
|
+
4. The skill builds on the release branches against the Local database, with the QA agent run locally.
|
|
16
|
+
5. One pull request per repo, assigned to the developer named in line 2. Task → Review.
|
|
17
|
+
6. The developer reviews, runs the branch locally, merges; runs any migration on dev; moves the task → QA and assigns the QA person.
|
|
18
|
+
7. The QA person tests on dev.
|
|
19
|
+
8. The QA person moves the task → Approved.
|
|
20
|
+
9. The developer promotes by hand, with the skill as checklist.
|
|
21
|
+
10. The skill writes "What's new", completes the subtasks, moves the task → Released, cleans up.
|
|
22
|
+
|
|
23
|
+
## Line 1: start
|
|
24
|
+
|
|
25
|
+
Read the release task and every subtask through `drawbridge-tests/lib/asana.js` (`api( 'GET', '/tasks/<id>?opt_fields=name,notes,memberships.section.name' )`, then `/tasks/<id>/subtasks`). Subtasks live in "DrawBridge - Application" and stay there. `gh auth status` must pass; if it does not, stop and tell the person `brew install gh && gh auth login`. Other developers start releases from their own machines, so this is never assumed.
|
|
26
|
+
|
|
27
|
+
## Line 2: the one list
|
|
28
|
+
|
|
29
|
+
For every subtask, find or write the story (`drawbridge-feature` step 1). Then ONE numbered list to the person who started the release, each item three plain sentences (`conventions/rules.md` rule 7), holding:
|
|
30
|
+
|
|
31
|
+
- every unknown from every story;
|
|
32
|
+
- **who on the development team takes the pull requests** (a GitHub username). Asked now so nobody needs to be present between lines 3 and 5. Never guess a reviewer;
|
|
33
|
+
- **a package publish, if any subtask names `@drawbridge/components` or `@drawbridge/drawbridge-utils`**, in these words: this release publishes a package; the package is built, reviewed and merged to the package's `main` first; the person publishes it when asked (the skill cannot), the publish needs the one-time password until the automation token (queue task 1218041740718540) exists; the apps' pull requests cannot merge until their pin bumps resolve.
|
|
34
|
+
|
|
35
|
+
Wait for the yes. Nothing below runs before it.
|
|
36
|
+
|
|
37
|
+
## Line 3: Building
|
|
38
|
+
|
|
39
|
+
1. Move the task to Building (`POST /sections/1219601033297172/addTask { task }`).
|
|
40
|
+
2. `release/<id>` in every repo a subtask touches, off `develop` (components and utils off `main`; docs off `main`), each in a worktree under `/Users/darrenshea/Projects/.worktrees/<repo>-release-<id>` so no main checkout changes branch.
|
|
41
|
+
3. Copy `drawbridge-docs/templates/release.md` to `releases/<id>.md`, fill Scope and Branches (reviewer from line 2), commit on the docs branch. The markdown is the one record; there is no json.
|
|
42
|
+
4. Write the task link into `drawbridge-api/release.json`, commit on the api's `develop` directly ("release <id>: band"), push. Dev shows the yellow band above the account once the api redeploys. This is the only develop commit before the pull requests merge.
|
|
43
|
+
5. If the release task has no subtask named "Marketing: What's new", create one.
|
|
44
|
+
|
|
45
|
+
## Line 4: build, on Local
|
|
46
|
+
|
|
47
|
+
All work on the release branches against the **Local** database. Develop and its schema are never touched while a release is being built, and one release at a time is promoted to develop.
|
|
48
|
+
|
|
49
|
+
1. **Local up.** `npm run migrate -- refresh` in the api (copies dev into Local; `--dry` first), then `npm run local` in every app the release touches: dashboard 3000, share 3001, website 3002, api 4000, sync 4001, webhooks 4002. The scripts force the ports; nothing sets them.
|
|
50
|
+
2. **Package first.** A package subtask is built, reviewed and merged to the package's `main` before any app subtask that depends on it; when it is merged, ask the person to publish, then bump the pin on the apps' release branches.
|
|
51
|
+
3. **Per subtask**, on the release branch: read the story and the reference page, one graph query, failing test first where a suite exists, the change, `npm test` in that repo. One commit per subtask, its message starting with the subtask id.
|
|
52
|
+
4. **Migration.** If any subtask moves data, ONE file, `drawbridge-api/scripts/migration-<id>.js`, exporting `({ controller }) => async ({ dryRun, organization, ...args }) => counts`, holding every data step. It uses the controller only; a dry run refuses controller writes but cannot refuse a native `collection.drop()` or `dropIndex()`, so a step that drops anything branches on `dryRun` itself and reports what it would drop. Prove it on Local: `npm run migrate -- <id> --dry --env local`, then `--env local`. The runner prints the counts and writes `runs/<env>-<id>-<time>.json`; nothing copies them anywhere.
|
|
53
|
+
5. **Walk every touched app on Local**: `npm run walk -- --local <path or url>` from drawbridge-tests (dashboard at `localhost:3000`; sync must be running for anything live). Record what was seen; a label quoted later comes from this walk.
|
|
54
|
+
6. **QA agent on Local.** Dispatch `drawbridge-qa` with `target : local`, once per subtask that has a story (story paths, the SUBTASK id, the organization id from `drawbridge-tests/fixtures/e2e-org.md`, present on Local because Local is a copy of dev). Fix every fail on the release branch, redispatch, until every `drawbridge-tests/results/qa/<subtask id>.json` reads `fails : 0`. The fixes are commits in the same pull request; that is why the agent runs here and not on dev (Darren: "all agent work is done locally so the work and fixes get committed as part of the PR").
|
|
55
|
+
**Inbound webhooks are the exception.** Every Local Environment points `APP_CLIENT_WEBHOOKS_URI` at `http://localhost:4002`, which Shopify, Stripe and Twilio cannot reach, so a change to how a webhook is received or handled is marked in the Scope table as "webhooks: tested on dev" and the QA person checks it on dev in line 7.
|
|
56
|
+
7. **Review.** `superpowers:code-reviewer` against the stories, then `ponytail-review`, on each repo's diff.
|
|
57
|
+
8. Push the release branches.
|
|
58
|
+
|
|
59
|
+
## Line 5: Review
|
|
60
|
+
|
|
61
|
+
1. One pull request per repo: `gh pr create --base develop --head release/<id> --title "Release <id>: <task name>" --assignee <developer> --reviewer <developer> --body <the Scope table, the per-subtask commits, the QA reports' paths, and the migration's dev command if there is one>`. Components and utils target `main`.
|
|
62
|
+
2. Fill the Branches table in `releases/<id>.md` with the PR links; commit.
|
|
63
|
+
3. Put the PR links on the release task as ONE numbered list (`drawbridge-asana-comment`), assign the task to the developer, move it to Review (`POST /sections/1219762451512990/addTask`).
|
|
64
|
+
4. Stop. Report the PR links.
|
|
65
|
+
|
|
66
|
+
## Lines 6 to 8: the developer and the QA person
|
|
67
|
+
|
|
68
|
+
The skill does none of this. For the record, so the skill can answer "what is the next step":
|
|
69
|
+
|
|
70
|
+
- Line 6, the developer: reviews the diff, runs the branch locally, approves and merges. Dev deploys itself. If there is a migration: `npm run migrate -- <id> --dry --env dev` from the api checkout on `develop`, read the printed result, then without `--dry`. Then moves the task to QA and assigns the QA person in Asana.
|
|
71
|
+
- Line 7, the QA person: tests on dev. The band already names the release.
|
|
72
|
+
- Line 8, the QA person: moves the task to Approved.
|
|
73
|
+
|
|
74
|
+
## Line 9: promote, as the developer's checklist
|
|
75
|
+
|
|
76
|
+
**Production is done by a developer, by hand: every push to `main`, every deploy, the migration** (Darren: "All production deployment and migrations will be done manually, you are only to aid a developer deploying to production"). The skill hands over one step at a time, waits for "done", verifies by reading, records, then hands over the next.
|
|
77
|
+
|
|
78
|
+
1. Confirm the task sits in Approved; refuse otherwise.
|
|
79
|
+
2. Hand over the preparation: the window (avoid 00:00 and 02:00 UTC, sync's scheduled jobs) and the Atlas snapshot. Wait.
|
|
80
|
+
3. Per app, in this order unless the release doc says otherwise (dashboard, api, sync, share, webhooks, website): hand over the fast-forward of `main` to the exact tested `develop` commit (`git push origin <sha>:refs/heads/main`), then the Deploy click in DigitalOcean (prod apps deploy from `main` with deploy-on-push off). Verify by reading: the deployment ACTIVE, `/health` reporting the commit. Note the commit in the release doc's Promote section.
|
|
81
|
+
4. Migration, after the api is ACTIVE and before sync: from the developer's api checkout on `main` at the promoted commit, with the api's two-line `.env.production` beside `migrate.js`: `npm run migrate -- <id> --env prod --dry --sha <promoted api commit>`, read the result, then without `--dry`. (The deployed api container can run it too, through `doctl apps console`.) Then `git rm drawbridge-api/scripts/migration-<id>.js`, committed on develop, and `main` fast-forwarded once more.
|
|
82
|
+
5. Hand over the verification list from the release doc's Promote section; the developer reports what they saw; the skill fills it in.
|
|
83
|
+
|
|
84
|
+
## Line 10: Released
|
|
85
|
+
|
|
86
|
+
1. **What's new.** Write the marketing breakdown into the "Marketing: What's new" subtask, in the customer's words, one item per subtask a merchant would notice (`drawbridge-asana-comment` for the shape, `humanizer` for the words).
|
|
87
|
+
2. Complete every subtask (Application → Complete). Move the release task to Released (`POST /sections/1219601137919036/addTask`).
|
|
88
|
+
3. Remove the worktrees; refresh the knowledge graph (`drawbridge-ship-feature` step 5). Report the promoted commits.
|
|
89
|
+
|
|
90
|
+
## What the skill never does
|
|
91
|
+
|
|
92
|
+
- Push `main`, deploy production, run anything against the production or dev database, publish a package, merge a pull request, assign the QA person or move the task to QA, Approved. Those are a developer's or a tester's lines.
|
|
93
|
+
- Name a reviewer, a tester, a window or a release scope that nobody told it. Each is one numbered question in line 2.
|
|
94
|
+
- Write a release document, branch or migration under any name but the Asana id.
|
|
95
|
+
- Build or run the QA agent against dev or develop before the pull requests merge. Local only.
|
|
96
|
+
|
|
97
|
+
## Section ids
|
|
98
|
+
|
|
99
|
+
Planned `1219601041167595`, Building `1219601033297172`, Review `1219762451512990`, QA `1219601033155111`, Approved `1219601033299066`, Released `1219601137919036`; project `1219601041167594`, workspace `15457086713130`.
|
|
@@ -57,22 +57,21 @@ quietly that dev served stale code the whole time.
|
|
|
57
57
|
- **Production runs inside the deployed api container**, never from a laptop,
|
|
58
58
|
so no laptop ever holds a production file: `doctl apps console <prod api app
|
|
59
59
|
id> drawbridge-api`, then `op run --environment "$OP_ENVIRONMENT_ID" -- node
|
|
60
|
-
migrate.js <asana id> --env prod --dry --sha <promoted commit>`, then the
|
|
61
|
-
without `--dry
|
|
62
|
-
and `scripts/`. There is no git there, so the runner proves `--sha`
|
|
60
|
+
migrate.js <release asana id> --env prod --dry --sha <promoted commit>`, then the
|
|
61
|
+
same without `--dry`. The image carries `migrate.js` and `scripts/`. There is no git there, so the runner proves `--sha`
|
|
63
62
|
against `APP_COMMIT_HASH` (the deployed commit, injected by the app spec); in
|
|
64
63
|
a checkout it still refuses production off `main`, at the wrong commit, or with
|
|
65
64
|
`scripts/`, `lib/` or `migrate.js` modified. `cat` the counts file from the
|
|
66
65
|
console shell afterwards, outside `op run`, to read it unconcealed.
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
has not run.
|
|
66
|
+
- **The runner records nothing but its counts file**, and nothing else records
|
|
67
|
+
a run either: a developer runs the migration on dev after the pull request
|
|
68
|
+
merges and reads the printed result, and runs it on production from their
|
|
69
|
+
laptop (the api's two-line `.env.production`) during the promote (Darren,
|
|
70
|
+
2026-10-22: the runner "shouldn't be writing to a row either"; "a development
|
|
71
|
+
migration just returns the result"). There is no release json. "Has it run
|
|
72
|
+
on prod?" is answered by `scripts/migration-<id>.js` still existing: after
|
|
73
|
+
the production run the developer `git rm`s it, so the folder only ever holds
|
|
74
|
+
what has not run.
|
|
76
75
|
- Add it to the release document in `drawbridge-docs/releases/` for the launch it
|
|
77
76
|
belongs to, with the ordering constraint stated: what has to be deployed before
|
|
78
77
|
it can run, and what breaks if it runs early.
|
|
@@ -56,8 +56,16 @@ every later walk until it expires (`e2e/auth.setup.js`, `lib/otc.js`).
|
|
|
56
56
|
npm run walk -- /organizations/<org id>/suppressions # a dashboard path
|
|
57
57
|
npm run walk -- https://<slug>.dev.drwbrdg.com/<campaign> # any full URL (share, website)
|
|
58
58
|
npm run walk -- /organizations/<org id>/campaigns --out shot.png
|
|
59
|
+
npm run walk -- --local /organizations/<org id>/campaigns # the laptop: localhost:3000, the Local database
|
|
60
|
+
npm run walk -- --production https://trydrawbridge.com/pricing # public pages only; no signed-in production walk
|
|
59
61
|
```
|
|
60
62
|
|
|
63
|
+
`--local` re-runs the walk under the api's Local Environment through the api's `scripts/op.sh`
|
|
64
|
+
(`lib/target.js`), so this repo keeps its single dev-pointing `.env`; the api, sync and the
|
|
65
|
+
dashboard must be running (`npm run local` in each). Each target keeps its own saved session
|
|
66
|
+
(`e2e/.auth/user.local.json` for the laptop). Any script of your own runs the same way:
|
|
67
|
+
`node lib/target.js local -- node <script>`.
|
|
68
|
+
|
|
61
69
|
It signs in if the saved session is missing or stale, opens the page, saves a screenshot
|
|
62
70
|
(default `results/walk/<timestamp>.png`) and prints the headings, buttons, links and table
|
|
63
71
|
headers a person would see. **Read the screenshot** (the Read tool renders images), then
|
package/package.json
CHANGED
|
@@ -78,8 +78,9 @@ const unresolved = []
|
|
|
78
78
|
for (const name of fs.readdirSync(familyRoot, { withFileTypes: true })) {
|
|
79
79
|
if (!name.isDirectory() || !name.name.startsWith('drawbridge-')) continue
|
|
80
80
|
// drawbridge-agents is the meta-tooling repo (this script, the hook, the convention docs all
|
|
81
|
-
// contain the literal tag strings) — tags live in the app repos, so skip it
|
|
82
|
-
|
|
81
|
+
// contain the literal tag strings) — tags live in the app repos, so skip it, and skip its
|
|
82
|
+
// worktrees too (drawbridge-agents-<branch>), which carry the same strings.
|
|
83
|
+
if (name.name.startsWith('drawbridge-agents')) continue
|
|
83
84
|
const repoRoot = path.join(familyRoot, name.name)
|
|
84
85
|
walk(repoRoot, (file) => {
|
|
85
86
|
if (!SOURCE_EXTENSIONS.has(path.extname(file))) return
|