Skip to content

Commit bf8dfd1

Browse files
committed
feat: harden dev workflow with safety guards, deterministic builds, and tool-agnostic agent config
- Add AGENTS.md as tool-agnostic AI config, CLAUDE.md becomes a symlink - Add ccc-dev/status.sh to detect pending work before destructive operations - Make ccc-dev/patch.sh produce deterministic commits (fixed author/date) - Guard ccc:record, ccc:clean, ccc:reset against data loss - Replace scripts/pr.sh and scripts/review.sh with inline agent workflows - Add telemetry opt-out env vars and wl-clipboard to devcontainer - Rename pnpm claude to pnpm coworker, add coworker:ask for scripting - Reorder check pipeline: lint before build for faster feedback - Update pnpm to 10.30.0 and typescript-eslint to 8.56.0 - Update all docs to reflect new tooling and workflows
1 parent 978c849 commit bf8dfd1

17 files changed

Lines changed: 610 additions & 341 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111

1212
"containerEnv": {
1313
"DEVCONTAINER": "true",
14-
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
14+
"DEVCONTAINERS_NO_TELEMETRY": "true",
15+
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
16+
"CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY": "1",
17+
"DO_NOT_TRACK": "1",
18+
"NEXT_TELEMETRY_DISABLED": "1",
19+
"NO_UPDATE_NOTIFIER": "1",
20+
"npm_config_update_notifier": "false"
1521
},
1622

1723
// Persisted volumes to speed installs and avoid repeated network requests
@@ -24,10 +30,12 @@
2430
"postCreateCommand": {
2531
// Enable corepack and fix workspace ownership for non-root user
2632
"permissions": "sudo corepack enable && sudo chown -R node:node /home/node ${containerWorkspaceFolder}",
27-
// Needed for anthropic.claude-code extension to work with a pnpm claude installation
28-
"aliases": "echo \"alias claude='pnpm claude'\" >> ~/.bash_aliases",
33+
// Needed for AI Coworker extension to work with a pnpm installation
34+
"aliases": "echo \"alias claude='pnpm coworker'\" >> ~/.bash_aliases",
2935
// Install GSD
30-
"gsd": "pnpm dlx get-shit-done-cc@latest --claude --global --force-statusline"
36+
"gsd": "pnpm dlx get-shit-done-cc@latest --claude --global --force-statusline",
37+
// Clipboard support for wl-copy/wl-paste (used by CLAUDE.md)
38+
"clipboard": "sudo apt-get update -qq && sudo apt-get install -y -qq wl-clipboard"
3139
},
3240

3341
// Run each time the container starts. Ensures updated dependencies are installed inside the container user environment.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@
88
# Reference repos
99
contracts/
1010
whitepaper/
11+
12+
# AI tool config symlink
13+
CLAUDE.md

.planning/codebase/CONVENTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
## Important Context
66

77
**Tooling:**
8-
- `gh` CLI is NOT available and must NOT be installed. Use `pnpm pr` to open PRs and `pnpm review` to fetch PR comments.
8+
- `gh` CLI is NOT available and must NOT be installed. PR and review workflows are handled inline by the AI Coworker (see AGENTS.md).
99

1010
**Legacy vs. New code:**
1111
- `@ickb/lumos-utils@1.4.2` and `@ickb/v1-core@1.4.2` are **LEGACY and DEPRECATED** npm packages. The apps (`apps/bot`, `apps/tester`, `apps/interface`) still depend on them.

.planning/codebase/STACK.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ The repo supports using a local development build of CCC for testing unpublished
101101
**`ccc-dev/record.sh`:**
102102
- Clones the CCC repo (`https://github.com/ckb-devrel/ccc.git`) into `./ccc-dev/ccc/`
103103
- Accepts refs as args: branch names, PR numbers, or commit SHAs
104-
- Merges specified refs onto a `wip` branch (uses Claude CLI for merge conflict resolution)
104+
- Merges specified refs onto a `wip` branch (uses AI Coworker CLI for merge conflict resolution)
105105
- Builds CCC locally: `pnpm build:prepare && pnpm build`
106106
- Run via: `pnpm ccc:record` (default invocation: `bash ccc-dev/record.sh releases/next releases/udt`)
107107
- The `ccc-dev/ccc/` directory is gitignored
108-
- Skips if `ccc-dev/ccc/` already exists (remove it to redo setup)
108+
- Aborts if `ccc-dev/ccc/` has pending work (any changes vs pinned commit, diverged HEAD, or untracked files)
109109

