@drawbridge/drawbridge-agents 0.1.80 → 0.1.82
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.
|
@@ -5,7 +5,7 @@ description: Use when someone gives you a release task from the Asana project "D
|
|
|
5
5
|
|
|
6
6
|
# Run a release
|
|
7
7
|
|
|
8
|
-
One Asana release task is the unit. Its id names everything: the `
|
|
8
|
+
One Asana release task is the unit. Its id names everything: the `feature/<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
9
|
|
|
10
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
11
|
|
|
@@ -14,7 +14,7 @@ The ten lines below are the release, as Darren confirmed them on 2026-10-22. The
|
|
|
14
14
|
3. Task → Building: branches, the release document, the band.
|
|
15
15
|
4. The skill builds on the release branches against the Local database, with the QA agent run locally.
|
|
16
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.
|
|
17
|
+
6. The developer reviews, runs the branch locally, merges (only when no other release is in QA or Approved); runs any migration on dev; moves the task → QA and assigns the QA person.
|
|
18
18
|
7. The QA person tests on dev.
|
|
19
19
|
8. The QA person moves the task → Approved.
|
|
20
20
|
9. The developer promotes by hand, with the skill as checklist.
|
|
@@ -36,10 +36,10 @@ Wait for the yes. Nothing below runs before it. A release that publishes a packa
|
|
|
36
36
|
|
|
37
37
|
## Line 3: Building
|
|
38
38
|
|
|
39
|
-
1. **
|
|
40
|
-
2. `
|
|
39
|
+
1. **Many releases build at once; one at a time reaches develop.** List the project's tasks (`GET /projects/1219601041167594/tasks?opt_fields=name,memberships.section.name`). Other releases in Building or Review are fine: every release is built on its own branches against the Local database, so they do not touch each other (Darren, 2026-10-22: "We should be able to do multiple releases at once since the code is all being done locally anyways"). Say which ones are in flight and go on. The lane that holds one release is develop: a release in QA or Approved owns dev until it is Released, and the developer merges no other release's pull requests meanwhile (line 6). This step never blocks on it; the merge does. Then move this task to Building (`POST /sections/1219601033297172/addTask { task }`).
|
|
40
|
+
2. `feature/<id>` in every repo a subtask touches, off `develop` (components and utils off `main`): a git-flow FEATURE branch, never `release/<id>`, because the repos carry git-flow config and a client's "Finish release" merges into `main` with a tag, which would put unapproved code on main before dev QA; "Finish feature" merges into `develop`, which is what this flow does (Darren, 2026-10-22; Almond keeps its older `release/` name). Each in a worktree under `/Users/darrenshea/Projects/.worktrees/<repo>-feature-<id>` so no main checkout changes branch. **drawbridge-docs is the exception**: its `feature/<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
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.
|
|
42
|
+
4. Write this task's link into `drawbridge-api/release.json` and commit it on the api's `feature/<id>` branch ("release <id>: band"), never on `develop`: with several releases building at once, a band written to develop at open would name a release that is not on dev. The band reaches develop with the merge, and dev shows it above the account once the api redeploys, which is exactly when that release is the one on dev. A release that touches no api code still gets an api `feature/<id>` branch carrying this one commit and its own pull request at line 5. Nothing is committed to develop before the pull requests merge.
|
|
43
43
|
5. Move every subtask from Application → Queue to Application → In progress (`POST /sections/1211315620607633/addTask { task }`). In the Application project, Queue means not scheduled and In progress means in a release (Darren, 2026-10-22); Complete comes at line 10. The release task itself lives in the Releases project only, never in Application or the Backlog, because a release draws its subtasks from both (Darren, 2026-10-22: "releases will include application tasks and backlog items, so their own board makes more sense"). A Backlog subtask keeps its Backlog membership; only Application subtasks get the Queue → In progress move.
|
|
44
44
|
6. **No pull request yet.** No "Marketing: What's new" subtask yet either: it is created, written and completed in one go at line 10, so developers and QA never see an open marketing item among the subtasks they are building and testing (Darren, 2026-10-22: "we should not have the marketing task in a release until it's completed, as it's confusing for the developers and qa people"). Nothing is opened, drafted or assigned at this point; the developer hears nothing until line 5, when the branch is finished. A pull request opened early reads to the developer as "review this now" and there is nothing to review (Darren, 2026-10-22, after the first run).
|
|
45
45
|
|
|
@@ -47,13 +47,13 @@ Wait for the yes. Nothing below runs before it. A release that publishes a packa
|
|
|
47
47
|
|
|
48
48
|
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.
|
|
49
49
|
|
|
50
|
-
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 components app (`npm run app` in drawbridge-components) is 3003. The scripts force the ports; nothing sets them.
|
|
50
|
+
1. **Local up.** `npm run migrate -- refresh` in the api (copies dev into Local; `--dry` first; there is ONE Local database, so when another release is being built on this machine at the same time, a refresh resets its data mid-walk: say so and agree a moment before running it), then `npm run local` in every app the release touches: dashboard 3000, share 3001, website 3002, api 4000, sync 4001, webhooks 4002; the components app (`npm run app` in drawbridge-components) is 3003. The scripts force the ports; nothing sets them.
|
|
51
51
|
2. **Package first, and the publish never blocks.** Every subtask that touches `@drawbridge/drawbridge-utils` or `@drawbridge/components` is built before any app subtask, so the publish is the earliest thing the person is asked for, and it never pauses the build (Darren, 2026-10-22: "I had to wait a while for the publishing code to be written"; "the publish step includes merging each npm package to main, and bumping the pin(s)"). The whole package step, per package, utils before components (components peer-depends on utils):
|
|
52
|
-
1. Build the package subtasks on `
|
|
52
|
+
1. Build the package subtasks on `feature/<id>` in that package, tests first, `npm test` and `npm run test:app` (components) green, the two review passes.
|
|
53
53
|
2. Bump the package's own version in its `package.json` (patch), commit, push, and open its pull request to the package's `main` (`gh pr create --base main …`), assigned to the developer from line 2. Put the link on the release task.
|
|
54
54
|
3. Ask the person for the publish, as one numbered item with the exact words: merge that pull request, then from the package checkout on `main`: `git pull && npm run build` (tsup, tests, `npm publish` with the one-time password), then confirm with `npm view <package> version`.
|
|
55
55
|
4. **Keep going** on the app subtasks. For one that needs the new package code, `npm link` the local package checkout into the app worktree so it is written and tested against it now.
|
|
56
|
-
5. When `npm view <package> version` shows the new version (checked between subtasks, never by stopping): bump the pin to that exact version in **every consumer in the family**, not only the release's (Darren, 2026-10-22: "Once a package is published, all consumer pins should also be updated"; pins are version-exact family-wide, `conventions/drawbridge-packages.md`). One command does it: `npx drawbridge-agents-bump <package> <version>` (from any family checkout; `--dry` lists the consumers first) finds every consumer, keeps each one's field, installs the exact version so the lockfile names it, commits "<package> <version>" and pushes each repo's current branch. Before running it, the release's own consumers must have their `
|
|
56
|
+
5. When `npm view <package> version` shows the new version (checked between subtasks, never by stopping): bump the pin to that exact version in **every consumer in the family**, not only the release's (Darren, 2026-10-22: "Once a package is published, all consumer pins should also be updated"; pins are version-exact family-wide, `conventions/drawbridge-packages.md`). One command does it: `npx drawbridge-agents-bump <package> <version>` (from any family checkout; `--dry` lists the consumers first) finds every consumer, keeps each one's field, installs the exact version so the lockfile names it, commits "<package> <version>" and pushes each repo's current branch. Before running it, the release's own consumers must have their `feature/<id>` branch checked out (the worktrees), so they take the bump there, while every other consumer takes a pin-only commit on its integration branch. Unlink first where a worktree was linked; run the tests after. A sibling package bumped this way is itself published by the same steps before the apps that depend on it.
|
|
57
57
|
6. No app pull request opens while a pin still names a version the registry does not have.
|
|
58
58
|
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.
|
|
59
59
|
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.
|
|
@@ -67,8 +67,8 @@ All work on the release branches against the **Local** database. Develop and its
|
|
|
67
67
|
|
|
68
68
|
Only when every repo's release branch is finished: every subtask committed, `npm test` green in each repo, every QA report at `fails : 0`, both review passes done, the branches pushed. A pull request is the request to review, so it exists only once there is something to review.
|
|
69
69
|
|
|
70
|
-
1. One pull request per repo: `gh pr create --base develop --head
|
|
71
|
-
2. Fill the Branches table in `releases/<id>.md` with the PR links; commit.
|
|
70
|
+
1. One pull request per repo: `gh pr create --base develop --head feature/<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`.
|
|
71
|
+
2. Every pull request body ends with the lane rule in one line: "Merge only when no other release is in QA or Approved on the Releases board; dev holds one release at a time." Fill the Branches table in `releases/<id>.md` with the PR links; commit.
|
|
72
72
|
3. Attach every QA report's screenshots to the release task (`node lib/asana-attach.js <release id> <png>` from drawbridge-tests, one per scenario, named `<subtask id>-<scenario>.png`), because the reports under `results/qa/` are gitignored and exist only on the machine that ran them. Then 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`).
|
|
73
73
|
4. Stop. Report the PR links.
|
|
74
74
|
|
|
@@ -76,7 +76,7 @@ Only when every repo's release branch is finished: every subtask committed, `npm
|
|
|
76
76
|
|
|
77
77
|
The skill does none of this. For the record, so the skill can answer "what is the next step":
|
|
78
78
|
|
|
79
|
-
- 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`. The developer may have an agent run those two dev commands on their explicit instruction in their own session (Darren, 2026-10-22); the skill never runs them on its own, and no agent ever runs the production one. Then moves the task to QA and assigns the QA person in Asana.
|
|
79
|
+
- Line 6, the developer: reviews the diff, runs the branch locally, approves and merges, but only when no other release sits in QA or Approved: dev carries one release at a time, and a second merge would put two releases' code in front of the QA person under one band (Darren, 2026-10-22: "only 1 QA release can hit develop at any given time"). 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`. The developer may have an agent run those two dev commands on their explicit instruction in their own session (Darren, 2026-10-22); the skill never runs them on its own, and no agent ever runs the production one. Then moves the task to QA and assigns the QA person in Asana.
|
|
80
80
|
- Line 7, the QA person: tests on dev. The band already names the release.
|
|
81
81
|
- Line 8, the QA person: moves the task to Approved.
|
|
82
82
|
|
package/bin/bump.js
CHANGED
|
@@ -30,9 +30,10 @@ const consumersOf = (manifests, name) => Object.entries(manifests)
|
|
|
30
30
|
|
|
31
31
|
const saveFlag = (field) => FLAGS[field]
|
|
32
32
|
|
|
33
|
-
// A pin lands on an integration branch or
|
|
34
|
-
// stray
|
|
35
|
-
|
|
33
|
+
// A pin lands on an integration branch or a release's own branch (feature/<asana id>,
|
|
34
|
+
// digits only), never on a stray branch someone left checked out (growth-b sat on
|
|
35
|
+
// ship-main). Almond's older release/<id> name is honoured until it merges.
|
|
36
|
+
const takesBump = (branch) => branch === 'develop' || branch === 'main' || /^(feature|release)\/\d+$/.test(branch)
|
|
36
37
|
|
|
37
38
|
const readManifests = (projectsDir) => Object.fromEntries(
|
|
38
39
|
fs.readdirSync(projectsDir)
|
|
@@ -69,7 +70,7 @@ const main = () => {
|
|
|
69
70
|
const dir = path.join(projectsDir, repo)
|
|
70
71
|
const branch = run(dir, 'git', [ 'branch', '--show-current' ])
|
|
71
72
|
if (current === version) { console.log(repo + ': already ' + version + ' (' + field + ', ' + branch + ')'); continue }
|
|
72
|
-
if (!takesBump(branch)) { console.log(repo + ': skipped, on ' + (branch || 'a detached head') + ' (check out develop, main or
|
|
73
|
+
if (!takesBump(branch)) { console.log(repo + ': skipped, on ' + (branch || 'a detached head') + ' (check out develop, main or feature/<asana id> first)'); continue }
|
|
73
74
|
if (dry) { console.log(repo + ': ' + current + ' -> ' + version + ' (' + field + ', ' + branch + ')'); continue }
|
|
74
75
|
run(dir, 'npm', [ 'install', '--save-exact', saveFlag(field), name + '@' + version, '--no-audit', '--no-fund', '--loglevel=error' ])
|
|
75
76
|
const files = [ 'package.json', 'package-lock.json' ]
|
|
@@ -5,9 +5,10 @@ Branches use the **full gitflow prefixes, always spelled out**. Never use abbrev
|
|
|
5
5
|
| Prefix | Use |
|
|
6
6
|
| --- | --- |
|
|
7
7
|
| `feature/<name>` | New features / changes (branched from `develop`) |
|
|
8
|
+
| `feature/<asana id>` | A release's work (since 2026-10-22): the Releases project task id, the same id as `drawbridge-api/scripts/migration-<id>.js` and `drawbridge-docs/releases/<id>.md`; one branch per app the release touches, off `develop`, built against the Local database, merged by a developer through a pull request. It is a feature branch, not a git-flow release branch, on purpose: the repos carry git-flow config, and a client's "Finish release" merges into `main` with a tag, which would put unapproved code on main before dev QA. "Finish feature" merges into `develop`, which is what the flow does. Almond (`1219601137920078`) keeps its older `release/` name; everything from Butterscotch on is `feature/`. |
|
|
8
9
|
| `bugfix/<name>` | Non-urgent bug fixes |
|
|
9
10
|
| `hotfix/<name>` | Urgent production fixes (branched from `main`) |
|
|
10
|
-
| `release/<
|
|
11
|
+
| `release/<version>` | Not used by the release flow: one release is in flight at a time, so `develop` is the release and `main` is fast-forwarded to it at promote (Darren, 2026-10-22). Reserved for git-flow's own meaning should that change |
|
|
11
12
|
| `chore/<name>` | Maintenance — dependency bumps, config, cleanup |
|
|
12
13
|
| `support/<name>` | Long-lived support branches |
|
|
13
14
|
|
|
@@ -31,7 +31,7 @@ quietly that dev served stale code the whole time.
|
|
|
31
31
|
|
|
32
32
|
- One release has at most one migration file,
|
|
33
33
|
`drawbridge-api/scripts/migration-<release asana id>.js`, named for the
|
|
34
|
-
RELEASE task (the same id as the `
|
|
34
|
+
RELEASE task (the same id as the `feature/<id>` branches and
|
|
35
35
|
`drawbridge-docs/releases/<id>.md`), holding every data step the release
|
|
36
36
|
needs and exporting
|
|
37
37
|
`({ controller }) => async ({ dryRun, organization, ...args }) => counts`.
|
package/package.json
CHANGED