@drawbridge/drawbridge-agents 0.1.77 → 0.1.79

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 dev organization id to walk under.
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> # dashboard
26
- npm run walk -- <full url> # share page, website
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**: their GitHub username (for the pull requests) and their Asana name (for the task). 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. A release that publishes a package stops once more, at the publish (line 4 step 2); everything else between lines 3 and 5 runs without anyone present.
36
+
37
+ ## Line 3: Building
38
+
39
+ 1. **One release at a time.** List the project's tasks (`GET /projects/1219601041167594/tasks?opt_fields=name,memberships.section.name`). If any other release sits in Building, Review, QA or Approved, stop and say which one; only one release is being built or tested at a time (Darren, 2026-10-22). Then move this 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`), each in a worktree under `/Users/darrenshea/Projects/.worktrees/<repo>-release-<id>` so no main checkout changes branch. **drawbridge-docs is the exception**: its `release/<id>` branch is made in the main docs checkout (docs is `main`-only and single-writer), because `npx drawbridge-agents-check-stories` reads nothing from a worktree path (Asana 1218852240225835). "Repo a subtask touches" includes docs, components and utils, not only the six apps.
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. If `drawbridge-api/release.json` does not already carry this task's link, write it, 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. When the link is already there, say so and move on.
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. Anything a person must do around the run (export a collection and read it back before a drop, take a snapshot) is written into the release doc's Migrations section as the developer's steps, not into the file. 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: `APP_TEST_ORG_ID` in `drawbridge-tests/.env`, the e2e organization `fixtures/e2e-org.md` describes, present on Local because Local is a copy of dev). A subtask spanning many stories gets one report listing them all. 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, write to the production or dev database (the refresh READS dev to copy it into Local, and that is all), publish a package, merge a pull request, assign the QA person or move the task to QA or Approved. Those are a developer's or a tester's lines.
93
+ - Name a reviewer or a release scope that nobody told it; both are asked in line 2. The tester is the developer's choice at line 6 and the window is the developer's at line 9; the skill asks for neither.
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
+ Releases project `1219601041167594` (workspace `15457086713130`): Planned `1219601041167595`, Building `1219601033297172`, Review `1219762451512990`, QA `1219601033155111`, Approved `1219601033299066`, Released `1219601137919036`. Application project, where the subtasks live: Complete `1213887707425532`.
@@ -1,6 +1,6 @@
1
1
  # Migrations live in the api
2
2
 
3
- Every one-off migration and backfill goes in `drawbridge-api/scripts.js`.
3
+ Every one-off migration and backfill is one file in `drawbridge-api/scripts/`, `migration-<release asana id>.js`, run through `drawbridge-api/migrate.js` and nothing else.
4
4
 
5
5
  **The only exception is media processing** — work that needs ffmpeg or sharp to
6
6
  open an image or a video. Those dependencies exist in `drawbridge-sync` and
@@ -46,33 +46,36 @@ quietly that dev served stale code the whole time.
46
46
  return (`{ found, updated }` or whatever the counts are). The first run of a
47
47
  migration is a read.
48
48
  - Run it only through the runner. On a laptop, from the api checkout:
49
- `npm run migrate -- <asana id> --dry --env dev`, then
50
- `--organization <id> --env dev --release <slug>`, then `--env dev --release <slug>`.
49
+ `npm run migrate -- <release asana id> --dry --env dev`, then
50
+ `--organization <org id> --env dev`, then `--env dev`. There is no `--release`
51
+ flag: the migration id IS the release id.
51
52
  No env file holds a value: the runner re-runs itself through `scripts/op.sh`
52
53
  with the file `--env` names (`.env.local` / `.env.development`, two lines naming
53
54
  a 1Password Environment), so the Environment is injected the way the servers
54
55
  get it. It refuses the wrong cluster, hands a dry run a controller that throws
55
56
  on any write, and writes the result to `runs/<env>-<fn>-<time>.json` (read the
56
57
  file, never the console: `op run` conceals anything that looks like a secret).
57
- - **Production runs inside the deployed api container**, never from a laptop,
58
- so no laptop ever holds a production file: `doctl apps console <prod api app
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 same
61
- without `--dry` and with `--release <slug>`. The image carries `migrate.js`
62
- and `scripts/`. There is no git there, so the runner proves `--sha`
63
- against `APP_COMMIT_HASH` (the deployed commit, injected by the app spec); in
64
- a checkout it still refuses production off `main`, at the wrong commit, or with
65
- `scripts/`, `lib/` or `migrate.js` modified. `cat` the counts file from the
66
- console shell afterwards, outside `op run`, to read it unconcealed.
67
- - A real fleet run records itself when drawbridge-docs sits beside the api:
68
- `drawbridge-docs/releases/<slug>.json` gets
69
- `migrations.<asana id>.<development|production> = true`, and the release
70
- document `releases/<slug>.md` gets a row in its Migrations table. That is how
71
- "has it run on prod?" is answered. In the container there is no docs checkout:
72
- the runner prints exactly which flag and row to write, and you commit them
73
- from a laptop from the counts file. After a production run the promote step
74
- deletes `scripts/migration-<asana id>.js`, so the folder only ever holds what
75
- has not run.
58
+ - **Production is run by a developer, by hand, from their api checkout** on
59
+ `main` at the promoted commit with a clean tree, with the api's two-line
60
+ `.env.production` beside `migrate.js` (Darren, 2026-10-22: "the api is the
61
+ only place that needs this, and locally it's there"):
62
+ `npm run migrate -- <release asana id> --env prod --dry --sha <promoted commit>`,
63
+ then the same without `--dry`. The runner refuses production off `main`, at
64
+ the wrong commit, or with `scripts/`, `lib/` or `migrate.js` modified. The
65
+ deployed api container can run it too (`doctl apps console <prod api app id>
66
+ drawbridge-api`, then the `op run --environment "$OP_ENVIRONMENT_ID" -- node
67
+ migrate.js …` form; the image carries `migrate.js` and `scripts/`, there is no
68
+ git, so `--sha` is proven against `APP_COMMIT_HASH`). An agent never runs it:
69
+ it hands the developer the command and verifies by reading afterwards.
70
+ - **The runner records nothing but its counts file**, and nothing else records
71
+ a run either: a developer runs the migration on dev after the pull request
72
+ merges and reads the printed result, and runs it on production from their
73
+ laptop (the api's two-line `.env.production`) during the promote (Darren,
74
+ 2026-10-22: the runner "shouldn't be writing to a row either"; "a development
75
+ migration just returns the result"). There is no release json. "Has it run
76
+ on prod?" is answered by `scripts/migration-<id>.js` still existing: after
77
+ the production run the developer `git rm`s it, so the folder only ever holds
78
+ what has not run.
76
79
  - Add it to the release document in `drawbridge-docs/releases/` for the launch it
77
80
  belongs to, with the ordering constraint stated: what has to be deployed before
78
81
  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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawbridge/drawbridge-agents",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "description": "Shared agent-instruction content (rules, code style, conventions) for the drawbridge-* monorepo.",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {