@drawbridge/drawbridge-agents 0.1.90 → 0.1.92
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,9 +5,9 @@ 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 `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.
|
|
8
|
+
One Asana release task is the unit. Its id names everything: the `feature/<id>` branch in every app the release touches, the `release/<id>` branch the developer cuts from develop once it is approved, `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
|
-
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.
|
|
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, the cut in 8, and 9. A QA person owns 7 and the approval in 8. The skill never does a developer's or a tester's line for them.
|
|
11
11
|
|
|
12
12
|
1. A person gives the skill the release task link. The skill runs the doctor, then asks two things before reading anything: who reviews and who tests.
|
|
13
13
|
2. The skill reads the task and subtasks, writes the stories, sends ONE numbered list and waits for the yes. The yes starts an unattended run.
|
|
@@ -16,8 +16,8 @@ The ten lines below are the release, as Darren confirmed them on 2026-10-22. The
|
|
|
16
16
|
5. One end list: the parked questions, the access requests, the publish ask, the pull requests that are ready. The person answers, the skill closes out the rest, task → Review.
|
|
17
17
|
6. The developer reviews, runs the branch locally, reviews whenever ready and merges only when develop is free; runs any migration on dev; moves the task → QA and assigns the QA person.
|
|
18
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.
|
|
19
|
+
8. The QA person moves the task → Approved. The developer cuts `release/<id>` from the tested develop commit and empties the band on develop, which frees develop for the next release.
|
|
20
|
+
9. The developer promotes `release/<id>` by hand ("Finish release", then the deploys), with the skill as checklist.
|
|
21
21
|
10. The skill writes "What's new", completes the subtasks, moves the task → Released, cleans up.
|
|
22
22
|
|
|
23
23
|
## Line 1: start
|
|
@@ -41,9 +41,9 @@ Wait for both answers. Never guess either name. The developer still assigns the
|
|
|
41
41
|
|
|
42
42
|
- every unknown from every story, **each with the fix you recommend**: "I recommend <the option>, because <the reason>." The recommendation comes from having read the code the subtask touches (the files the graph named, opened whole) and from what apps like Drawbridge commonly do for the same thing, and it picks the best experience for the person using the product. That goes for every aspect of the platform, not only screens: a feature, a price or plan rule, a design, a message, a default, a limit. A question without a recommendation reads as a question nobody has thought about (Darren, 2026-10-22: "recommend the fix as well. This way I know you've reviewed the code and considered the best approach. We should always be looking at what is the best user experience as well as what is common for apps like ours"). When the recommendation needs a fact you do not have, say which, and still name the option you would take;
|
|
43
43
|
- nothing about who reviews or tests: both were answered at line 1;
|
|
44
|
-
- **a package publish, if any subtask names `@drawbridge/components` or `@drawbridge/drawbridge-utils`**, as a statement, not a question: this release publishes a package; the developer named above publishes it. The package is built first and gets its own pull request to the package's `main`; the end list (line 5) hands the developer the merge and the
|
|
44
|
+
- **a package publish, if any subtask names `@drawbridge/components` or `@drawbridge/drawbridge-utils`**, as a statement, not a question: this release publishes a package; the developer named above publishes it. The package is built first and gets its own pull request to the package's `main`; the end list (line 5) hands the developer the merge and the tag to push; the skill then bumps the pin in every consumer, and the app pull requests open after that, once the publish is done. Line 4 step 2 is the exact sequence.
|
|
45
45
|
|
|
46
|
-
**Publishing is settled; never ask about it.** The developer publishes every package
|
|
46
|
+
**Publishing is settled; never ask about it.** The developer publishes every package by merging its version bump to `main` and pushing the tag `v<version>` (`git checkout main && git pull && git tag v<version> && git push origin v<version>`); GitHub Actions (`.github/workflows/publish.yml`, since Butterscotch 2026-10-23, task 1218041740718540) builds, runs the tests and publishes through npm trusted publishing, so no npm token exists anywhere and the registry shows the publisher as "GitHub Actions" (proven with stripe 0.1.56). The workflow refuses a tag that differs from `package.json` or is not on `main`. The hand path, `git pull && npm run build` on `main` with the developer's one-time password, still works as a fallback. Agents hold no npm token and never will. So the skill never asks who publishes, whether to publish, whether it may publish, or how: it writes the one command into the end list as an instruction to the developer and waits for `npm view` to show the version (Darren, 2026-10-22: "I get a lot of questions in the release about npm publishing etc, lets make sure that it's clear that the developers do the publishing so that these go away").
|
|
47
47
|
|
|
48
48
|
Wait for the yes. Nothing below runs before it. From the yes to the end list, the run is unattended: the next section says what that means.
|
|
49
49
|
|
|
@@ -60,10 +60,10 @@ A run does not stop while there is code left to write. Whatever the hour, the ag
|
|
|
60
60
|
|
|
61
61
|
## Line 3: Building
|
|
62
62
|
|
|
63
|
-
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. Pull requests never wait on another release: they open when the work is finished, and the developer reviews them whenever they like, on the feature branch locally. **Develop holds one release at a time.** The merge is what waits: a reviewed release sits in Review until the release before it is
|
|
64
|
-
2. `feature/<id>` in every repo a subtask touches, off `develop` (components and utils off `main`): a git-flow FEATURE branch, never `release/<id
|
|
63
|
+
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. Pull requests never wait on another release: they open when the work is finished, and the developer reviews them whenever they like, on the feature branch locally. **Develop holds one release at a time.** The merge is what waits: a reviewed release sits in Review until the release before it is cut (line 8: approved, `release/<id>` made), then merges, gets its dev migration, and moves to QA. It does not wait for the production promote, which runs from the cut branch (Darren, 2026-10-23: a cut release "frees dev up for the next feature"). The Review slot may queue several reviewed releases; that is fine (Darren, 2026-10-23: "There will only ever be one on develop at once. The Review slot may queue up once the devs have reviewed a release but that's fine"; "Develop can only go one at a time"). This step never blocks on it; the merge does. Then move this task to Building (`POST /sections/1219601033297172/addTask { task }`).
|
|
64
|
+
2. `feature/<id>` in every repo a subtask touches, off `develop` (components and utils off `main`): a git-flow FEATURE branch, never `release/<id>`: the repos carry git-flow config, and a client's "Finish release" merges into `main` with a tag, so a release branch made at build time would put unapproved code on main; "Finish feature" merges into `develop`, which is what the build needs (Darren, 2026-10-22). `release/<id>` exists only from the cut at line 8, when the code is approved. Almond's build branches carried the `release/1219601137920078` name and were moved forward to its tested develop commit at its cut. 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). **The stories do not wait on that branch.** They are committed and pushed to docs `main` here, before any code, straight from the main docs checkout (`git -C ../drawbridge-docs push origin main`): a story is the spec, text only, nothing deploys from docs, and the feature pipeline writes the story before the first edit anyway. That is what makes the story links in step 5 work the moment they are added (Darren, 2026-10-22: "Story links will need to be added after the docs repo has been pushed on main so the links work"). The docs `feature/<id>` branch then carries only what rides with the code: `releases/<id>.md`, reference pages, a story edited again during the build. "Repo a subtask touches" includes docs, components and utils, not only the six apps.
|
|
65
65
|
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.
|
|
66
|
-
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.
|
|
66
|
+
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. The previous release's cut empties `release.json` on develop (line 8), so when this pull request merges after that, GitHub shows a conflict on `release.json` (changed on both sides): keep the branch's file.
|
|
67
67
|
5. **Every subtask links its story.** Append to each subtask's description, under its own text, one line per story: "Story: <story id>, <GitHub link>", the link being the story file in the docs repo on GitHub, `https://github.com/trydrawbridge/drawbridge-docs/blob/main/user-stories/<domain folder>/<file>.md` (`PUT /tasks/<subtask> { notes }`; the original description stays above, untouched). Never paste the story into the task: the file in drawbridge-docs is the one copy, and the link is read on GitHub (Darren, 2026-10-22: "link to the GitHub repo for each story in the subtask so it can be read in GitHub in the docs repo"; "Don't rewrite them in the task, just link to them"). The stories were pushed to docs `main` in step 2, so every link resolves the moment it is added; check each with `gh api repos/trydrawbridge/drawbridge-docs/contents/user-stories/<folder>/<file>.md` before writing it. The QA person cross-references the story against the feature before the final test.
|
|
68
68
|
6. 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.
|
|
69
69
|
7. **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).
|
|
@@ -76,7 +76,7 @@ All work on the release branches against the **Local** database. Develop and its
|
|
|
76
76
|
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 package is finished and its pull request ready when the end list goes out, and the build never pauses for it (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):
|
|
77
77
|
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.
|
|
78
78
|
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. Nothing is posted to Asana yet; the link goes into the end list.
|
|
79
|
-
3. Write the publish instruction into the Parked section, addressed to the developer from line
|
|
79
|
+
3. Write the publish instruction into the Parked section, addressed to the developer from line 1, as one numbered item with the exact words: merge that pull request, then from the package checkout: `git checkout main && git pull && git tag v<version> && git push origin v<version>`; the Publish workflow does the rest, and `npm view <package> version` shows it within a few minutes (by hand if the workflow fails: `npm run build` on `main`). It is an instruction, not a question, and it goes out at line 5, never now. No question about publishing is ever put to anyone (line 2).
|
|
80
80
|
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.
|
|
81
81
|
5. When `npm view <package> version` shows the new version (after the person has published from the end list): 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.
|
|
82
82
|
6. No app pull request opens while a pin still names a version the registry does not have.
|
|
@@ -95,7 +95,7 @@ Only when every subtask that can be built has been built: each committed, `npm t
|
|
|
95
95
|
**First, the end list.** ONE numbered list to the person who started the release, the first words anyone has heard since the yes (Darren, 2026-10-22: "ask finalizing questions / request access to complete then"). In this order: every parked question, every access request with what it unblocks, the publish ask when there is a package, the subtasks not built and why, and the repos whose pull requests are ready to open. Each item three plain sentences (rule 7). Then, in the same message, open the pull requests that depend on nothing parked (steps 1 to 3 below) and stop. When the answers and grants arrive, finish the parked steps on the release branches, bump the pins once the registry has the version, run the tests and the QA agent on what changed, open the remaining pull requests, and only then move the task to Review. This close-out is the end of the coding segment of a release; nothing in it is asked for a second time.
|
|
96
96
|
|
|
97
97
|
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`.
|
|
98
|
-
2. Every pull request body ends with the lane rule in one line: "Review any time, on the feature branch locally. Merge only when develop is free: one release on develop at a time, so this merges once the release before it is
|
|
98
|
+
2. Every pull request body ends with the lane rule in one line: "Review any time, on the feature branch locally. Merge only when develop is free: one release on develop at a time, so this merges once the release before it is approved and cut to its release/ branch." Fill the Branches table in `releases/<id>.md` with the PR links; commit.
|
|
99
99
|
3. **How to test, on every subtask, for both readers.** Append to each subtask's description, under its Story lines, two headings (Darren, 2026-10-22: "steps for a developer to test via code, or locally, and a QA person's steps"). First, "Test locally (developer)": one numbered list with the branch to check out, the exact commands (`npm test` in the repo, the test file that proves the change, `npm run migrate -- <id> --dry --env local` when there is a migration, `npm run walk -- --local <path>` for a screen), and for a screen: "Open an organization with the following features: <what this subtask needs, e.g. a connected Shopify store, a giveaway with a published prize>" on `http://localhost:3000`, then the path inside it by screen name, and the result each command must print or show. Never a fixed organization id. Then, "Test on dev (QA)": one numbered list with the dev app to open first (dashboard `https://dev.dashboard.trydrawbridge.com/organizations`, then "Open an organization with the following features: <what this subtask needs>" and the screens by name from there, never a fixed organization id, a share page `https://<slug>.dev.drwbrdg.com/...`, the website `https://dev.trydrawbridge.com/...`, the components app `https://components.trydrawbridge.com/...`), then one action per step, then what the tester must see. Every label in it is quoted from the Local walk and the QA reports of line 4, never from memory (`conventions/walk-the-app.md`), with dev URLs in place of localhost. A migration subtask says what the tester checks after the developer's dev run. The words go through `humanizer`. Both lists are written here, after the build, because only then are the commands and labels known (Darren, 2026-10-22: "include steps on how to test in the respective development apps"). The pull request body and the release doc's QA table point at the subtasks for these steps rather than repeating them.
|
|
100
100
|
4. 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`): this is the first Asana comment of the release, and the package pull request's link rides in it too. Assign the task to the developer and move it to Review (`POST /sections/1219762451512990/addTask`) only once every pull request is open, parked items included.
|
|
101
101
|
5. Stop. Report the PR links.
|
|
@@ -104,30 +104,45 @@ Only when every subtask that can be built has been built: each committed, `npm t
|
|
|
104
104
|
|
|
105
105
|
The skill does none of this. For the record, so the skill can answer "what is the next step":
|
|
106
106
|
|
|
107
|
-
- Line 6, the developer: reviews the diff, runs the branch locally, approves and merges, but merges only when develop is free. Develop holds one release at a time: the review happens whenever the developer likes, on the feature branch locally, and the approved release waits in Review until the one before it is
|
|
107
|
+
- Line 6, the developer: reviews the diff, runs the branch locally, approves and merges, but merges only when develop is free. Develop holds one release at a time: the review happens whenever the developer likes, on the feature branch locally, and the approved release waits in Review until the one before it is cut at line 8 (Darren, 2026-10-23: "Develop can only go one at a time"; "The Review slot may queue up once the devs have reviewed a release but that's fine"). Merging means the developer has QA'd the branch locally and it is ready (Darren, 2026-10-23). Then the merge, the dev migration, the move to QA and the QA assignment, in that order. 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.
|
|
108
108
|
- Line 7, the QA person: tests on dev. The band already names the release.
|
|
109
|
-
- Line 8, the QA person: moves the task to Approved.
|
|
109
|
+
- Line 8, the QA person: moves the task to Approved. Then the developer cuts the release, below.
|
|
110
|
+
|
|
111
|
+
## Line 8: the cut, as the developer's checklist
|
|
112
|
+
|
|
113
|
+
The cut stages the approved release for production and frees develop for the next one (Darren, 2026-10-23). The developer does it; the skill hands over the steps and verifies by reading.
|
|
114
|
+
|
|
115
|
+
1. Confirm the task sits in Approved; refuse otherwise.
|
|
116
|
+
2. Find the commit QA tested, per app in the Branches table (the apps, not components or utils, which ship from their own `main` when published): the develop commit dev is running. The api reports it at `https://dev.api.trydrawbridge.com/health` (`commit`); the other apps' active dev deployment shows it in DigitalOcean (`apps-get-deployment-status`). If develop has moved past it, cut from that commit, never the tip.
|
|
117
|
+
3. Per app: the client's "Start release" named `<id>` from that commit, then publish the branch. Plain git: `git push origin <commit>:refs/heads/release/<id>`. Verify with `git ls-remote origin release/<id>`.
|
|
118
|
+
4. Take the band off develop, in the api: write `{}` into `release.json`, commit it on develop as "release <id>: cut, band off develop", and push. Never delete the file: the Dockerfile copies it by name, and deleting it failed the dev build at Almond's cut (`fa2a0dc4`). `lib/release.js` sends no band for `{}`. Dev shows none until the next release merges and brings its own (line 3 step 4).
|
|
119
|
+
5. Record the cut commits in the release doc's Cut section. Develop is free: the next release in Review may merge (line 6).
|
|
120
|
+
|
|
121
|
+
**A bug found after the cut.** Dev now runs the next release, so a fix to the cut release cannot be tested on dev.
|
|
122
|
+
|
|
123
|
+
- In the cut release, not yet in production: the fix goes on `release/<id>`, a developer tests it locally, and "Finish release" at line 9 carries it to `main` and develop. A bug that can wait is fixed in the next release.
|
|
124
|
+
- Already in production: the client's "Start hotfix" from `main`; "Finish hotfix" merges it into `main` and develop, then the developer deploys by hand (Darren, 2026-10-23: "the fix needs to be done via a hotfix so that [git-flow] merges to all the places it should").
|
|
110
125
|
|
|
111
126
|
## Line 9: promote, as the developer's checklist
|
|
112
127
|
|
|
113
128
|
**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.
|
|
114
129
|
|
|
115
|
-
1. Confirm the task sits in Approved; refuse otherwise.
|
|
130
|
+
1. Confirm the task sits in Approved and `release/<id>` exists in every app in the Branches table (line 8); refuse otherwise.
|
|
116
131
|
2. Hand over the preparation: the window (avoid 00:00 and 02:00 UTC, sync's scheduled jobs) and the Atlas snapshot. Wait.
|
|
117
|
-
3. Per app, in this order unless the release doc says otherwise (dashboard, api, sync, share, webhooks, website): hand over the
|
|
118
|
-
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, from the api component's Console in the DigitalOcean dashboard.) Then `git rm drawbridge-api/scripts/migration-<id>.js`, committed on develop
|
|
132
|
+
3. Per app with a `release/<id>` branch, in this order unless the release doc says otherwise (dashboard, api, sync, share, webhooks, website): hand over the client's "Finish release" with the tag `<id>`, which merges `release/<id>` into `main` and into develop and tags it, then the push of `main`, develop and the tag, then the Deploy click in DigitalOcean (prod apps deploy from `main` with deploy-on-push off). Plain git for the finish: `git checkout main && git pull && git merge --no-ff release/<id>`, `git tag <id>`, `git checkout develop && git pull && git merge --no-ff release/<id>`, `git push origin main develop <id>`. The merge into develop keeps develop's band: develop emptied or replaced `release.json` after the cut and the release branch did not touch it. An app with no `release/<id>` is not promoted. Verify by reading: the deployment ACTIVE through the DigitalOcean MCP server registered in Claude Code (`apps-get-deployment-status`; the release doctor checks it is there, and no machine needs doctl), `/health` reporting `main`'s new commit (the merge commit, whose code is the cut commit plus any fix made on the release branch). Note the commit in the release doc's Promote section.
|
|
133
|
+
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, from the api component's Console in the DigitalOcean dashboard.) Then `git rm drawbridge-api/scripts/migration-<id>.js`, committed on develop. `main` takes the removal with the next release's finish; never push develop to `main`, which would ship the next release unapproved.
|
|
119
134
|
5. Hand over the verification list from the release doc's Promote section; the developer reports what they saw; the skill fills it in.
|
|
120
135
|
|
|
121
136
|
## Line 10: Released
|
|
122
137
|
|
|
123
138
|
1. **What's new.** Create the "Marketing: What's new" subtask on the release task now (`POST /tasks/<id>/subtasks`), with the marketing breakdown as its description, in the customer's words, one item per subtask a merchant would notice (`drawbridge-asana-comment` for the shape, `humanizer` for the words), and complete it in the same step (`PUT /tasks/<subtask> { completed : true }`). It exists only finished; a release never carries an open marketing subtask.
|
|
124
139
|
2. Complete every subtask (Application → Complete). Move the release task to Released (`POST /sections/1219601137919036/addTask`).
|
|
125
|
-
3. Remove the worktrees; refresh the knowledge graph and commit it in drawbridge-docs (`drawbridge-ship-feature` step 5), so the next release starts from what this one learned instead of searching for it. Report the promoted commits.
|
|
140
|
+
3. Remove the worktrees and the `release/<id>` branches the finish left (`git push origin --delete release/<id>`, a developer's push); refresh the knowledge graph and commit it in drawbridge-docs (`drawbridge-ship-feature` step 5), so the next release starts from what this one learned instead of searching for it. Report the promoted commits.
|
|
126
141
|
|
|
127
142
|
## What the skill never does
|
|
128
143
|
|
|
129
|
-
- Push `main`, deploy production, write to the production database, 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. On dev the skill writes nothing of its own either (the refresh only READS dev to copy it into Local); the dev migration runs on a developer's explicit instruction, by the developer or by an agent they ask.
|
|
130
|
-
- Ask anything about npm publishing: who, whether, how, or for permission. The developer publishes, always; the skill hands them the one command in the end list and waits for the registry.
|
|
144
|
+
- Push `main`, cut or finish a `release/` branch, deploy production, write to the production database, 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. On dev the skill writes nothing of its own either (the refresh only READS dev to copy it into Local); the dev migration runs on a developer's explicit instruction, by the developer or by an agent they ask.
|
|
145
|
+
- Ask anything about npm publishing: who, whether, how, or for permission. The developer publishes, always, by pushing the version tag; the skill hands them the one command in the end list and waits for the registry.
|
|
131
146
|
- Name a reviewer, a tester or a release scope that nobody told it; the people are asked at line 1, the scope at line 2. The window is the developer's at line 9; the skill asks for it never.
|
|
132
147
|
- Name an organization in a test list. A developer or a tester opens one that has the features the list names; nobody can guess which they will use.
|
|
133
148
|
- Write a release document, branch or migration under any name but the Asana id.
|
|
@@ -2,8 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Conventions for working on the `@drawbridge/*` npm packages
|
|
4
4
|
(`drawbridge-utils`, `drawbridge-components`, `drawbridge-mongodb`,
|
|
5
|
-
`drawbridge-redis`, `drawbridge-stripe`, `drawbridge-
|
|
6
|
-
|
|
5
|
+
`drawbridge-redis`, `drawbridge-stripe`, `drawbridge-telemetry`, `drawbridge-agents`)
|
|
6
|
+
and the apps that consume them. `drawbridge-shopify` is retired: the repo was archived
|
|
7
|
+
on GitHub and `@drawbridge/shopify` deprecated on npm (2026-09-13, "use
|
|
8
|
+
@drawbridge/drawbridge-utils/shopify/*"); never pin it.
|
|
9
|
+
|
|
10
|
+
## Publishing
|
|
11
|
+
|
|
12
|
+
**A publish is a tag push (since 2026-10-23).** Merge the version bump to `main`, then from
|
|
13
|
+
the package checkout `git checkout main && git pull && git tag v<version> && git push origin
|
|
14
|
+
v<version>`. Every package's `.github/workflows/publish.yml` runs on `v*` tags: it refuses a
|
|
15
|
+
tag that differs from `package.json` or is not on `main`, runs `npm ci`, `npx tsup` and
|
|
16
|
+
`node --test`, then `npm publish --ignore-scripts` through npm trusted publishing (OIDC,
|
|
17
|
+
`id-token: write`, npm 11). No npm token is stored anywhere; the registry records the
|
|
18
|
+
publisher as "GitHub Actions" (first proven with stripe 0.1.56, run 39975659406). The
|
|
19
|
+
trusted publisher for each package is configured on npmjs.com by Darren. A developer pushes
|
|
20
|
+
the tag; an agent never does.
|
|
21
|
+
|
|
22
|
+
The hand path below still works as a fallback when the workflow fails.
|
|
7
23
|
|
|
8
24
|
## Build + publish script
|
|
9
25
|
|
|
@@ -5,10 +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
|
|
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 while it is built, 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 build needs. |
|
|
9
9
|
| `bugfix/<name>` | Non-urgent bug fixes |
|
|
10
|
-
| `hotfix/<name>` | Urgent production fixes (branched from `main`) |
|
|
11
|
-
| `release/<
|
|
10
|
+
| `hotfix/<name>` | Urgent production fixes (branched from `main`); "Finish hotfix" merges into `main` and `develop` |
|
|
11
|
+
| `release/<asana id>` | A release once it is approved (since 2026-10-23): the developer cuts it from the develop commit QA tested on dev, which frees `develop` for the next release; a fix that must ship with it goes on this branch, tested locally. At promote, "Finish release" merges it into `main` and `develop` with the tag `<asana id>`, and the developer deploys by hand. One per app the release touches; never made at build time. Almond's build branches already carried this name and were moved forward at its cut |
|
|
12
12
|
| `chore/<name>` | Maintenance — dependency bumps, config, cleanup |
|
|
13
13
|
| `support/<name>` | Long-lived support branches |
|
|
14
14
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
const fs = require('fs')
|
|
15
15
|
const path = require('path')
|
|
16
16
|
const { spawnSync } = require('child_process')
|
|
17
|
-
const { markerPath } = require('./consult-docs-record.js')
|
|
17
|
+
const { isDocsPath, markerPath } = require('./consult-docs-record.js')
|
|
18
18
|
|
|
19
19
|
const SOURCE_EXTENSIONS = new Set([ '.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs' ])
|
|
20
20
|
|
|
@@ -66,7 +66,7 @@ const run = () => {
|
|
|
66
66
|
const segments = resolved.split('/')
|
|
67
67
|
|
|
68
68
|
if (!SOURCE_EXTENSIONS.has(path.extname(resolved).toLowerCase())) process.exit(0)
|
|
69
|
-
if (segments
|
|
69
|
+
if (isDocsPath(segments)) process.exit(0)
|
|
70
70
|
if (segments.includes('.claude')) process.exit(0)
|
|
71
71
|
if (/\/drawbridge-growth[^/]*\//.test(resolved + '/')) process.exit(0)
|
|
72
72
|
|
|
@@ -30,11 +30,15 @@ const readMarker = (file) => {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// drawbridge-docs itself or a worktree of it (.worktrees/drawbridge-docs-<name>),
|
|
34
|
+
// which is where release and feature work reads and writes the docs.
|
|
35
|
+
const isDocsPath = (segments) => segments.some((segment) => segment === 'drawbridge-docs' || segment.startsWith('drawbridge-docs-'))
|
|
36
|
+
|
|
33
37
|
const isDocsRead = (tool, toolInput) => {
|
|
34
38
|
if (tool !== 'Read') return false
|
|
35
39
|
const filePath = String(toolInput.file_path || '')
|
|
36
40
|
const resolved = path.resolve(filePath).split(path.sep).join('/')
|
|
37
|
-
return resolved.split('/')
|
|
41
|
+
return isDocsPath(resolved.split('/')) && /\.md$/i.test(resolved)
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
// A source edit outside .claude and drawbridge-docs: what qa-gate.js keys on to
|
|
@@ -48,7 +52,7 @@ const isSourceEdit = (tool, toolInput) => {
|
|
|
48
52
|
const resolved = path.resolve(filePath).split(path.sep).join('/')
|
|
49
53
|
const segments = resolved.split('/')
|
|
50
54
|
if (!SOURCE_EXTENSIONS.has(path.extname(resolved).toLowerCase())) return false
|
|
51
|
-
if (segments.includes('.claude') || segments
|
|
55
|
+
if (segments.includes('.claude') || isDocsPath(segments)) return false
|
|
52
56
|
return true
|
|
53
57
|
}
|
|
54
58
|
|
|
@@ -81,7 +85,7 @@ const run = () => {
|
|
|
81
85
|
process.exit(0)
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
module.exports = { markerPath }
|
|
88
|
+
module.exports = { isDocsPath, markerPath }
|
|
85
89
|
|
|
86
90
|
// consult-docs-gate.js requires this file for markerPath; only the hook
|
|
87
91
|
// invocation itself may read stdin and exit.
|
package/package.json
CHANGED