Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
25cbf90
docs: v0.5.0 release cut — substrate-v2 command docs, team-memory gui…
claude Jul 7, 2026
58486bc
chore(security): add CodeQL, gitleaks, and Scorecard CI; harden SECUR…
claude Jul 7, 2026
7d9b508
feat: resolve CSS var() in fingerprints + machine-readable taste prof…
claude Jul 7, 2026
3b2fae9
merge item/docs: docs refresh + v0.5.0 release cut
claude Jul 7, 2026
dd5a026
merge item/taste: var() resolution + taste constraint profiles
claude Jul 7, 2026
6ba3afb
merge item/security: CodeQL, gitleaks, scorecard, hardened SECURITY.md
claude Jul 7, 2026
f933485
docs: changelog bullet for the var()/taste-profile work
claude Jul 7, 2026
0505ae4
feat: dashboard writes (ratify/retract), ledger CLI twins, route-stag…
claude Jul 7, 2026
08494f3
feat(ci): one-click version-bump + release pipeline; fix broken workf…
claude Jul 7, 2026
3156a87
merge item/dashwrites: ledger ratify/retract (dash + CLI) + route met…
claude Jul 7, 2026
2478f8e
merge item/release: one-click bump pipeline + release/CI fixes
claude Jul 7, 2026
e6da7d8
feat: sandboxed worktree dry-run — imagine --run executes the minimal…
claude Jul 7, 2026
b690c4d
merge item/dryrun: sandboxed imagine --run in an ephemeral worktree
claude Jul 7, 2026
457760c
feat(bench): measured benchmark harness, impact-quality eval, honest …
claude Jul 7, 2026
323241b
merge item/bench: measured benchmark harness + honest uniqueness comp…
claude Jul 7, 2026
001edba
chore: keep bench/ out of typecheck scope (measurement script, covere…
claude Jul 7, 2026
1595804
docs: changelog — the sandboxed dry-run runner shipped in this release
claude Jul 7, 2026
2ed5059
fix(scripts): complete regex escaping in rotateChangelog (CodeQL js/i…
claude Jul 7, 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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "forgekit",
"displayName": "Forge",
"version": "0.4.0",
"version": "0.5.0",
"description": "One config, every AI coding tool — cognitive substrate, tools, crew, guards, atlas, lean, recall from one source.",
"author": { "name": "CodeWithJuber" },
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "forgekit",
"version": "0.4.0",
"version": "0.5.0",
"description": "One config, every AI coding tool — cognitive substrate, MCP tools, guards, atlas, recall, and routing from one source.",
"author": { "name": "CodeWithJuber", "url": "https://github.com/CodeWithJuber" },
"homepage": "https://github.com/CodeWithJuber/forgekit#readme",
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# One-click release kickoff: Actions -> "Bump version" -> Run workflow.
# Runs the tests, bumps every version field via scripts/bump.mjs (package.json,
# package-lock.json, both plugin manifests, CITATION.cff, landing page, CHANGELOG
# rotation), commits "chore(release): vX.Y.Z", tags vX.Y.Z, and pushes commit + tag.
#
# Pushing the v* tag is what normally triggers release.yml — but pushes made with
# the default GITHUB_TOKEN deliberately do NOT trigger other workflows (GitHub's
# recursion guard). So this workflow also dispatches release.yml on the new tag
# explicitly, which needs `actions: write` (granted below). No PAT required.
name: Bump version

on:
workflow_dispatch:
inputs:
bump:
description: "Bump type (auto = conventional commits since last tag: BREAKING -> major, feat -> minor, else patch)"
type: choice
default: auto
options:
- auto
- patch
- minor
- major

permissions:
contents: write # push the release commit + tag
actions: write # dispatch release.yml on the new tag

concurrency:
group: bump
cancel-in-progress: false

jobs:
bump:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # full history + tags so "auto" can read commits since the last tag
- uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test # never tag a broken tree
- name: Bump version fields + rotate CHANGELOG
id: bump
env:
BUMP: ${{ inputs.bump }}
run: |
VERSION="$(node scripts/bump.mjs "$BUMP")"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Commit, tag, push
env:
VERSION: ${{ steps.bump.outputs.version }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore(release): v$VERSION"
git tag -a "v$VERSION" -m "v$VERSION"
git push origin HEAD "v$VERSION"
- name: Trigger the release workflow on the new tag
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.bump.outputs.version }}
run: gh workflow run release.yml --ref "v$VERSION"
16 changes: 13 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# CI gate for every push and PR: test matrix (Node 18/20/22), Biome lint+format, ShellCheck,
# the zero-runtime-dependency assertion, and dependency review. All must pass to merge.
# CI gate for every push and PR: test matrix (Node 20/22 — matches the ">=20" engines
# field; 18 is EOL), Biome lint+format, ShellCheck, the zero-runtime-dependency assertion,
# the version-drift guard, and dependency review. All must pass to merge.
name: CI

on:
Expand All @@ -17,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node: [18, 20, 22]
node: [20, 22]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
Expand Down Expand Up @@ -58,6 +59,15 @@ jobs:
- run: node -e "process.exit(Object.keys(require('./package.json').dependencies||{}).length)"
- run: npm pack --dry-run

version-drift:
name: Version fields agree
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
# package.json, package-lock.json, .claude-plugin/plugin.json, .codex-plugin/plugin.json,
# and CITATION.cff must all carry the same version (scripts/bump.mjs keeps them in sync).
- run: node scripts/bump.mjs check

dependency-review:
name: Dependency review
runs-on: ubuntu-latest
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# CodeQL static analysis for the JavaScript sources (src/, hooks/, test/). Findings land
# in Security -> Code scanning. This is CodeQL "advanced setup": if the repo ever had
# "default setup" enabled (Settings -> Code security), disable it there so the two don't
# fight over the same analysis slot.
name: CodeQL

on:
push:
branches: [main, master]
pull_request:
schedule:
- cron: "23 4 * * 1" # weekly, Monday 04:23 UTC — catches new queries, not just new code

permissions:
contents: read

jobs:
analyze:
name: Analyze (javascript-typescript)
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # upload SARIF results to code scanning
steps:
- uses: actions/checkout@v7
- uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
build-mode: none # interpreted — nothing to compile
- uses: github/codeql-action/analyze@v4
with:
category: "/language:javascript-typescript"
36 changes: 33 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# Push a v* tag -> test -> publish to public npm (with provenance) -> cut a GitHub Release.
# Requires one repo secret: NPM_TOKEN (an npm "Automation" token). See docs/RELEASING.md.
# Runs on a v* tag push, or via workflow_dispatch ON A TAG REF (bump.yml uses the
# dispatch path because pushes made with the default GITHUB_TOKEN never trigger
# other workflows). Flow: test -> assert tag == package.json version -> publish to
# public npm (with provenance) -> cut a GitHub Release.
#
# npm publish is SKIPPED with a warning — not failed — when the NPM_TOKEN secret is
# missing, so the GitHub Release is still created. Add an npm "Automation" token as
# the NPM_TOKEN repo secret to enable publishing. See docs/RELEASING.md.
name: Release

on:
push:
tags: ["v*"]
workflow_dispatch: # dispatched by bump.yml with --ref vX.Y.Z; must target a tag

permissions:
contents: read
Expand All @@ -15,7 +22,15 @@ jobs:
permissions:
contents: write # create the GitHub Release
id-token: write # npm provenance (supply-chain attestation)
env:
# secrets are not directly usable in step `if:`, so surface presence here.
HAS_NPM_TOKEN: ${{ secrets.NPM_TOKEN != '' }}
steps:
- name: Assert this run targets a v* tag
if: github.ref_type != 'tag'
run: |
echo "::error::Release must run on a v* tag ref (got '${{ github.ref }}'). Use the 'Bump version' workflow to cut one."
exit 1
- uses: actions/checkout@v7
with:
fetch-depth: 0 # full history so release notes can diff from the last tag
Expand All @@ -26,9 +41,24 @@ jobs:
cache: npm
- run: npm ci
- run: npm test
- run: npm publish --provenance --access public
- name: Assert tag matches package.json version
env:
TAG: ${{ github.ref_name }}
run: |
PKG="v$(node -p "require('./package.json').version")"
if [ "$TAG" != "$PKG" ]; then
echo "::error::Tag $TAG does not match package.json version $PKG. Re-run the 'Bump version' workflow instead of tagging by hand."
exit 1
fi
- name: Publish to npm (with provenance)
if: env.HAS_NPM_TOKEN == 'true'
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Skip npm publish (NPM_TOKEN not set)
if: env.HAS_NPM_TOKEN != 'true'
run: |
echo "::warning::NPM_TOKEN secret is not set — SKIPPING npm publish. The GitHub Release is still created. To publish, add an npm Automation token as the NPM_TOKEN repo secret (Settings -> Secrets and variables -> Actions) and re-run this workflow. See docs/RELEASING.md."
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
Expand Down
28 changes: 19 additions & 9 deletions .github/workflows/repo-settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
#
# NOTE: editing repo settings needs an ADMIN-scoped token. The default GITHUB_TOKEN
# cannot be granted `administration`, so add a fine-grained PAT (Administration: write,
# Metadata: read) as the repo secret ADMIN_TOKEN. Without it the job will 403 — in that
# case just run the two `gh` commands below locally once (they need no workflow):
# Metadata: read) as the repo secret ADMIN_TOKEN. Without it the job SKIPS with a
# warning (soft fail) — in that case just run the two `gh` commands below locally once
# (they need no workflow):
#
# gh repo edit CodeWithJuber/forgekit \
# --description "One config for every AI coding agent — cross-tool config + a cognitive substrate (memory, blast-radius, guardrails) for Claude Code, Codex, Cursor, Gemini, Aider, and more." \
# --homepage "https://github.com/CodeWithJuber/forgekit#readme" \
# --add-topic claude-code --add-topic ai-coding --add-topic ai-agents --add-topic mcp \
# --add-topic agents-md --add-topic cross-tool --add-topic cognitive-substrate \
# --add-topic developer-tools --add-topic cli --add-topic codex --add-topic cursor
# --add-topic ai-agents --add-topic claude-code --add-topic codex --add-topic cursor \
# --add-topic developer-tools --add-topic llm --add-topic memory --add-topic mcp \
# --add-topic agent-memory --add-topic cost-optimization --add-topic code-quality \
# --add-topic cli --add-topic zero-dependency --add-topic crdt --add-topic team-memory \
# --add-topic ai-coding --add-topic agents-md --add-topic cross-tool --add-topic cognitive-substrate
# gh api --method PATCH /repos/CodeWithJuber/forgekit -F has_discussions=true
name: Repo settings

Expand All @@ -27,15 +30,22 @@ jobs:
steps:
- name: Apply About, topics, and Discussions
env:
GH_TOKEN: ${{ secrets.ADMIN_TOKEN || github.token }}
GH_TOKEN: ${{ secrets.ADMIN_TOKEN }}
REPO: ${{ github.repository }}
run: |
if [ -z "$GH_TOKEN" ]; then
echo "::warning::ADMIN_TOKEN secret is not set — skipping. Editing repo settings needs a fine-grained PAT (Administration: write, Metadata: read) saved as the ADMIN_TOKEN repo secret; the default GITHUB_TOKEN cannot be granted 'administration'. Alternatively run the gh commands from this workflow's header comment locally."
exit 0
fi
set -e
# 19 topics (GitHub caps at 20): discoverability terms first, project-specific last.
gh repo edit "$REPO" \
--description "One config for every AI coding agent — cross-tool config + a cognitive substrate (memory, blast-radius, guardrails) for Claude Code, Codex, Cursor, Gemini, Aider, and more." \
--homepage "https://github.com/CodeWithJuber/forgekit#readme" \
--add-topic claude-code --add-topic ai-coding --add-topic ai-agents --add-topic mcp \
--add-topic agents-md --add-topic cross-tool --add-topic cognitive-substrate \
--add-topic developer-tools --add-topic cli --add-topic codex --add-topic cursor
--add-topic ai-agents --add-topic claude-code --add-topic codex --add-topic cursor \
--add-topic developer-tools --add-topic llm --add-topic memory --add-topic mcp \
--add-topic agent-memory --add-topic cost-optimization --add-topic code-quality \
--add-topic cli --add-topic zero-dependency --add-topic crdt --add-topic team-memory \
--add-topic ai-coding --add-topic agents-md --add-topic cross-tool --add-topic cognitive-substrate
gh api --method PATCH "/repos/$REPO" -F has_discussions=true
echo "Applied About, topics, and Discussions for $REPO."
35 changes: 35 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# OSSF Scorecard: weekly supply-chain posture check (branch protection, token permissions,
# pinned dependencies, ...). publish_results feeds the public viewer/API at
# https://scorecard.dev/viewer/?uri=github.com/CodeWithJuber/forgekit — required for the
# Scorecard badge. Results also land in Security -> Code scanning as SARIF.
# Scorecard itself will flag tag-pinned actions; this repo pins to major tags and lets
# Dependabot track them (see .github/dependabot.yml) — accepted trade-off, documented here.
name: Scorecard

on:
push:
branches: [master] # default branch only — publish_results requires it
schedule:
- cron: "30 5 * * 1" # weekly, Monday 05:30 UTC

permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
security-events: write # upload SARIF to code scanning
id-token: write # sign results so scorecard.dev will publish them
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false # scorecard checks for exactly this
- uses: ossf/scorecard-action@v2
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
30 changes: 30 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Secret scanning gate: gitleaks over the FULL git history on every push and PR.
# Deliberately blocking — a real credential in the tree or history should fail the build,
# not warn. (Rotate first, then rewrite/land; a red X is the cheap part of a leak.)
#
# Why this passes on our own redaction tests: test/_fixtures.js assembles secret-LOOKING
# strings at RUNTIME via .join() precisely so no secret-format literal exists in any blob
# for a scanner to match. Verified clean with gitleaks 8.16 across the whole history and
# working tree before this workflow was added — no .gitleaks.toml allowlist is needed.
name: Security

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

permissions:
contents: read

jobs:
gitleaks:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # gitleaks scans commit history, not just the checkout
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ github.token }} # PR comments / job summary
# GITLEAKS_LICENSE is only required for ORG-owned repos; this repo is user-owned.
1 change: 1 addition & 0 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ name: Stale
on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch: # allow a manual run to test the config

