@biffo/cli 0.109.1 → 0.109.3

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.
@@ -8,9 +8,9 @@ name: CI
8
8
 
9
9
  on:
10
10
  push:
11
- branches: [main]
11
+ branches: [dev]
12
12
  pull_request:
13
- branches: [main]
13
+ branches: [dev]
14
14
 
15
15
  concurrency:
16
16
  group: ${{ github.workflow }}-${{ github.ref }}
@@ -0,0 +1,73 @@
1
+ # Rules of Engagement for AI Agents
2
+
3
+ These rules are **binding for every automated coding agent** working in this
4
+ repository — Claude Code, Codex, Cursor, or any other. They are tool-agnostic:
5
+ express everything as plain `git` / `gh` / `pnpm` / `uv` commands. Tool-specific
6
+ guidance belongs in that tool's own file (e.g. `CLAUDE.md`), which imports this
7
+ one rather than restating it.
8
+
9
+ This is a **Biffo satellite repo** (a plugin or sibling app), separate from the
10
+ core project it extends. It follows the same engagement rules as every Biffo
11
+ repo; only its product differs.
12
+
13
+ ## 1. One integration branch: `dev`
14
+
15
+ - **`dev` is the integration branch** — you branch from it and open every PR back
16
+ into it; `gh repo view --json defaultBranchRef` confirms it. If it reports
17
+ anything other than `dev`, flag it rather than working around it. (A sibling app
18
+ also carries `staging` and a reserved `main`/production branch as promotion
19
+ targets — production not built yet; a plugin repo has `dev` only. Either way you
20
+ work off `dev`.)
21
+ - **All changes land via PR.** No direct commits to `dev`, no force-pushes to it.
22
+ Branch protection stays on.
23
+ - Never leave the primary checkout parked on a feature branch or let it fall
24
+ behind — keep it on `dev`, no more than a `git fetch` behind, and do the work
25
+ in worktrees (§2).
26
+
27
+ ## 2. Work in an isolated worktree
28
+
29
+ - **Always start from a freshly-fetched `dev`:** `git fetch origin`, then
30
+ `git worktree add .worktrees/<name> -b <type>/<slug> origin/dev`. Never branch
31
+ from a stale local ref.
32
+ - **Install dependencies in the new worktree before working** — `uv sync` and/or
33
+ `pnpm install`, so the local gates (pre-push checks, lint-staged) run against
34
+ fresh deps, not a stale `.venv`/`node_modules`.
35
+ - **One worktree per unit of work**, under the git-ignored `.worktrees/`.
36
+ - **Clean up when the PR merges:** `git worktree remove .worktrees/<name>`, then
37
+ let the branch be deleted. Keep `git worktree list` short and every entry live.
38
+
39
+ ## 3. Commits
40
+
41
+ - **Conventional Commits** (`feat`, `fix`, `chore`, `docs`, `test`, `infra`,
42
+ `security`, `refactor`, `perf`, `ci`), enforced by commitlint.
43
+ - Tag your commits with your agent's own `Co-Authored-By:` trailer.
44
+ - Keep commits and PRs **scoped to one concern**.
45
+
46
+ ## 4. Pull requests
47
+
48
+ - Link the issue the PR resolves (`Closes #N`) and describe what changed and why.
49
+ - Mark a PR **ready** (not draft) when it is meant to merge.
50
+ - Behavior changes ship **with tests**. Don't reduce coverage to make CI pass.
51
+
52
+ ## 5. Merging — never merge red
53
+
54
+ - Get CI green and confirm it: `gh pr checks <N>`. A green local run is not
55
+ sufficient — verify the actual PR checks.
56
+ - **Squash-merge, delete the branch, remove the worktree:**
57
+ `gh pr merge <N> --squash --delete-branch`.
58
+
59
+ ## 6. Push honestly, and verify the remote has your commit
60
+
61
+ - **Push with the exit status visible:** `git push origin HEAD; echo $?`. A pipe
62
+ (`git push | tail`) reports the pipe's status, not git's — a rejected push then
63
+ reads as success and the commit is silently lost. Never trust a "pushed"
64
+ message printed unconditionally after a pipe.
65
+ - **Confirm the remote actually has the commit before relying on it,** especially
66
+ before merge: `git log origin/<branch> -1`. A green PR page is not proof your
67
+ latest local commit reached it.
68
+
69
+ ## 7. Security
70
+
71
+ - **Never commit secrets** (keys, tokens, credentials, `.env` values).
72
+ - **Never silently disable a security gate.** If one must be loosened, do it in
73
+ the open and raise a tracking issue to restore it.
@@ -0,0 +1,15 @@
1
+ # AI Assistant Context
2
+
3
+ The tool-agnostic rules of engagement for **all** automated agents (integration
4
+ branch, worktrees, commits, PRs, merging, honest pushes, security) live in
5
+ [`AGENTS.md`](AGENTS.md) and are imported below. They are binding for any change
6
+ in this repo; `AGENTS.md` is the single source of truth.
7
+
8
+ @AGENTS.md
9
+
10
+ ## What this repo is
11
+
12
+ A **Biffo plugin** — code that extends a core Biffo project, distributed and
13
+ mounted by it. See the core project's ADR-0003 (plugin system) and ADR-0021
14
+ (shared plugin hosting) for how a plugin is installed and run. This repo carries
15
+ the plugin's own manifest (`biffo.plugin.json`), source, and tests.
@@ -12,9 +12,9 @@ name: CI
12
12
 