110110
**`.pnpmfile.cjs`:**
111111
- A pnpm `readPackage` hook that auto-discovers all packages in `ccc-dev/ccc/packages/*/package.json`

.planning/codebase/STRUCTURE.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
│ │ ├── REFS # Pinned branch HEADs
7474
│ │ └── resolutions/ # Merge conflict resolutions
7575
│ ├── ccc/ # Gitignored: ephemeral CCC clone (auto-generated)
76-
│ ├── record.sh # Records new pins with Claude conflict resolution
76+
│ ├── record.sh # Records new pins with AI Coworker conflict resolution
7777
│ ├── replay.sh # Deterministically rebuilds ccc/ from pins
7878
│ └── tsc.mjs # TypeScript compilation script override
7979
├── contracts/ # Reference: Rust on-chain contracts (git-ignored, clone via `pnpm reference`)
@@ -345,19 +345,15 @@
345345
- System: Record/replay mechanism for deterministic, conflict-free builds
346346
- `pins/`: Committed directory containing:
347347
- `REFS`: Pinned branch HEADs for merging
348-
- `resolutions/`: Serialized conflict resolutions with Claude aid
348+
- `resolutions/`: Serialized conflict resolutions with AI Coworker aid
349349
- `ccc/`: Generated from pins; auto-deleted and rebuilt on `pnpm install`
350350
- Activation: `.pnpmfile.cjs` hook triggers `replay.sh` and overrides package resolution
351351
- Commands:
352-
- Record: `pnpm ccc:record releases/next releases/udt` (requires Claude CLI)
352+
- Record: `pnpm ccc:record releases/next releases/udt` (requires AI Coworker CLI)
353+
- Status: `pnpm ccc:status` (check for pending work in `ccc/`)
353354
- Rebuild: `pnpm install` (automatic)
354-
- Clean: `pnpm ccc:nuke && pnpm install`
355-
356-
**scripts/:**
357-
- Purpose: Developer convenience scripts
358-
- Files: `pr.sh` (GitHub PR creation), `review.sh` (fetch PR comments)
359-
- Execution: Via `pnpm pr` and `pnpm review` shortcuts
360-
- Committed: Yes
355+
- Clean (re-replay): `pnpm ccc:clean && pnpm install` (guarded)
356+
- Reset (published): `pnpm ccc:reset && pnpm install` (guarded)
361357

362358
**node_modules/:**
363359
- Purpose: Installed npm/pnpm dependencies

