Skip to content

Commit e108d4d

Browse files
committed
feat(release): automate npm publishing and release workflow
1 parent 81bce84 commit e108d4d

10 files changed

Lines changed: 1173 additions & 241 deletions

File tree

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Bun
18+
uses: oven-sh/setup-bun@v2
19+
with:
20+
bun-version: latest
21+
22+
- name: Install dependencies
23+
run: bun install --frozen-lockfile
24+
25+
- name: Build
26+
run: bun run build
27+
28+
- name: Test
29+
run: bun test
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Conventional Commits
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
- edited
8+
- reopened
9+
- synchronize
10+
push:
11+
branches:
12+
- main
13+
14+
jobs:
15+
conventional-commits:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Validate pull request title
20+
if: github.event_name == 'pull_request'
21+
env:
22+
PR_TITLE: ${{ github.event.pull_request.title }}
23+
run: |
24+
if [[ ! "$PR_TITLE" =~ ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9._/-]+\))?(!)?:\ .+ ]]; then
25+
echo "Pull request title must follow Conventional Commits format."
26+
echo "Example: feat(worktree): add integration branch cleanup"
27+
echo "Current title: $PR_TITLE"
28+
exit 1
29+
fi
30+
31+
- name: Checkout
32+
if: github.event_name == 'push'
33+
uses: actions/checkout@v4
34+
with:
35+
fetch-depth: 0
36+
37+
- name: Validate commit subjects on main
38+
if: github.event_name == 'push'
39+
env:
40+
BEFORE_SHA: ${{ github.event.before }}
41+
AFTER_SHA: ${{ github.sha }}
42+
run: |
43+
set -euo pipefail
44+
45+
if [ "$BEFORE_SHA" = "0000000000000000000000000000000000000000" ]; then
46+
RANGE="$AFTER_SHA"
47+
else
48+
RANGE="$BEFORE_SHA..$AFTER_SHA"
49+
fi
50+
51+
invalid=0
52+
while IFS= read -r subject; do
53+
[ -z "$subject" ] && continue
54+
55+
if [[ "$subject" =~ ^Merge\ ]]; then
56+
continue
57+
fi
58+
59+
if [[ "$subject" =~ ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9._/-]+\))?(!)?:\ .+ ]]; then
60+
continue
61+
fi
62+
63+
echo "Invalid commit subject: $subject"
64+
invalid=1
65+
done < <(git log --format=%s "$RANGE")
66+
67+
if [ "$invalid" -ne 0 ]; then
68+
exit 1
69+
fi

.github/workflows/publish.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Publish to npm
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
inputs:
9+
dry_run:
10+
description: "Run semantic-release in dry-run mode"
11+
required: false
12+
default: false
13+
type: boolean
14+
15+
permissions:
16+
contents: write
17+
id-token: write
18+
19+
concurrency:
20+
group: semantic-release-${{ github.ref }}
21+
cancel-in-progress: false
22+
23+
jobs:
24+
release:
25+
runs-on: ubuntu-latest
26+
environment: npm
27+
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Setup Bun
35+
uses: oven-sh/setup-bun@v2
36+
with:
37+
bun-version: latest
38+
39+
- name: Setup Node
40+
uses: actions/setup-node@v4
41+
with:
42+
node-version: "24"
43+
registry-url: "https://registry.npmjs.org"
44+
45+
- name: Install dependencies
46+
run: bun install --frozen-lockfile
47+
48+
- name: Build
49+
run: bun run build
50+
51+
- name: Test
52+
run: bun test
53+
54+
- name: Semantic release
55+
run: |
56+
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.dry_run }}" = "true" ]; then
57+
bunx semantic-release --dry-run
58+
else
59+
bunx semantic-release
60+
fi
61+
env:
62+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

.releaserc.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"branches": [
3+
"main"
4+
],
5+
"plugins": [
6+
"@semantic-release/commit-analyzer",
7+
"@semantic-release/release-notes-generator",
8+
[
9+
"@semantic-release/npm",
10+
{
11+
"npmPublish": true
12+
}
13+
],
14+
[
15+
"@semantic-release/github",
16+
{
17+
"successComment": false,
18+
"failComment": false
19+
}
20+
]
21+
]
22+
}

