Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
392acd6
Update: WIP adding chan-ai package
dpaez May 21, 2026
c560274
Update: WIP chan-ai analyze fn working
dpaez May 29, 2026
38690c2
Update: WIP replace langchain with custom provider manager
dpaez May 30, 2026
91b0faf
Update: WIP replace langchain with custom provider manager
dpaez May 30, 2026
af955a6
Update: WIP replace langchain with custom provider manager
dpaez May 30, 2026
9ab594a
Update: slice 06 done
dpaez Jul 30, 2026
3ef3062
Update: slice 07 done
dpaez Jul 30, 2026
a505fba
Update: slice 08
dpaez Aug 25, 2026
03c7284
Update: tweaks
dpaez Aug 25, 2026
90f0927
Update: test tweak
dpaez Aug 25, 2026
3da363f
Fix: windows tests
dpaez Aug 25, 2026
de81f38
Fix: windows tests
dpaez Aug 25, 2026
d2fe40d
Update: slice 10
dpaez Sep 4, 2026
d083a87
Update: ignored files
dpaez Sep 4, 2026
52f72a2
feat(chan): add buildCodebaseSnapshot — deterministic codebase snapsh…
dpaez Sep 7, 2026
9b0ab5c
feat(chan-ai): add createInspector - Inspection operationfor the know…
dpaez Sep 9, 2026
7e89f6c
feat(chan): wire Inspection into init — AI-generated Context section …
dpaez Sep 10, 2026
50c216e
Update: add new e2e test
dpaez Sep 11, 2026
69cd814
docs(chan): document init Context generation in the README (slice 14)
dpaez Sep 19, 2026
941998e
Update: readme tweak
dpaez Sep 19, 2026
3fb809f
Update: audit fix
dpaez Sep 25, 2026
2145d01
Update: skills update
dpaez Sep 25, 2026
ffb06f9
Update: skip code.md and changelog from analyze
dpaez Sep 29, 2026
9d8bf43
Update: windows related optimizations, using execFile
dpaez Sep 30, 2026
c09a391
Update: prepare beta release
dpaez Sep 30, 2026
fda7f8d
Update: smoke test fix windows
dpaez Sep 30, 2026
f2cdbdb
Update: exclude lockfiles from analyze
dpaez Oct 1, 2026
ca401bd
Update: bump chan
dpaez Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .agents/skills/codebase-design/DEEPENING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Deepening

