Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ jobs:
- name: Verify committed action bundle is up to date
run: |
if ! git diff --exit-code -- packages/action/dist; then
echo "::error::packages/action/dist is out of date - run 'npm run build -w @seal/action' and commit the result."
echo "::error::packages/action/dist is out of date - run 'npm run build -w @docmend/action' and commit the result."
exit 1
fi
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dist/
.env.local
.DS_Store

# @seal/action ships as a GitHub Action, consumed directly from git with
# @docmend/action ships as a GitHub Action, consumed directly from git with
# no install/build step, so its bundled entry point must be committed.
!packages/action/dist/
!packages/action/dist/**
38 changes: 19 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# seal
# docmend

**Automated documentation healing.** seal watches your codebase, detects when a code change makes your docs inaccurate, and either fixes the stale section automatically or flags it for human review — as a local git hook, a GitHub Action, or both.
**Automated documentation healing.** docmend watches your codebase, detects when a code change makes your docs inaccurate, and either fixes the stale section automatically or flags it for human review — as a local git hook, a GitHub Action, or both.

Every team's docs drift out of sync with the code. seal closes that gap automatically, using an LLM to understand *what* changed and whether it actually invalidates what's written about it — not just that a file touched a function that happens to be mentioned somewhere.
Every team's docs drift out of sync with the code. docmend closes that gap automatically, using an LLM to understand *what* changed and whether it actually invalidates what's written about it — not just that a file touched a function that happens to be mentioned somewhere.

## How it works

Expand All @@ -13,25 +13,25 @@ Every team's docs drift out of sync with the code. seal closes that gap automati

## Installing

### As a local git hook (`@seal/cli`)
### As a local git hook (`@docmend/cli`)

```console
$ npm install --save-dev @seal/cli
$ npx seal init # installs a pre-commit hook
$ SEAL_GEMINI_API_KEY=... npx seal index # one-time: build the code-to-docs graph
$ npm install --save-dev @docmend/cli
$ npx docmend init # installs a pre-commit hook
$ DOCMEND_GEMINI_API_KEY=... npx docmend index # one-time: build the code-to-docs graph
```

From then on, `seal check` runs automatically on every commit: it diffs your staged changes, checks any linked docs for staleness, and — for high-confidence fixes — rewrites the doc and re-stages it alongside your change. Anything uncertain is reported, never silently applied.
From then on, `docmend check` runs automatically on every commit: it diffs your staged changes, checks any linked docs for staleness, and — for high-confidence fixes — rewrites the doc and re-stages it alongside your change. Anything uncertain is reported, never silently applied.

- Non-blocking by default. Pass `--strict` to block the commit when something needs review.
- `SEAL_SKIP=1 git commit ...` bypasses the check entirely.
- Re-run `seal index` after significant changes to refresh the cached graph (it's read fresh; nothing rebuilds automatically on every commit — that's what keeps the hook fast).
- `.sealignore` (gitignore-style syntax) excludes paths from the *changed-file* check.
- `DOCMEND_SKIP=1 git commit ...` bypasses the check entirely.
- Re-run `docmend index` after significant changes to refresh the cached graph (it's read fresh; nothing rebuilds automatically on every commit — that's what keeps the hook fast).
- `.docmendignore` (gitignore-style syntax) excludes paths from the *changed-file* check.

### As a GitHub Action (`@seal/action`)
### As a GitHub Action (`@docmend/action`)

```yaml
# .github/workflows/seal.yml
# .github/workflows/docmend.yml
on:
pull_request:

Expand All @@ -40,13 +40,13 @@ permissions:
pull-requests: write

jobs:
seal:
docmend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need the PR's base commit available, not just the head
- uses: dakshcodez/seal@v1
- uses: dakshcodez/docmend@v1
with:
gemini-api-key: ${{ secrets.GEMINI_API_KEY }}
# confidence-threshold: '0.8' # optional, default shown
Expand All @@ -57,7 +57,7 @@ On every PR, the Action diffs the base against the head commit, and for validate

## Configuration

Both the CLI and the Action read the same underlying pipeline. The CLI takes `SEAL_GEMINI_API_KEY` (or `GEMINI_API_KEY`) from the environment; the Action takes `gemini-api-key` as an input, matching the `action.yml` inputs (`confidence-threshold`, `auto-merge`, `github-token`).
Both the CLI and the Action read the same underlying pipeline. The CLI takes `DOCMEND_GEMINI_API_KEY` (or `GEMINI_API_KEY`) from the environment; the Action takes `gemini-api-key` as an input, matching the `action.yml` inputs (`confidence-threshold`, `auto-merge`, `github-token`).

## Real-world accuracy

Expand All @@ -71,9 +71,9 @@ TypeScript throughout, npm workspaces monorepo. Gemini (`gemini-3.7-flash` / `ge

```
packages/
core/ @seal/core - shared pipeline: parsing, link graph, change detection, doc repair
cli/ @seal/cli - npm package, the local git hook
action/ @seal/action - GitHub Action
core/ @docmend/core - shared pipeline: parsing, link graph, change detection, doc repair
cli/ @docmend/cli - npm package, the local git hook
action/ @docmend/action - GitHub Action
```

## License
Expand Down
10 changes: 5 additions & 5 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Real-world accuracy test

This documents a real-world test of seal against a fork of [tj/commander.js](https://github.com/tj/commander.js) (a real, actively-maintained, well-documented JavaScript library — chosen over the originally-suggested FastAPI/Pydantic for its much smaller size, to keep the test's embedding-API cost and runtime tractable on a free-tier key).
This documents a real-world test of docmend against a fork of [tj/commander.js](https://github.com/tj/commander.js) (a real, actively-maintained, well-documented JavaScript library — chosen over the originally-suggested FastAPI/Pydantic for its much smaller size, to keep the test's embedding-API cost and runtime tractable on a free-tier key).

## Methodology

1. Forked `tj/commander.js` to `dakshcodez/commander.js` and cloned it locally.
2. Ran `seal index` for real (live Gemini API, `gemini-3.7-flash`/`gemini-embedding-2` for indexing, `gemini-3.5-flash-lite` for the staleness/repair calls during this test session specifically to work around `3.7-flash`'s demand-driven `503`s — the shipped default remains `3.7-flash`). Indexed the full repo: **232 code chunks, 365 doc sections** (before the changelog-exclusion fix described below), producing 194 links (178 heuristic, 16 embedding).
3. Made three deliberate, targeted code changes and staged them, then ran `seal check` for real against the live pipeline.
2. Ran `docmend index` for real (live Gemini API, `gemini-3.7-flash`/`gemini-embedding-2` for indexing, `gemini-3.5-flash-lite` for the staleness/repair calls during this test session specifically to work around `3.7-flash`'s demand-driven `503`s — the shipped default remains `3.7-flash`). Indexed the full repo: **232 code chunks, 365 doc sections** (before the changelog-exclusion fix described below), producing 194 links (178 heuristic, 16 embedding).
3. Made three deliberate, targeted code changes and staged them, then ran `docmend check` for real against the live pipeline.
4. Inspected the actual generated corrections and verdicts against expectations.

## Deliberate test cases
Expand All @@ -31,6 +31,6 @@ Also observed, not fixed: the correction pass occasionally touched unrelated for
## Known limitations of this test

- The changelog-exclusion fix (bug #3 above) is verified at the unit level (the file-matching pattern was tested directly against 7 real-world filename cases, all correct) but **not re-validated end-to-end against the live API** — the free tier's *daily* embedding quota (1000 requests/day) was exhausted while re-indexing to confirm it, and daily quotas don't reset within a session. A full end-to-end re-run is a natural follow-up once quota is available.
- This test exercised the `@seal/cli` path (`seal index` + `seal check`) only, not the GitHub Action — the Action's `dist/index.js` isn't bundled for standalone execution yet (see the publish-phase task).
- This test exercised the `@docmend/cli` path (`docmend index` + `docmend check`) only, not the GitHub Action — the Action's `dist/index.js` isn't bundled for standalone execution yet (see the publish-phase task).
- One real repository, one language (JavaScript), a handful of deliberate cases — not a statistically rigorous accuracy benchmark, but real signal from real code and real docs rather than synthetic fixtures.
- The new `isTestFile`/`isChangelogFile` exclusions are unconditional — there's no way to opt a specific file back in short of renaming it. `.sealignore` exists as a user-facing override mechanism, but it's currently only wired into `check.ts`'s changed-file filtering, not into the doc/code indexing walk itself (a pre-existing gap, not introduced by this fix). A team that genuinely wants a file named `HISTORY.md` treated as living documentation has no escape hatch today.
- The new `isTestFile`/`isChangelogFile` exclusions are unconditional — there's no way to opt a specific file back in short of renaming it. `.docmendignore` exists as a user-facing override mechanism, but it's currently only wired into `check.ts`'s changed-file filtering, not into the doc/code indexing walk itself (a pre-existing gap, not introduced by this fix). A team that genuinely wants a file named `HISTORY.md` treated as living documentation has no escape hatch today.
40 changes: 20 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "seal",
"name": "docmend",
"private": true,
"version": "0.1.0",
"description": "Automated documentation healing for your codebase",
Expand All @@ -11,8 +11,8 @@
"node": ">=20"
},
"scripts": {
"build": "npm run build -w @seal/core && npm run build -w @seal/cli && npm run build -w @seal/action",
"typecheck": "npm run build -w @seal/core && npm run typecheck -w @seal/cli && npm run typecheck -w @seal/action",
"build": "npm run build -w @docmend/core && npm run build -w @docmend/cli && npm run build -w @docmend/action",
"typecheck": "npm run build -w @docmend/core && npm run typecheck -w @docmend/cli && npm run typecheck -w @docmend/action",
"lint": "eslint ."
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/action/action.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'seal - Automated Documentation Healing'
name: 'docmend - Automated Documentation Healing'
description: 'Detects code changes that make documentation stale, auto-fixes high-confidence cases via a PR, and flags the rest for human review.'
inputs:
gemini-api-key:
Expand All @@ -13,7 +13,7 @@ inputs:
required: false
default: '0.8'
auto-merge:
description: 'Automatically merge the auto-fix PR seal opens.'
description: 'Automatically merge the auto-fix PR docmend opens.'
required: false
default: 'false'
outputs:
Expand Down
Loading
Loading