permissions:
issues: write
Expand Down
26 changes: 26 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ Stop-guard, so it works whether or not the model invokes it), **recall** (memory
`substrate_check` / `predict_impact` / `assumption_gate`) composes atlas, preflight,
route, scope, cortex, and verify into one pre-action contract before mutating work.

**PCM ledger** (`.forge/ledger/`; decision recorded in
[`docs/adr/0006-proof-carrying-memory.md`](docs/adr/0006-proof-carrying-memory.md)) —
the convergent store all memory subsystems write to. Every stored unit (cortex lesson,
`recall`/`brain` fact, reuse artifact, design fingerprint, doom-loop diagnosis) is a
content-addressed *claim*: claim bytes are a pure function of (kind, body, scope) —
byte-identical on every replica — evidence and tombstones are append-only hash-deduped
logs, and confidence (`val`) is a decayed Beta posterior moved only by independent
oracles (tests, CI, human accept/revert). Merge is a join-semilattice (property-tested:
commutative, associative, idempotent), so teammate ledgers converge in any order over
plain git — `forge init` emits the union-merge `.gitattributes` rule; `forge ledger
merge` folds in any other ledger tree. The legacy stores (`lessons/`, `recall`, `brain`)
remain the read path; the ledger is where their events converge. Surface: `forge ledger
stats | verify | show | blame | query | merge | import` (`--personal` for the
per-user ledger beside the global recall store).