AGENTS.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# AI Coworker Configuration
2+
3+
This file is the tool-agnostic agent config:
4+
5+
- Never add `Co-Authored-By` lines to commit messages.
6+
- Never add AI tool attribution or branding to PR descriptions, commit messages, or code comments (e.g. "Generated with ...", "Built by ...", "Powered by ...").
7+
- Refer to yourself as "AI Coworker" in docs and comments, not by product or company name.
8+
- Do not install or use `gh` CLI.
9+
- **Routine Pre-PR Validation**: `pnpm check:full`, it wipes derived state and regenerates from scratch. If `ccc-dev/ccc/` has pending work, the wipe is skipped to prevent data loss — re-record or push CCC changes first for a clean validation.
10+
- **Open a PR**: Push the branch, then construct and present a GitHub compare URL
11+
(`quick_pull=1`) to the user. Base branch is `master`. Prefill "title" (concise, under 70 chars) and "body" (markdown with ## Why and ## Changes sections). Be brief.
12+
- **Fetch PR review comments**: Use the GitHub REST API via curl. Fetch all three comment types (issue comments, reviews, and inline comments). Reviewers reply asynchronously — poll every minute until comments arrive.
13+
- **Copy to clipboard**:
14+
```
15+
head -c -1 <<'EOF' | wl-copy
16+
content goes here
17+
EOF
18+
```
19+
20+
# CCC Local Development (ccc-dev/)
21+
22+
The `ccc-dev/` system uses a record/replay mechanism for deterministic builds of a local CCC fork:
23+
24+
- `ccc-dev/pins/` is **committed** to git (base SHAs, merge refs, conflict resolutions), regenerated by `pnpm ccc:record`.
25+
- `ccc-dev/ccc/` is **not in git** — it is rebuilt from pins on `pnpm install`.
26+
- The developer may have **pending work** in `ccc-dev/ccc/`. Run `pnpm ccc:status` (exit 0 = safe to wipe, exit 1 = has custom work) before any operation that would destroy it. `pnpm ccc:record`, `pnpm ccc:clean`, and `pnpm ccc:reset` already guard against this automatically.
27+
- `.pnpmfile.cjs` silently rewrites all `@ckb-ccc/*` dependencies to `workspace:*` when `ccc-dev/ccc/` exists. Local CCC packages override published ones without any visible change in package.json files.
28+
- `pnpm install` has a side effect: if `ccc-dev/pins/REFS` exists but `ccc-dev/ccc/` does not, it automatically runs `ccc-dev/replay.sh` to rebuild CCC from pins. This is intentional.
29+
- `ccc-dev/patch.sh` rewrites CCC package exports to point at `.ts` source instead of `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same `pins/HEAD` hash. This is why imports from `@ckb-ccc/*` resolve to TypeScript source files inside `node_modules` — it is not a bug.
30+
- `ccc-dev/tsc.mjs` is a custom `tsc` wrapper that filters out diagnostics originating from `ccc-dev/ccc/`. CCC source does not satisfy this repo's strict tsconfig (`verbatimModuleSyntax`, `noUncheckedIndexedAccess`, `noImplicitOverride`), so the wrapper suppresses those errors while still reporting errors in stack source.
31+
32+
# Reference Repos
33+
34+
`contracts/` and `whitepaper/` (cloned via `pnpm reference`) are made **read-only** with `chmod -R a-w`. To refresh, delete the directory and re-run `pnpm reference`.
35+
36+
# Versioning
37+
38+
All packages use version `1001.0.0` (Epoch Semantic Versioning), managed by changesets (`pnpm changeset`).

README.md

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ This monorepo is developing the **new generation** of iCKB libraries, replacing
88

99
**New packages** (under `packages/`, built on CCC):
1010

11-
| Package | Purpose | Status |
12-
|---|---|---|
11+
| Package | Purpose | Status |
12+
| ------------- | -------------------------------------------------------------------------- | ------------------ |
1313
| `@ickb/utils` | Blockchain primitives, transaction helpers, epoch arithmetic, UDT handling | Active development |
14-
| `@ickb/dao` | Nervos DAO abstraction layer | Active development |
15-
| `@ickb/order` | Limit order cell management | Active development |
16-
| `@ickb/core` | iCKB core protocol logic (deposits, receipts, owned owner) | Active development |
17-
| `@ickb/sdk` | High-level SDK composing all packages | Active development |
14+
| `@ickb/dao` | Nervos DAO abstraction layer | Active development |
15+
| `@ickb/order` | Limit order cell management | Active development |
16+
| `@ickb/core` | iCKB core protocol logic (deposits, receipts, owned owner) | Active development |
17+
| `@ickb/sdk` | High-level SDK composing all packages | Active development |
1818

1919
**Apps migration status:**
2020

21-
| App | Purpose | Stack |
22-
|---|---|---|
23-
| `apps/faucet` | Testnet CKB distribution | **Migrated** to new packages + CCC |
24-
| `apps/sampler` | iCKB exchange rate sampling | **Migrated** to new packages + CCC |
25-
| `apps/bot` | Automated order matching | Legacy (`@ickb/v1-core` + Lumos) |
26-
| `apps/tester` | Order creation simulator | Legacy (`@ickb/v1-core` + Lumos) |
27-
| `apps/interface` | React web UI | Legacy (`@ickb/v1-core` + Lumos) |
21+
| App | Purpose | Stack |
22+
| ---------------- | --------------------------- | ---------------------------------- |
23+
| `apps/faucet` | Testnet CKB distribution | **Migrated** to new packages + CCC |
24+
| `apps/sampler` | iCKB exchange rate sampling | **Migrated** to new packages + CCC |
25+
| `apps/bot` | Automated order matching | Legacy (`@ickb/v1-core` + Lumos) |
26+
| `apps/tester` | Order creation simulator | Legacy (`@ickb/v1-core` + Lumos) |
27+
| `apps/interface` | React web UI | Legacy (`@ickb/v1-core` + Lumos) |
2828

2929
**Key upstream contributions:** UDT and Epoch support were contributed to CCC upstream and have been merged. Some local utilities may overlap with features now available natively in CCC.
3030

@@ -58,10 +58,10 @@ graph TD;
5858
When `ccc-dev/pins/REFS` is committed, `pnpm install` automatically sets up the CCC local development environment on first run (by replaying pinned merges via `ccc-dev/replay.sh`). No manual setup step is needed — just clone and install:
5959

6060
```bash
61-
git clone <repo-url> && cd stack && pnpm install
61+
git clone git@github.com:ickb/stack.git && cd stack && pnpm install
6262
```
6363

64-
To redo the setup from scratch: `rm -rf ccc-dev/ccc && pnpm install`.
64+
To redo the setup from scratch: `pnpm ccc:clean && pnpm install`.
6565

6666
See [ccc-dev/README.md](ccc-dev/README.md) for recording new pins, developing CCC PRs, and the full workflow.
6767

@@ -80,12 +80,15 @@ This clones two repos into the project root (both are git-ignored and made read-
8080

8181
## Developer Scripts
8282

83-
| Command | Description |
84-
|---|---|
85-
| `pnpm pr` | Open a GitHub PR creation page for the current branch. Uses Claude to auto-generate title and body when available, falls back to branch name and commit log. |
86-
| `pnpm review` | Fetch and display PR review comments from GitHub for the current branch (or `pnpm review -- --pr <number>` for a specific PR). |
87-
88-
> **Note:** `gh` CLI is not available in this environment. Use `pnpm pr` and `pnpm review` instead.
83+
| Command | Description |
84+
| ------------------- | ------------------------------------------------------------------------------------- |
85+
| `pnpm coworker` | Launch an interactive AI Coworker session (full autonomy, opus model). |
86+
| `pnpm coworker:ask` | One-shot AI query for scripting (sonnet model, stateless). Used by `pnpm ccc:record`. |
87+
| `pnpm ccc:status` | Check if CCC clone matches pinned state. Exit 0 = safe to wipe. |
88+
| `pnpm ccc:record` | Record CCC pins (clone, merge refs, build). Guarded against pending work. |
89+
| `pnpm ccc:clean` | Remove CCC clone, keep pins (guarded). Re-replay on next `pnpm install`. |
90+
| `pnpm ccc:reset` | Remove CCC clone and pins (guarded). Restores published CCC packages. |
91+
| `pnpm check:full` | Wipe derived state and validate from scratch. Skips wipe if CCC has pending work. |
8992

9093
## Epoch Semantic Versioning
9194

ccc-dev/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ CCC has unreleased branches (`releases/next`, `releases/udt`) that this project
1010

1111
2. **Workspace override** — When `ccc-dev/ccc/` is present, `.pnpmfile.cjs` auto-discovers all CCC packages and rewrites `@ckb-ccc/*` dependencies to `workspace:*` — no manual `pnpm.overrides` needed. This is necessary because `catalog:` specifiers resolve to a semver range _before_ pnpm considers workspace linking — even with `link-workspace-packages = true`, pnpm fetches from the registry without this hook. When CCC is not cloned, the hook is a no-op and deps resolve from the registry normally.
1212

13-
3. **Source-level types**`patch.sh` (called by both `record.sh` and `replay.sh`) patches CCC's `package.json` exports to point TypeScript at `.ts` source instead of built `.d.ts`. This gives real-time type feedback when editing across the CCC/stack boundary — changes in CCC source are immediately visible to stack packages without rebuilding.
13+
3. **Source-level types**`patch.sh` (called by both `record.sh` and `replay.sh`) patches CCC's `package.json` exports to point TypeScript at `.ts` source instead of built `.d.ts`, then creates a deterministic git commit (fixed author/date) so record and replay produce the same `pins/HEAD` hash. This gives real-time type feedback when editing across the CCC/stack boundary — changes in CCC source are immediately visible to stack packages without rebuilding.
1414

1515
4. **Diagnostic filtering**`ccc-dev/tsc.mjs` is a tsc wrapper used by stack package builds. Because CCC `.ts` source is type-checked under the stack's stricter tsconfig (`verbatimModuleSyntax`, `noImplicitOverride`, `noUncheckedIndexedAccess`), plain `tsc` would report hundreds of CCC diagnostics that aren't real integration errors. The wrapper emits output normally and only fails on diagnostics from stack source files. When CCC is not cloned, packages fall back to plain `tsc`.
1616

@@ -33,7 +33,7 @@ Recording captures the current upstream state and any conflict resolutions:
3333
pnpm ccc:record
3434
```
3535

36-
This runs `ccc-dev/record.sh` which clones CCC, merges the configured refs, uses Claude CLI to resolve any conflicts, patches for source-level type resolution, and writes `pins/`. Commit the resulting `ccc-dev/pins/` directory so other contributors get the same build.
36+
This runs `ccc-dev/record.sh` which clones CCC, merges the configured refs, uses AI Coworker to resolve any conflicts, patches for source-level type resolution, and writes `pins/`. Commit the resulting `ccc-dev/pins/` directory so other contributors get the same build.
3737

3838
The `ccc:record` script in `package.json` is preconfigured with the current refs:
3939

@@ -61,7 +61,7 @@ bash ccc-dev/record.sh 268 releases/next
6161
bash ccc-dev/record.sh abc1234
6262
```
6363

64-
Refs are merged sequentially onto a `wip` branch, then CCC is built. On merge conflicts, the script auto-resolves them using Claude.
64+
Refs are merged sequentially onto a `wip` branch, then CCC is built. On merge conflicts, the script auto-resolves them using AI Coworker.
6565

6666
## Developing CCC PRs
6767

@@ -96,15 +96,17 @@ git checkout wip # return to development
9696

9797
## Switching modes
9898

99+
**Check for pending work:** `pnpm ccc:status` — exit 0 if `ccc-dev/ccc/` matches pinned state (safe to wipe), exit 1 otherwise.
100+
99101
**Local CCC (default when `pins/` is committed):** `pnpm install` auto-replays pins and overrides deps.
100102

101103
**Published CCC:** `pnpm ccc:reset && pnpm install` — removes clone and pins, restores published packages.
102104

103-
**Re-record:** `pnpm ccc:record` wipes and re-records everything from scratch.
105+
**Re-record:** `pnpm ccc:record` wipes and re-records everything from scratch. Aborts if `ccc-dev/ccc/` has pending work.
104106

105107
**Force re-replay:** `pnpm ccc:clean && pnpm install` — removes clone but keeps pins, replays on next install.
106108

107109
## Requirements
108110

109-
- **Recording** (`pnpm ccc:record`): Requires [Claude CLI](https://www.npmjs.com/package/@anthropic-ai/claude-code) for automated conflict resolution (only when merging refs).
111+
- **Recording** (`pnpm ccc:record`): Requires the AI Coworker CLI (installed as a devDependency; invoked via `pnpm coworker:ask`) for automated conflict resolution (only when merging refs).
110112
- **Replay** (`pnpm install`): No extra tools needed — works for any contributor with just pnpm.

ccc-dev/patch.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
set -euo pipefail
33

44
# Patch a CCC clone for use in the stack workspace.
5-
# Usage: ccc-dev/patch.sh <ccc-repo-dir>
5+
# Usage: ccc-dev/patch.sh <ccc-repo-dir> <merge-count>
66

7-
REPO_DIR="${1:?Usage: patch.sh <ccc-repo-dir>}"
7+
REPO_DIR="${1:?Usage: patch.sh <ccc-repo-dir> <merge-count>}"
8+
MERGE_COUNT="${2:?Missing merge-count argument}"
89

910
# Remove CCC's own lockfile so deps are recorded in the root pnpm-lock.yaml
1011
rm -f "$REPO_DIR/pnpm-lock.yaml"
@@ -24,3 +25,11 @@ for pkg_json in "$REPO_DIR"/packages/*/package.json; do
2425
else . end
2526
) else . end' "$pkg_json" > "$pkg_json.tmp" && mv "$pkg_json.tmp" "$pkg_json"
2627
done
28+
29+
# Commit patched files with deterministic identity so record and replay produce the same hash
30+
export GIT_AUTHOR_NAME="ci" GIT_AUTHOR_EMAIL="ci@local"
31+
export GIT_COMMITTER_NAME="ci" GIT_COMMITTER_EMAIL="ci@local"
32+
PATCH_TS="@$((MERGE_COUNT + 1)) +0000"
33+
export GIT_AUTHOR_DATE="$PATCH_TS" GIT_COMMITTER_DATE="$PATCH_TS"
34+
git -C "$REPO_DIR" add -A
35+
git -C "$REPO_DIR" commit -m "patch: source-level type resolution"

ccc-dev/pins/HEAD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c6eb9a0aeb74f91b5fceedd56dde418ed71d151e
1+
ddd976a81f71d14135714a2b365cb6e3653126fc

0 commit comments

Comments
 (0)