How to deepen a cluster of shallow modules safely, given its dependencies. Assumes the vocabulary in [SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**.

## Dependency categories

When assessing a candidate for deepening, classify its dependencies. The category determines how the deepened module is tested across its seam.

### 1. In-process

Pure computation, in-memory state, no I/O. Always deepenable: merge the modules and test through the new interface directly. No adapter needed.

### 2. Local-substitutable

Dependencies that have local test stand-ins (PGLite for Postgres, in-memory filesystem). Deepenable if the stand-in exists. The deepened module is tested with the stand-in running in the test suite. The seam is internal; no port at the module's external interface.

### 3. Remote but owned (Ports & Adapters)

Your own services across a network boundary (microservices, internal APIs). Define a **port** (interface) at the seam. The deep module owns the logic; the transport is injected as an **adapter**. Tests use an in-memory adapter. Production uses an HTTP/gRPC/queue adapter.

Recommendation shape: *"Define a port at the seam, implement an HTTP adapter for production and an in-memory adapter for testing, so the logic sits in one deep module even though it's deployed across a network."*

### 4. True external (Mock)

Third-party services (Stripe, Twilio, etc.) you don't control. The deepened module takes the external dependency as an injected port; tests provide a mock adapter.

## Seam discipline

- **One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a port unless at least two adapters are justified (typically production + test). A single-adapter seam is just indirection.
- **Internal seams vs external seams.** A deep module can have internal seams (private to its implementation, used by its own tests) as well as the external seam at its interface. Don't expose internal seams through the interface just because tests use them.

## Testing strategy: replace, don't layer

- Old unit tests on shallow modules become waste once tests at the deepened module's interface exist; delete them.
- Write new tests at the deepened module's interface. The **interface is the test surface**.
- Tests assert on observable outcomes through the interface, not internal state.
- Tests should survive internal refactors, since they describe behaviour, not implementation. If a test has to change when the implementation changes, it's testing past the interface.
44 changes: 44 additions & 0 deletions .agents/skills/codebase-design/DESIGN-IT-TWICE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Design It Twice

When the user wants to explore alternative interfaces for a chosen deepening candidate, use this parallel sub-agent pattern. Based on "Design It Twice" (Ousterhout): your first idea is unlikely to be the best.

Uses the vocabulary in [SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**, **leverage**.

## Process

### 1. Frame the problem space

Before spawning sub-agents, write a user-facing explanation of the problem space for the chosen candidate:

- The constraints any new interface would need to satisfy
- The dependencies it would rely on, and which category they fall into (see [DEEPENING.md](DEEPENING.md))
- A rough illustrative code sketch to ground the constraints, not a proposal, just a way to make the constraints concrete

Show this to the user, then immediately proceed to Step 2. The user reads and thinks while the sub-agents work in parallel.

### 2. Spawn sub-agents

Spawn 3+ sub-agents in parallel. Each must produce a **radically different** interface for the deepened module.

Prompt each sub-agent with a separate technical brief (file paths, coupling details, dependency category from [DEEPENING.md](DEEPENING.md), what sits behind the seam). The brief is independent of the user-facing problem-space explanation in Step 1. Give each agent a different design constraint:

- Agent 1: "Minimize the interface: aim for 1–3 entry points max. Maximise leverage per entry point."
- Agent 2: "Maximise flexibility: support many use cases and extension."
- Agent 3: "Optimise for the most common caller: make the default case trivial."
- Agent 4 (if applicable): "Design around ports & adapters for cross-seam dependencies."

Include both [SKILL.md](SKILL.md) vocabulary and CONTEXT.md vocabulary in the brief so each sub-agent names things consistently with the architecture language and the project's domain language.

Each sub-agent outputs:

1. Interface (types, methods, params, plus invariants, ordering, error modes)
2. Usage example showing how callers use it
3. What the implementation hides behind the seam
4. Dependency strategy and adapters (see [DEEPENING.md](DEEPENING.md))
5. Trade-offs: where leverage is high, where it's thin

### 3. Present and compare

Present designs sequentially so the user can absorb each one, then compare them in prose. Contrast by **depth** (leverage at the interface), **locality** (where change concentrates), and **seam placement**.

After comparing, give your own recommendation: which design you think is strongest and why. If elements from different designs would combine well, propose a hybrid. Be opinionated: the user wants a strong read, not a menu.
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
dist
.git
.github
*.log
.DS_Store
.pi
.vscode
30 changes: 19 additions & 11 deletions .github/workflows/node-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,32 @@ name: node-ci

on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:

runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
node-version: [22.x, 24.x]
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- run: yarn test
- uses: actions/checkout@v7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm run build
- run: npm run test:ci
- run: npm run lint
- run: npm run check-types
- run: npm run smoke
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ packages/**/dist

.vscode

lerna-debug.log
lerna-debug.log

.DS_Store

.agents/
.pi/
1 change: 0 additions & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"no-labels": "error",
"no-extra-label": "error",
"sort-imports": "off",

"unicorn/prefer-string-starts-ends-with": "error",
"unicorn/prefer-string-trim-start-end": "error",
"unicorn/prefer-spread": "error",
Expand Down
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [4.0.0-beta.0] - 2026-09-30

### Changed
- Packages are ESM TypeScript. Published `exports` and the `chan` bin point at the compiled `dist` output.
- Node.js 22 or newer is required.
- `@geut/chan-ai`: analyzer tools now receive `{ commitShas, cwd }` and return `Promise<string[]>` (one string per SHA, in the same order). `getCommitInfo` is renamed to `getCommitsInfo`.

### Added
- AI-assisted `chan analyze`, `chan auto`, and `chan hook`, plus a breaking-change check on `chan release`.

## [3.2.6] - 2021-12-23
### Fixed
- fixed bitbucket and gitlab url in releaseTemplate
Expand Down
41 changes: 41 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Chan

Chan is a changelog management tool (`@geut/chan`) with an optional AI layer that maintains a code knowledge base alongside the consumer-facing changelog.

## Language

### Artifacts

**Knowledge Base**:
The `.chan/code.md` file: an append-only, committed record of code changes (one entry per commit) plus an optional Context section. Supports changelog enhancement and future queries about how the codebase evolved.
_Avoid_: code.md file (when speaking conceptually), code base (reserved for the actual source tree)

**Changelog**:
The consumer-facing `CHANGELOG.md` curated by hand or by AI augmentation.
_Avoid_: knowledge base

**Context**:
The machine-owned `## Context` section at the top of the Knowledge Base: a terse, evidence-backed summary of the project (description, usage, runtimes, project types, requirements, notes), delimited by `chan:context` markers. Generated once at init by an Inspection and re-read as prompt context by later AI operations. The only part of the Knowledge Base exempt from the append-only rule.
_Avoid_: codebase context (that is the `AIConfig.context` option), project context

### Operations

**Inspection**:
The one-time AI operation that derives the Context from a Codebase Snapshot. Performed by the inspector (`createInspector` in chan-ai).
_Avoid_: analysis (reserved for commits), augmentation

**Analysis**:
The per-commit AI operation that produces a structured entry appended to the Knowledge Base.
_Avoid_: inspection

**Augmentation**:
The AI operation that turns one or more commits (plus Knowledge Base context) into a single changelog entry.

**Codebase Snapshot**:
The deterministic text gathered by chan (package.json, full README, top-level directory listing) that feeds an Inspection. Chan-ai never touches the filesystem to build it.
_Avoid_: inspection input, project description

### Invariants

**Append-only**:
The rule that existing Knowledge Base content is never rewritten; entries are only appended. The Context section is the sole exception.
13 changes: 13 additions & 0 deletions Dockerfile.cowork
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM node:22-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends git ca-certificates \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /workspace

COPY scripts/cowork-entrypoint.sh /usr/local/bin/cowork-entrypoint.sh
RUN chmod +x /usr/local/bin/cowork-entrypoint.sh

ENTRYPOINT ["cowork-entrypoint.sh"]
CMD ["tail", "-f", "/dev/null"]
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# chan

[![npm version](https://badge.fury.io/js/%40geut%2Fchan.svg)](https://badge.fury.io/js/%40geut%2Fchan)
[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/)

Chan is a set of tools used for writing and maintaining a CHANGELOG empowering the user to use a coloquial/friendly style.
See more here: [keepachangelog.com](http://keepachangelog.com/)
Expand Down
21 changes: 21 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
cowork:
build:
context: .
dockerfile: Dockerfile.cowork
container_name: chan-ai-cowork
volumes:
- .:/workspace
# Keep container-side node_modules isolated from the host so binaries
# and platform-specific packages work correctly inside Docker.
- node_modules:/workspace/node_modules
- chan-ai-dist:/workspace/packages/chan-ai/dist
working_dir: /workspace
stdin_open: true
tty: true
# No exposed ports: this is a CLI/test package with no HTTP service.
# Humans interact with it via `docker compose exec cowork ...`.

volumes:
node_modules:
chan-ai-dist:
4 changes: 2 additions & 2 deletions docs/KNOWLEDGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The codebase is organized into 6 packages under `/packages/`:
**Purpose**: End-user command-line interface

**Key Files**:
- `bin/chan.js` - CLI entry point using yargs
- `src/bin.ts` - CLI entry point using yargs (published as `dist/src/bin.js`)
- `src/commands/index.js` - Command registry
- `src/commands/init.js` - Initialize CHANGELOG.md
- `src/commands/actions.js` - Add changes (added, changed, fixed, etc.)
Expand Down Expand Up @@ -408,7 +408,7 @@ export function remarkToChan () {
├── node_modules/ # Dependencies
└── packages/
├── chan/ # CLI tool
│ ├── bin/chan.js
│ ├── src/bin.ts
│ ├── src/
│ │ ├── commands/
│ │ ├── config.js
Expand Down
Loading
Loading