## Component map — the reuse ledger (30 components)

**Reuse (rename + swap brand token, logic unchanged):**
Expand Down Expand Up @@ -132,6 +147,17 @@ forgekit/
sync.js # emitter (source → per-tool targets); hash + DO-NOT-EDIT
doctor.js # health checks
emit/ # one module per tool (claude, codex, cursor, gemini, aider, copilot, windsurf, zed, continue) + mcp
ledger.js # PCM core: content-addressed claims, oracle taxonomy, decayed Beta val, Eq. 3 retrieval, semilattice merge (ADR-0006)
ledger_store.js # git-native on-disk ledger (.forge/ledger/): sharded claims, append-only evidence/tombstone logs, normal-form verify
ledger_bridge.js # legacy-store bridge: cortex/recall/brain shadow-writes + idempotent `ledger import`
reuse.js # proof-carrying artifact cache: fingerprint (MinHash+LSH), exact→near→adapt→miss ladder, atlas revalidation
context.js # budgeted context assembly + completeness gate: R(edit) set cover, compression ladder, computed missing-set
diagnose.js # doom-loop diagnosis: normalized failure signatures; 3× = diagnosis claim + one-tier escalation
imagine.js # consequence simulation (Eq. 4): predicted breaks + minimal dry-run suite via greedy set cover
uifingerprint.js # deterministic design fingerprint + slop-distance / conformance gate (no LLM, no screenshots)
dash.js # localhost-only read-only dashboard over the ledger, metrics, and blast radius (node:http, one HTML page)
metrics.js # stage-tagged .forge/metrics.jsonl — the measured events every cost figure is computed from
cost_report.js # per-stage cost factors as pure arithmetic over metrics.jsonl; composes ONLY measured stages
source/
rules.json # THE canonical rules source (git · testing · security · style)
substrate.json # cognitive-substrate defaults (thresholds, routing, llm knobs)
Expand Down
Loading
Loading