|
| 1 | +# Charter Roadmap: v0.13 → v1.0 |
| 2 | + |
| 3 | +> ⚠️ **SUPERSEDED — historical record (archived 2026-05-30).** |
| 4 | +> This roadmap is essentially complete and is kept only for provenance. |
| 5 | +> The repo shipped **v1.0.0**; 11 of the 12 sequenced issues are closed |
| 6 | +> (#164 #163 #161 #160 #159 #162 #123 #122 #140 #155 #139) — only **#116** |
| 7 | +> (MCP gateway `charter_brief`) remains open. Parts B/4b deliverables exist |
| 8 | +> (`.github/VERSIONING.md`, `.github/workflows/codeql.yml`, `CODE_OF_CONDUCT.md`), |
| 9 | +> and Part G Phase 2 has executed (commercial commands `run`/`architect`/ |
| 10 | +> `scaffold`/`login` removed from `@stackbilt/cli` in #127/#183). |
| 11 | +> **For current direction, use the issue board, not this file.** |
| 12 | +
|
| 13 | +> **Synthesized from**: full issue triage (19 open issues), OSS hygiene audit (12 packages), and commercial-split impact analysis. |
| 14 | +> **Date**: 2026-05-23 |
| 15 | +> **Acceptance criterion**: `charter audit` run on the charter repo itself exits with a passing score — i.e., Charter governs itself. |
| 16 | +
|
| 17 | +--- |
| 18 | + |
| 19 | +## Thesis |
| 20 | + |
| 21 | +Charter's credibility rests on one thing: **it must govern itself**. The repo currently scores **0/100** on its own audit (`charter score` reports 102 false-positive broken path references; `charter audit` finds 0 patterns, 0 policy docs). Fixing that is not just issue #159 — it's the through-line for all OSS polish work. Every bug fix, hygiene improvement, and CI hardening either directly enables self-governance or removes noise that obscures it. |
| 22 | + |
| 23 | +Once PRs 1–3 land (false positives cleared, stack detection working), run `charter audit` on the charter repo to establish the actual baseline score. Set the v0.13 acceptance threshold from that measurement — not from a guess. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Commercial-Split Posture (No Firm Date — Plan Both Paths) |
| 28 | + |
| 29 | +The four commercial commands (`run`, `architect`, `scaffold`, `login`) and their supporting files (`http-client.ts`, `credentials.ts`, `types/scaffold-contract-types.ts`) will eventually move to `@stackbilt/build` in a new repo. There is no fixed date for this. The key boundary: |
| 30 | + |
| 31 | +- **11 governance packages** (`types`, `core`, `adf`, `git`, `classify`, `validate`, `drift`, `blast`, `surface`, `policies`, `ci`) are split-stable: all OSS polish on them carries forward unchanged. |
| 32 | +- **`@stackbilt/cli`**: governance-command sections (audit, drift, doctor, adf, serve, score, blast, surface, context) are split-stable. Commercial-command sections of README and any new tests targeting `run`/`architect`/`scaffold`/`login` logic are throwaway. |
| 33 | + |
| 34 | +**Rule**: Do all pre-split OSS work scoped to governance-only surface. Do not expand test coverage for the four commercial commands — their thin existing coverage (`deprecated-commands.test.ts`) is the correct migration safety net. |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +## Part A — Bug Fixes (PR 1–3, ship before anything else) |
| 39 | + |
| 40 | +These three PRs are blocking: they cause false signal that masks real governance problems. |
| 41 | + |
| 42 | +### PR 1 · Path Resolver — Filter Non-File Strings (`packages/cli/src/commands/score.ts`) |
| 43 | + |
| 44 | +**Closes**: #164 (URL/env-var false positives), #163 (Windows paths + cross-repo refs) |
| 45 | + |
| 46 | +**Root cause**: `looksLikePath()` and `extractPathCandidates()` in `score.ts` (~lines 980–1040) match HTTP routes (`/api/v1/users`), env-var assignments (`DATABASE_URL=http://…`), and Windows absolute paths (`C:\Users\…`) as broken file references. |
| 47 | + |
| 48 | +**Changes**: |
| 49 | +- `looksLikePath()`: add exclusion guards — strings starting with `http://`/`https://`, strings matching `[A-Z_]+=[^\s]` (env-var assignment), strings containing `://`, bare HTTP paths starting with `/` followed by two or more path segments with no extension. |
| 50 | +- `resolveReferencedPath()` (~lines 1011–1029): replace `startsWith('/')` absolute-path check with `path.isAbsolute()` (handles `C:\` and `/`). Add normalize for Windows drive-letter paths. |
| 51 | +- Cross-repo references: when a candidate path contains no local anchor and starts with a known sibling-repo prefix, emit a `[skip:cross-repo]` annotation instead of `[broken]`. |
| 52 | +- Add test cases for each false-positive category. |
| 53 | + |
| 54 | +### PR 2 · CLI Version — Read from CLI Package `package.json` (`packages/cli/src/commands/context.ts`) |
| 55 | + |
| 56 | +**Closes**: #161 |
| 57 | + |
| 58 | +**Root cause**: `buildContextModel()` in `context.ts` (~lines 470–479) reads version from `path.join(root, 'package.json')`, where `root` is cwd. When `charter context` is run from the charter monorepo root, cwd is the workspace root (`package.json` at v0.10.0), not the CLI package dir. |
| 59 | + |
| 60 | +**Change**: After reading the root `package.json`, if `pkg.name` does not match `@stackbilt/cli`, resolve the CLI package directory from `__dirname` and read `packages/cli/package.json` (or walk `__dirname` upward to the nearest `package.json` with `"name": "@stackbilt/cli"`). Use that version for the brief. This is isolated to the version field — all other context (routes, hotspots, patterns) should still resolve relative to cwd. |
| 61 | + |
| 62 | +### PR 3 · Stack Detection — TypeScript Monorepos (`packages/cli/src/commands/setup.ts`) |
| 63 | + |
| 64 | +**Closes**: #160 (TypeScript monorepo detection), partially unblocks #162 and #159 |
| 65 | + |
| 66 | +**Root cause**: `loadPackageContexts()` (~line 645) only checks for `pnpm-workspace.yaml`. The monorepo flag (~line 458) only sets true for pnpm. |
| 67 | + |
| 68 | +**Changes**: |
| 69 | +- Parse `tsconfig.json` at root for `"references"` array → TypeScript project-references layout. |
| 70 | +- Parse root `package.json` `"workspaces"` field → npm/yarn workspaces. |
| 71 | +- Mark `monorepo: true` for any of the three cases. |
| 72 | +- `detectStack()` should return `"typescript-monorepo"` preset when `tsconfig.json` + multi-package layout detected. |
| 73 | +- Hotspot analysis fallback: when direct file-churn analysis returns empty (no git history for sub-packages), fall back to top-level package directory churn. |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## Part B — OSS Hygiene (PR 4, all 12 packages, split-safe) |
| 78 | + |
| 79 | +**One PR** touching all 12 `package.json` files. Quick wins with outsized impact on npm discoverability and supply-chain trust. |
| 80 | + |
| 81 | +### PR 4 · Package Metadata Sweep |
| 82 | + |
| 83 | +**Gaps found** (all 12 packages): |
| 84 | + |
| 85 | +| Gap | Impact | Fix | |
| 86 | +|-----|--------|-----| |
| 87 | +| `keywords` missing on all 12 | npm search invisibility | Add 3–5 per package (e.g. `["governance","charter","typescript","monorepo","cli"]` for cli; package-specific terms for others) | |
| 88 | +| `publishConfig.provenance: true` missing on all 12 | attestation doesn't attach to npm metadata | Add `"provenance": true` to existing `publishConfig` block in every package.json | |
| 89 | +| Root `package.json` missing `engines` field | no Node version signal at repo level | Add `"engines": { "node": ">=18.0.0" }` to root | |
| 90 | +| `author` field missing on 11/12 packages | trust/accountability gap | Add `"author": "Stackbilt LLC"` to all 11 | |
| 91 | + |
| 92 | +**What's already correct** (do not change): `repository.directory` (all correct), `exports` map (proper ESM/CJS), `sideEffects: false`, `engines` per-package, `files` whitelist, `bugs`, `homepage`, `license`, `publishConfig.access: "public"`. |
| 93 | + |
| 94 | +**Also in this PR**: |
| 95 | +- Create root `.npmignore` blocking `*.test.ts`, `*.spec.ts`, `__tests__/`, `tsconfig*.json`, `*.tsbuildinfo`, `*.map` as defense-in-depth alongside `files` whitelists. |
| 96 | + |
| 97 | +### PR 4b · GitHub Repo Hygiene (`.github/`) |
| 98 | + |
| 99 | +**Not filed as an issue — OSS hygiene gap** |
| 100 | + |
| 101 | +Current state of `.github/`: |
| 102 | +- `ISSUE_TEMPLATE/` (bug_report, feature_request, config) — ✓ present |
| 103 | +- `PULL_REQUEST_TEMPLATE.md` — ✓ present |
| 104 | +- `dependabot.yml` (npm + github-actions, weekly) — ✓ present |
| 105 | +- `CODEOWNERS` — ✓ present but only covers `/.ai/*`; all other paths unowned |
| 106 | +- `CODE_OF_CONDUCT.md` — **missing** |
| 107 | +- CodeQL / code scanning workflow — **missing** |
| 108 | + |
| 109 | +**Changes**: |
| 110 | +1. Add `CODE_OF_CONDUCT.md` at repo root using the [Contributor Covenant 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) template. Enforcement contact: `admin@stackbilt.dev` (matches SECURITY.md). |
| 111 | +2. Add `.github/workflows/codeql.yml` — CodeQL on push to main, schedule weekly. Target: JavaScript/TypeScript. This enables GitHub's code scanning dashboard and closes a "top notch OSS" signal gap. |
| 112 | +3. Expand `CODEOWNERS`: add `* @Stackbilt-dev/charter-maintainers` as a catch-all so all PRs require review, with more specific overrides for `packages/cli/ @Stackbilt-dev/cli-team` etc. |
| 113 | + |
| 114 | +This PR can be bundled with PR 4 (package-metadata-sweep) or shipped independently. |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Part C — Test Coverage at Export Boundary (PR 5) |
| 119 | + |
| 120 | +**Closes**: OSS hygiene gap (no issue filed) |
| 121 | + |
| 122 | +The CLAUDE.md policy says "every public export must have test coverage." Four packages currently violate this: |
| 123 | + |
| 124 | +| Package | Untested export | Suggested test location | |
| 125 | +|---------|-----------------|------------------------| |
| 126 | +| `@stackbilt/ci` | `setOutput`, `setSummary`, `annotateDriftViolations`, `annotateValidationStatus`, `formatPRComment` — all 5 have zero unit tests | `packages/ci/src/__tests__/ci.test.ts` | |
| 127 | +| `@stackbilt/classify` | `formatChangeClassification()` | `packages/classify/src/__tests__/format.test.ts` | |
| 128 | +| `@stackbilt/validate` | `classifyMessage()` boundary behavior | `packages/validate/src/__tests__/classify.test.ts` | |
| 129 | +| `@stackbilt/surface` | `formatSurfaceMarkdown()` | `packages/surface/src/__tests__/format.test.ts` | |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +## Part D — Dogfood: Make Charter Pass Its Own Audit (PR 6) |
| 134 | + |
| 135 | +**Closes**: #159 |
| 136 | + |
| 137 | +This is the credibility PR. After PRs 1–3 land (false positives gone, stack detection working), the charter repo should be able to score itself. What's still needed: |
| 138 | + |
| 139 | +1. **`.charter/patterns/`**: Add at minimum one pattern file capturing the governance trailer pattern used in this repo (Conventional Commits + issue references). Use `charter adf populate` output as a starting point, then hand-edit. |
| 140 | +2. **Policy documentation**: The audit checks for policy files covering Security, Versioning, and Contributing. The files already exist (`SECURITY.md`, `CONTRIBUTING.md`, `PUBLISHING.md`) but may not match the section headings the audit expects. Align or add a `docs/governance-policy.md` that explicitly covers what the audit scanner expects. |
| 141 | +3. **`.charter/config.json`**: Add `policyFiles` array pointing to the existing files, and `patternDir: ".charter/patterns"`. |
| 142 | + |
| 143 | +**Acceptance test**: `charter audit --format text` on the charter repo exits 0 with score > 60/100. |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## Part E — UX & DX Improvements (PR 7–9, v0.13 target) |
| 148 | + |
| 149 | +### PR 7 · Default `charter` Command — Risk-First View (`packages/cli/src/commands/why.ts`) |
| 150 | + |
| 151 | +**Closes**: #162, partially #139 |
| 152 | + |
| 153 | +**Change**: In `quickstartCommand()`, detect whether `.charter/` exists. If yes, skip the adoption pitch and render a "governance posture" view: risk-signal summary (unreviewed high-risk commits, drift violations, coverage %), next recommended action. If no, keep the current adoption pitch. The "Why teams use Charter" block should never appear on an installed repo. |
| 154 | + |
| 155 | +### PR 8 · CI Tag Unification (`.github/workflows/release.yml`) |
| 156 | + |
| 157 | +**Closes**: #123, #122 |
| 158 | + |
| 159 | +**Changes**: |
| 160 | +- Extract the tag-format regex into a reusable script (`scripts/validate-tag.sh`) shared by both `publish-release` and `publish-npm` jobs. |
| 161 | +- Add a `needs: [verify-tag]` edge from `publish-npm` to the tag-verification job so it cannot proceed on a malformed tag. |
| 162 | +- Create `.github/VERSIONING.md` documenting the unified-versioning invariant: all workspace packages share a single version; the release tag is the source of truth; if independent versioning is ever adopted, the guard in `release.yml` must be replaced with per-package metadata. |
| 163 | +- Annotate the workspace version loop in `release.yml` with a comment pointing to `VERSIONING.md`. |
| 164 | + |
| 165 | +### PR 9 · README Quick-Start Decision Table |
| 166 | + |
| 167 | +**Closes**: #140 |
| 168 | + |
| 169 | +One markdown table near the top of `README.md` (after the install command, before the deep reference): |
| 170 | + |
| 171 | +| Situation | Command | |
| 172 | +|-----------|---------| |
| 173 | +| First time in repo | `charter setup` | |
| 174 | +| Daily commit check | `charter audit` | |
| 175 | +| See what changed | `charter drift` | |
| 176 | +| AI context for current session | `charter context` | |
| 177 | +| Full governance posture report | `charter score` | |
| 178 | +| Check blast radius of a change | `charter blast <file>` | |
| 179 | + |
| 180 | +Keep the table to 6–8 rows max. Link each command to its anchor in the CLI reference. |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +## Part F — Feature Work (v0.13, lower urgency) |
| 185 | + |
| 186 | +These are non-blocking and can be worked in parallel with Parts A–E or deferred to a dedicated v0.13 sprint. |
| 187 | + |
| 188 | +### `context-refresh` enhancements (#155) |
| 189 | +- `charter context-refresh --watch` mode: re-emit brief on file changes using `fs.watch()`. |
| 190 | +- `--ttl-minutes N`: emit a refreshed brief every N minutes (for long agent sessions). |
| 191 | +- Both are additive; the command already exists. |
| 192 | + |
| 193 | +### MCP gateway brief exposure (#116) |
| 194 | +- In `packages/cli/src/commands/serve.ts`, register a `charter_brief` MCP tool/resource. |
| 195 | +- Input: optional `repo` path (defaults to cwd). |
| 196 | +- Output: the same JSON that `charter context --format json` produces. |
| 197 | +- Per-tenant targeting: accept a `tenantId` header and resolve repo path from a config map. |
| 198 | + |
| 199 | +### Bootstrap fragility (#139, partial) |
| 200 | +- `charter bootstrap --yes` failing the `install` step in locked environments should not report partial status if setup/adf/doctor all succeeded. Treat `install` as best-effort; report a warning, not a failure. |
| 201 | + |
| 202 | +### Repo intelligence module (#138) |
| 203 | +- Optional: `charter gh-intel` (requires `gh` CLI in PATH). |
| 204 | +- Pulls: recent PR patterns, open issue count, CODEOWNERS, branch protection rules. |
| 205 | +- Appends a `## Repo Intelligence` section to the ADF context bundle. |
| 206 | + |
| 207 | +--- |
| 208 | + |
| 209 | +## Part G — v1.0 Commercial Split (when scheduled) |
| 210 | + |
| 211 | +**Do not execute until a firm date is set.** The plan is clear: |
| 212 | + |
| 213 | +1. **Phase 1** (new repo): Stand up `Stackbilt-dev/stackbilt-build`, create `@stackbilt/build` package skeleton, copy `run.ts`, `architect.ts`, `scaffold.ts`, `login.ts`, `http-client.ts`, `credentials.ts`. Port `login.test.ts` and the commercial cases from `deprecated-commands.test.ts`. |
| 214 | + |
| 215 | +2. **Phase 2** (this repo): Remove the four command files from `packages/cli/src/commands/`. Replace their switch-case entries in `src/index.ts` with calls to `deprecation-warning.ts` that point users to `@stackbilt/build`. Remove `auth-wiring.test.ts` commercial cases. |
| 216 | + |
| 217 | +3. **Phase 3** (release.yml): Remove `@stackbilt/cli` from the monorepo publish sweep (or carve it out into a separate job that ships on its own version cadence). |
| 218 | + |
| 219 | +4. **Phase 4** (docs): Rewrite `packages/cli/README.md` commercial-command sections as redirect stubs. Update root `README.md` to reflect the split. |
| 220 | + |
| 221 | +**Pre-split work to defer** (throwaway cost if done now): |
| 222 | +- New test coverage for `run`, `architect`, or `scaffold` command logic. |
| 223 | +- `@stackbilt/cli` keywords/description framing that emphasizes `run`/`architect`. |
| 224 | +- Any CLI README section covering the four commercial commands in depth. |
| 225 | + |
| 226 | +--- |
| 227 | + |
| 228 | +## Sequenced PR Order |
| 229 | + |
| 230 | +``` |
| 231 | +PR 1 path-resolver-fixes → closes #164, #163 |
| 232 | +PR 2 cli-version-fix → closes #161 |
| 233 | +PR 3 ts-monorepo-stack-detection → closes #160 |
| 234 | + ↓ |
| 235 | +PR 4 package-metadata-sweep → OSS hygiene (all 12 packages) |
| 236 | +PR 5 export-boundary-tests → @stackbilt/ci, classify, validate, surface |
| 237 | + ↓ |
| 238 | +PR 6 dogfood-self-governance → closes #159 ← credibility gate |
| 239 | + ↓ |
| 240 | +PR 7 default-command-risk-view → closes #162 |
| 241 | +PR 8 ci-tag-unification → closes #123, #122 |
| 242 | +PR 9 readme-quickstart-table → closes #140 |
| 243 | + ↓ |
| 244 | +PR 10 context-refresh-enhancements → closes #155 |
| 245 | +PR 11 mcp-brief-exposure → closes #116 |
| 246 | +PR 12 bootstrap-fragility-fix → closes #139 (partial) |
| 247 | + ↓ |
| 248 | + [v0.13 cut] |
| 249 | + ↓ |
| 250 | + [when commercial split date is set → Part G] |
| 251 | +``` |
| 252 | + |
| 253 | +PRs 1–3 are dependencies for PR 6 (false positives must be gone before self-audit is meaningful). PRs 4–5 are independent and can be batched. PR 6 is the milestone gate — "Charter governs itself" is the v0.13 headline. |
| 254 | + |
| 255 | +--- |
| 256 | + |
| 257 | +## Issues Not Covered by This Roadmap |
| 258 | + |
| 259 | +| Issue | Status | |
| 260 | +|-------|--------| |
| 261 | +| #90 — configurable dependency orchestration | Deferred: requires design review; no clear scope yet | |
| 262 | +| #102 — drift code-gen-aware scanning | Deferred to post-v0.13: useful but not blocking | |
| 263 | +| #115 — portfolio .charter coverage audit | Deferred: operational task, not a code change | |
| 264 | +| #138 — GitHub CLI repo intelligence | Listed in Part F as optional | |
| 265 | + |
| 266 | +--- |
| 267 | + |
| 268 | +## Measuring Success |
| 269 | + |
| 270 | +At v0.13 cut, these should all be true: |
| 271 | + |
| 272 | +- [ ] `charter score` on the charter repo exits with < 10 broken references (was 102+) |
| 273 | +- [ ] `charter audit` on the charter repo exits with score ≥ baseline+30 (measure baseline after PR 1–3, then set threshold) |
| 274 | +- [ ] `charter --version` and `charter context` both report the same version |
| 275 | +- [ ] All 12 package.json files have `keywords`, `author`, and `publishConfig.provenance: true` |
| 276 | +- [ ] `pnpm test` remains 490+/490 passing |
| 277 | +- [ ] `@stackbilt/ci`, `@stackbilt/classify`, `@stackbilt/validate`, `@stackbilt/surface` all have export-boundary unit tests |
0 commit comments