13
13
  on:
14
14
  push:
15
- branches: [main, dev, staging]
15
+ branches: [dev, staging, main]
16
16
  pull_request:
17
- branches: [main, dev, staging]
17
+ branches: [dev, staging, main]
18
18
  # Manual re-run, matching the core project's CI. Without this there is no way
19
19
  # to trigger CI on a protected branch without pushing to it — and a sibling
20
20
  # repo has the same branch protection, so the same recovery gap. See #293.
@@ -2,9 +2,9 @@ name: 'CodeQL'
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [main, dev, staging]
5
+ branches: [dev, staging, main]
6
6
  pull_request:
7
- branches: [main, dev, staging]
7
+ branches: [dev, staging, main]
8
8
  schedule:
9
9
  # Weekly catch-up scan (Tuesday 05:17 UTC) for issues that land outside
10
10
  # PR review (e.g. direct merges onto a branch).
@@ -0,0 +1,73 @@
1
+ # Rules of Engagement for AI Agents
2
+
3
+ These rules are **binding for every automated coding agent** working in this
4
+ repository — Claude Code, Codex, Cursor, or any other. They are tool-agnostic:
5
+ express everything as plain `git` / `gh` / `pnpm` / `uv` commands. Tool-specific
6
+ guidance belongs in that tool's own file (e.g. `CLAUDE.md`), which imports this
7
+ one rather than restating it.
8
+
9
+ This is a **Biffo satellite repo** (a plugin or sibling app), separate from the
10
+ core project it extends. It follows the same engagement rules as every Biffo
11
+ repo; only its product differs.
12
+
13
+ ## 1. One integration branch: `dev`
14
+
15
+ - **`dev` is the integration branch** — you branch from it and open every PR back
16
+ into it; `gh repo view --json defaultBranchRef` confirms it. If it reports
17
+ anything other than `dev`, flag it rather than working around it. (A sibling app
18
+ also carries `staging` and a reserved `main`/production branch as promotion
19
+ targets — production not built yet; a plugin repo has `dev` only. Either way you
20
+ work off `dev`.)
21
+ - **All changes land via PR.** No direct commits to `dev`, no force-pushes to it.
22
+ Branch protection stays on.
23
+ - Never leave the primary checkout parked on a feature branch or let it fall
24
+ behind — keep it on `dev`, no more than a `git fetch` behind, and do the work
25
+ in worktrees (§2).
26
+
27
+ ## 2. Work in an isolated worktree
28
+
29
+ - **Always start from a freshly-fetched `dev`:** `git fetch origin`, then
30
+ `git worktree add .worktrees/<name> -b <type>/<slug> origin/dev`. Never branch
31
+ from a stale local ref.
32
+ - **Install dependencies in the new worktree before working** — `uv sync` and/or
33
+ `pnpm install`, so the local gates (pre-push checks, lint-staged) run against
34
+ fresh deps, not a stale `.venv`/`node_modules`.
35
+ - **One worktree per unit of work**, under the git-ignored `.worktrees/`.
36
+ - **Clean up when the PR merges:** `git worktree remove .worktrees/<name>`, then
37
+ let the branch be deleted. Keep `git worktree list` short and every entry live.
38
+
39
+ ## 3. Commits
40
+
41
+ - **Conventional Commits** (`feat`, `fix`, `chore`, `docs`, `test`, `infra`,
42
+ `security`, `refactor`, `perf`, `ci`), enforced by commitlint.
43
+ - Tag your commits with your agent's own `Co-Authored-By:` trailer.
44
+ - Keep commits and PRs **scoped to one concern**.
45
+
46
+ ## 4. Pull requests
47
+
48
+ - Link the issue the PR resolves (`Closes #N`) and describe what changed and why.
49
+ - Mark a PR **ready** (not draft) when it is meant to merge.
50
+ - Behavior changes ship **with tests**. Don't reduce coverage to make CI pass.
51
+
52
+ ## 5. Merging — never merge red
53
+
54
+ - Get CI green and confirm it: `gh pr checks <N>`. A green local run is not
55
+ sufficient — verify the actual PR checks.
56
+ - **Squash-merge, delete the branch, remove the worktree:**
57
+ `gh pr merge <N> --squash --delete-branch`.
58
+
59
+ ## 6. Push honestly, and verify the remote has your commit
60
+
61
+ - **Push with the exit status visible:** `git push origin HEAD; echo $?`. A pipe
62
+ (`git push | tail`) reports the pipe's status, not git's — a rejected push then
63
+ reads as success and the commit is silently lost. Never trust a "pushed"
64
+ message printed unconditionally after a pipe.
65
+ - **Confirm the remote actually has the commit before relying on it,** especially
66
+ before merge: `git log origin/<branch> -1`. A green PR page is not proof your
67
+ latest local commit reached it.
68
+
69
+ ## 7. Security
70
+
71
+ - **Never commit secrets** (keys, tokens, credentials, `.env` values).
72
+ - **Never silently disable a security gate.** If one must be loosened, do it in
73
+ the open and raise a tracking issue to restore it.
@@ -0,0 +1,16 @@
1
+ # AI Assistant Context
2
+
3
+ The tool-agnostic rules of engagement for **all** automated agents (integration
4
+ branch, worktrees, commits, PRs, merging, honest pushes, security) live in
5
+ [`AGENTS.md`](AGENTS.md) and are imported below. They are binding for any change
6
+ in this repo; `AGENTS.md` is the single source of truth.
7
+
8
+ @AGENTS.md
9
+
10
+ ## What this repo is
11
+
12
+ A **Biffo sibling app** (ADR-0007) — an independently-deployed microservice that
13
+ shares the core project's login and domain (`baseurl.com/<name>`) but has its own
14
+ repo, CI/CD, and AWS resources. It never touches the core database directly — it
15
+ only ever calls the core project's own API. Its own identity lives in
16
+ `biffo.sibling.json`.
package/dist/index.js CHANGED
@@ -515,10 +515,11 @@ var GitAdapter = class {
515
515
  *
516
516
  * Sets the initial branch name explicitly (`-b`) rather than relying on
517
517
  * the running machine's `init.defaultBranch` git config, which isn't
518
- * guaranteed to be "main" (or even consistent between a dev's laptop and
519
- * a CI runner).
518
+ * guaranteed to be "dev" (or even consistent between a dev's laptop and
519
+ * a CI runner). Defaults to `dev`, the single integration branch every Biffo
520
+ * repo uses (#559).
520
521
  */
521
- async init(cwd, initialBranch = "main") {
522
+ async init(cwd, initialBranch = "dev") {
522
523
  await execa("git", ["init", "-b", initialBranch], { cwd });
523
524
  }
524
525
  /** Adds a remote. Fails if a remote with this name already exists. */
@@ -531,7 +532,7 @@ var GitAdapter = class {
531
532
  async commit(cwd, message) {
532
533
  await execa("git", ["commit", "-m", message], { cwd });
533
534
  }
534
- /** The current branch name (e.g. "main"). */
535
+ /** The current branch name (e.g. "dev"). */
535
536
  async currentBranch(cwd) {
536
537
  const { stdout } = await execa("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
537
538
  return stdout.trim();
@@ -644,7 +645,7 @@ var GitHubAdapter = class {
644
645
  * The repo's default branch — the integration branch a PR should target.
645
646
  *
646
647
  * Asked of GitHub rather than inferred from the local checkout: it differs per
647
- * repo (biffo-template uses `main`, instances use `dev`), and the local
648
+ * repo (every Biffo repo uses `dev` (#559)), and the local
648
649
  * current branch is whatever the caller happens to be on, which under the
649
650
  * worktree-per-change workflow is never it.
650
651
  */
@@ -840,7 +841,7 @@ var GitHubAdapter = class {
840
841
  `Ref "${ref}" not found in ${org}/${repo} after ${timeoutMs / 1e3}s \u2014 GitHub template generation may have stalled. Check the repository and re-run biffo init.`
841
842
  );
842
843
  }
843
- async createBranch(org, repo, branch, from = "main", waitTimeoutMs = 12e4, waitIntervalMs = 3e3) {
844
+ async createBranch(org, repo, branch, from = "dev", waitTimeoutMs = 12e4, waitIntervalMs = 3e3) {
844
845
  try {
845
846
  await this.octokit.repos.getBranch({ owner: org, repo, branch });
846
847
  log.info(`Branch ${branch} already exists \u2014 skipping`);
@@ -1269,7 +1270,7 @@ var GitHubAdapter = class {
1269
1270
  }
1270
1271
  }
1271
1272
  }
1272
- async triggerWorkflow(org, repo, workflowId, inputs = {}, ref = "main", timeoutMs = 6e4, intervalMs = 5e3) {
1273
+ async triggerWorkflow(org, repo, workflowId, inputs = {}, ref = "dev", timeoutMs = 6e4, intervalMs = 5e3) {
1273
1274
  const deadline = Date.now() + timeoutMs;
1274
1275
  while (true) {
1275
1276
  try {
@@ -1288,7 +1289,7 @@ var GitHubAdapter = class {
1288
1289
  }
1289
1290
  }
1290
1291
  }
1291
- async waitForWorkflowRun(org, repo, workflowId, baselineRunId, timeoutMs = 36e5, intervalMs = 3e4, branch = "main") {
1292
+ async waitForWorkflowRun(org, repo, workflowId, baselineRunId, timeoutMs = 36e5, intervalMs = 3e4, branch = "dev") {
1292
1293
  const deadline = Date.now() + timeoutMs;
1293
1294
  while (Date.now() < deadline) {
1294
1295
  const { data } = await this.octokit.actions.listWorkflowRuns({
@@ -1977,7 +1978,7 @@ function breakingChangesBetween(from, to, entries) {
1977
1978
  }
1978
1979
 
1979
1980
  // src/lib/global-workflows.ts
1980
- var GLOBAL_DISPATCH_REF = "main";
1981
+ var GLOBAL_DISPATCH_REF = "dev";
1981
1982
  var GLOBAL_DISPATCH_WORKFLOW_PATHS = [
1982
1983
  ".github/workflows/deploy-global.yml"
1983
1984
  ];
@@ -5300,11 +5301,11 @@ async function pushSkeleton(git, skeletonRoot, cloneUrl, config, coreConfig, git
5300
5301
  // `template_version` field doc on `SiblingMarker` (lib/sibling-teardown.ts).
5301
5302
  templateVersion: getLatestCoreVersion()
5302
5303
  });
5303
- await git.init(workDir, "main");
5304
+ await git.init(workDir, "dev");
5304
5305
  await git.addRemote(workDir, "origin", cloneUrl);
5305
5306
  await git.add(workDir, ["."]);
5306
5307
  await git.commit(workDir, `feat: scaffold ${config.project.name} sibling app (ADR-0007)`);
5307
- await git.push(workDir, "main", { token: githubToken });
5308
+ await git.push(workDir, "dev", { token: githubToken });
5308
5309
  } finally {
5309
5310
  git.cleanup(workDir);
5310
5311
  }
@@ -5345,8 +5346,8 @@ function writeSiblingTemplate(templateRoot, targetDir, config, context) {
5345
5346
  }
5346
5347
  async function configureSiblingGithub(github, config, coreConfig, session, coreIdentity) {
5347
5348
  const { org, repo } = githubRepo(config);
5348
- await github.createBranch(org, repo, "dev", "main");
5349
- await github.createBranch(org, repo, "staging", "main");
5349
+ await github.createBranch(org, repo, "staging", "dev");
5350
+ await github.createBranch(org, repo, "main", "dev");
5350
5351
  await github.setDefaultBranch(org, repo, "dev");
5351
5352
  await github.configureBranchProtection(config);
5352
5353
  await github.createEnvironments(config);
@@ -5694,9 +5695,9 @@ async function runInit(github, aws, config, session, appSibling) {
5694
5695
  }
5695
5696
  const { org, repo } = config.source_control.config;
5696
5697
  if (!hasCompleted(session, "github_branches")) {
5697
- log.step(5, totalSteps, "Creating dev and staging branches...");
5698
- await github.createBranch(org, repo, "dev", "main");
5699
- await github.createBranch(org, repo, "staging", "main");
5698
+ log.step(5, totalSteps, "Creating the staging and main branches...");
5699
+ await github.createBranch(org, repo, "staging", "dev");
5700
+ await github.createBranch(org, repo, "main", "dev");
5700
5701
  markStepComplete(session, "github_branches");
5701
5702
  } else {
5702
5703
  log.step(5, totalSteps, "Branches already created \u2014 skipping");
@@ -5833,8 +5834,8 @@ function appSiblingRegistryFiles(config) {
5833
5834
  }));
5834
5835
  }
5835
5836
  var INSTANCE_CONFIG_FILE = "biffo.config.json";
5836
- var INSTANCE_FILE_BASE_BRANCH = "main";
5837
- var INSTANCE_FILE_FOLLOWER_BRANCHES = ["dev", "staging"];
5837
+ var INSTANCE_FILE_BASE_BRANCH = "dev";
5838
+ var INSTANCE_FILE_FOLLOWER_BRANCHES = ["staging", "main"];
5838
5839
  var INSTANCE_FILE_BRANCHES = [
5839
5840
  INSTANCE_FILE_BASE_BRANCH,
5840
5841
  ...INSTANCE_FILE_FOLLOWER_BRANCHES
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.109.1",
3
+ "version": "0.109.3",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",