AGENTS.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AGENTS.md
2+
3+
Guide for coding agents working on `opencode-mission-control` in ULW mode.
4+
5+
## Mission
6+
7+
- Keep changes small, safe, and shippable.
8+
- Match existing repository patterns (TypeScript + Bun + one-tool-per-file design).
9+
- Prefer deterministic behavior over clever behavior.
10+
11+
## Fast Project Map
12+
13+
- `src/index.ts` - plugin entry point, registers tools/hooks/commands.
14+
- `src/tools/` - one file per MCP tool (`launch`, `merge`, `plan`, etc.).
15+
- `src/lib/` - shared core logic (worktrees, tmux, monitor, orchestrator, merge train).
16+
- `src/hooks/` - OpenCode lifecycle hooks.
17+
- `tests/` - Bun test suite.
18+
19+
## ULW Working Rules
20+
21+
1. Implement exactly what was requested; do not add extra features.
22+
2. For bug fixes: make minimal edits, avoid broad refactors.
23+
3. Never use `as any`, `@ts-ignore`, or silent catch blocks.
24+
4. Keep file ownership boundaries intact (tool logic in `src/tools`, shared logic in `src/lib`).
25+
5. Do not commit unless explicitly asked.
26+
27+
## Build and Verify
28+
29+
Run these before marking work complete:
30+
31+
```bash
32+
bun run build
33+
bun test
34+
```
35+
36+
If tests fail, identify whether failures are pre-existing vs introduced by your change.
37+
38+
## Manual Test Plan
39+
40+
- The operational manual E2E flow is in `MANUAL_TEST_PLAN.md`.
41+
- For fast validation after changes, run the **Quick Smoke Test** section first.
42+
- Use the **Nuclear Cleanup** sequence before and after manual testing to avoid leftover tmux sessions, worktrees, branches, and state files.
43+
- Follow plan safety rules exactly: `tmc-` test naming, no remote push flows during testing (`mc_pr` is structural only), and explicit SHA-based resets.
44+
45+
## Release Notes for Agents
46+
47+
- npm package output is `dist/` only (`package.json -> files`).
48+
- Automated release path is semantic-release via `.github/workflows/publish.yml` on `main`.
49+
- Required secret for release workflow: `NPM_TOKEN`.
50+
- Use Conventional Commits (`feat:`, `fix:`, `perf:`, `chore:`) so semantic versioning can compute releases.
51+
52+
## Collaboration Norms
53+
54+
- Explain what changed and where with exact file paths.
55+
- Call out risks or assumptions explicitly.
56+
- Keep docs updated when behavior or workflows change.
57+
58+
If in doubt: choose the simplest implementation that preserves existing behavior.

AUDIT-REPORT.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ From opencode-dynamic-context-pruning and subtask2: **`output.messages` must be
134134
| Debounce + deduplication for notifications | quota, notificator | Prevent notification spam |
135135
| Zod schemas for config validation | scheduler, quota | MC declares Zod but never uses it |
136136

137-
### Novel Patterns Worth Stealing
137+
### Novel Patterns Worth Barrowing
138138

139139
| Pattern | Source Plugin | How MC Should Use It |
140140
|---------|-------------|---------------------|
@@ -393,7 +393,7 @@ MC's notification hooks (`notifications.ts`, `awareness.ts`) were dead code. The
393393
| Plugin | Key Insight for MC |
394394
|--------|-------------------|
395395
| **opencode-quota** | Definitive guide for `session.prompt({noReply: true})`. Copy their debounce + `parentID` skip logic. |
396-
| **opencode-pty** | `notifyOnExit` + ring buffer output = push notifications without polling. Steal this for pane death detection. |
396+
| **opencode-pty** | `notifyOnExit` + ring buffer output = push notifications without polling. Barrow this for pane death detection. |
397397
| **opencode-dynamic-context-pruning** | `output.messages` MUST be mutated in-place. Staleness-based pruning for MC's context injection. |
398398
| **oh-my-opencode** | Agent orchestration is prompt-driven. Tmux pane visibility for real-time watching. Session continuity via `session_id`. |
399399
| **opencode-notificator** | Most mature notification plugin. Uses `event` hook + `node-notifier` for OS alerts. Rate-limited. |

MVP-ASSESSMENT.md

Lines changed: 0 additions & 112 deletions
This file was deleted.

0 commit comments

Comments
 (0)