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
43 changes: 24 additions & 19 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ROADMAP - @git-stunts/git-warp

Last reconciled: 2026-06-06
Last reconciled: 2026-06-12

**Current public package/tag release:** v17.0.0
**Next intended release:** v18.0.0
Expand All @@ -26,27 +26,33 @@ goalpost.
| Field | Value |
| --- | --- |
| Release id | `v18.0.0` |
| Release status | `active` |
| Release status | `pre-tag complete` |
| Current public release | `v17.0.0` |
| Goalposts | `5` |
| Landed goalposts | `4` |
| Landed goalposts | `5` |
| Total planned slice budget | `53` |
| Target milestone | `v18.0.0` |
| Release evidence packet | `docs/releases/v18.0.0/README.md` |

v18.0.0 is ready only when every goalpost below is landed, every issue in the
`v18.0.0` milestone is closed, superseded work has been closed or moved out of
the target milestone with linked disposition, the release evidence packet is
complete and placeholder-free, and `npm run release:preflight` passes from
aligned `main`.
v18.0.0 is ready for an explicit operator tag decision only when every goalpost
below is landed, every issue in the `v18.0.0` milestone is closed, superseded
work has been closed or moved out of the target milestone with linked
disposition, the release evidence packet is complete and placeholder-free, and
`npm run release:preflight` passes from aligned `main`.

As of 2026-06-12, GitHub has zero open `v18.0.0` milestone issues, zero open
`release-home:v18.0.0` issues, and zero open `lane:v18.0.0` issues. V18-GP5
[#552](https://github.com/git-stunts/git-warp/issues/552) is closed with
final-local guard evidence. No v18 tag has been cut; tagging still requires
explicit operator approval.
Comment thread
flyingrobots marked this conversation as resolved.

| Goalpost | Status | Slice budget | Umbrella or tracker issue | Goalpost doc | Release gate |
| --- | --- | ---: | --- | --- | --- |
| V18-GP1 Optics Public API Closeout | landed | 20 | [#547](https://github.com/git-stunts/git-warp/issues/547) | [v18-gp1-optics-public-api-closeout.md](method/roadmap/v18.0.0/v18-gp1-optics-public-api-closeout.md) | First-use Optics are usable and honest without hidden full materialization. |
| V18-GP2 Bounded-Memory Large-Graph Product Gate | landed | 15 | [#549](https://github.com/git-stunts/git-warp/issues/549) | [v18-gp2-bounded-memory-large-graph-gate.md](method/roadmap/v18.0.0/v18-gp2-bounded-memory-large-graph-gate.md) | Normal public reads, writes, content lookup, and sync must honor an explicit memory budget. |
| V18-GP3 Content Attachment Plane Honesty | landed | 4 | [#550](https://github.com/git-stunts/git-warp/issues/550) | [v18-gp3-content-attachment-plane-honesty.md](method/roadmap/v18.0.0/v18-gp3-content-attachment-plane-honesty.md) | Release claims now distinguish typed attachment-plane progress from accepted legacy storage residuals. |
| V18-GP4 Holographic Slicing And Checkpoint Basis | landed | 8 | [#626](https://github.com/git-stunts/git-warp/issues/626), [#628](https://github.com/git-stunts/git-warp/issues/628)-[#635](https://github.com/git-stunts/git-warp/issues/635) | [v18-gp4-holographic-slicing-checkpoint-basis.md](method/roadmap/v18.0.0/v18-gp4-holographic-slicing-checkpoint-basis.md) | Normal public graph-shaped reads now have bounded, witnessed slices over declared basis. |
| V18-GP5 Release Operation Evidence | active | 6 | [#552](https://github.com/git-stunts/git-warp/issues/552) | [v18-gp5-release-operation-evidence.md](method/roadmap/v18.0.0/v18-gp5-release-operation-evidence.md) | Tagging and publishing must satisfy the release policy and record deterministic evidence. |
| V18-GP5 Release Operation Evidence | landed | 6 | [#552](https://github.com/git-stunts/git-warp/issues/552) | [v18-gp5-release-operation-evidence.md](method/roadmap/v18.0.0/v18-gp5-release-operation-evidence.md) | Tagging and publishing must satisfy the release policy and record deterministic evidence. |

Sequencing:

Expand All @@ -58,18 +64,17 @@ V18-GP4 Holographic slicing basis
-> V18-GP5 Release operation evidence
```

V18-GP1, V18-GP2, V18-GP3, and V18-GP4 are landed. The next release-blocking
target is V18-GP5 [#552](https://github.com/git-stunts/git-warp/issues/552),
which owns release operation evidence and must not be completed before explicit
tag approval.
V18-GP1, V18-GP2, V18-GP3, V18-GP4, and V18-GP5 are landed. The remaining
v18 release action is an explicit operator tag decision. Do not create the
v18 tag without explicit operator approval.

Release progress should be reported as:

```text
v18.0.0 goalposts: 4/5 landed
v18.0.0 slices: 47/53 landed
next goalpost: V18-GP5 Release Operation Evidence
next slice: reconcile #552 against current issue metadata and release evidence
v18.0.0 goalposts: 5/5 landed
v18.0.0 slices: 53/53 landed
next goalpost: none for v18 before explicit tag approval
next slice: keep paying down v18-line debt without cutting the tag
```

## Pre-Migration Snapshot
Expand Down Expand Up @@ -107,7 +112,7 @@ the `type:*`, `priority:*`, `status:*`, and `area:*` label axes.

| Release Slot | Count | Planning Intent |
| --- | ---: | --- |
| v18.0.0 | 2 | Ship only after bounded-memory public paths and release operation evidence are coherent. |
| v18.0.0 | 0 | Pre-tag goalposts are closed; tag and publish still require explicit operator approval. |
| v18.0.1 | 50 | Repair public docs, examples, release tooling, and review guardrails that make the v18 line usable without expanding the runtime ontology. |
| v18.0.2 | 50 | Finish the remaining release-tooling spillover, then start the testing-quality cleanup wave with behavior-backed proofs instead of brittle text checks. |
| v18.0.3 | 50 | Continue static-text and fixture-quality paydown while keeping the release train small enough to review as one coherent patch wave. |
Expand Down Expand Up @@ -191,7 +196,7 @@ Ship only after bounded-memory public paths and release operation evidence are c
| Issue | Title | Status | Type | Lane | Feature | Release Home | Flags |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [#549](https://github.com/git-stunts/git-warp/issues/549) | Bounded-memory large-graph product gate | Closed | enhancement | release, v18.0.0 | graph-model-substrate | - | release |
| [#552](https://github.com/git-stunts/git-warp/issues/552) | v18 public release blockers | Blocked | release | release, v18.0.0 | graph-model-substrate | - | blocked, release |
| [#552](https://github.com/git-stunts/git-warp/issues/552) | v18 public release blockers | Closed | release | release, v18.0.0 | graph-model-substrate | - | release |

### v18.0.1 - Public Docs And Release Tooling Repair

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
- added the two explicit successor notes:
- PORT_extract-runtime-host-product.md
- DX_migrate-tests-and-seed-helpers-off-warpruntime.md
- added the split ratchet at
[delete-warpruntime-class-split.test.ts](../../../../test/unit/scripts/delete-warpruntime-class-split.test.ts)
- added the historical split ratchet
`test/unit/scripts/delete-warpruntime-class-split.test.ts`; that brittle
static-text ratchet was retired by the static-text witness burndown and is
now covered by
[openwarpgraph-composition-root.test.ts](../../../../test/unit/scripts/openwarpgraph-composition-root.test.ts)
plus
[WarpGraph.public-sync.test.ts](../../../../test/unit/domain/WarpGraph.public-sync.test.ts)
- updated the `v17` release ledger and workload map to the new order:
`PORT_extract-runtime-host-product` →
`DX_migrate-tests-and-seed-helpers-off-warpruntime` →
Expand All @@ -26,5 +31,5 @@ test/helper migration cut, then the actual file and export deletion.

## Witness

- `npm exec vitest run test/unit/scripts/delete-warpruntime-class-split.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `npm exec vitest run test/unit/scripts/openwarpgraph-composition-root.test.ts test/unit/domain/WarpGraph.public-sync.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `git diff --check`
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
- refreshed the ratchets:
- [runtime-host-product-seam.test.ts](../../../../test/unit/scripts/runtime-host-product-seam.test.ts)
- [openwarpgraph-composition-root.test.ts](../../../../test/unit/scripts/openwarpgraph-composition-root.test.ts)
- [WarpGraph.public-sync.test.ts](../../../../test/unit/domain/WarpGraph.public-sync.test.ts)
- [runtime-controller-host-types.test.ts](../../../../test/unit/scripts/runtime-controller-host-types.test.ts)
- [delete-warpruntime-class-split.test.ts](../../../../test/unit/scripts/delete-warpruntime-class-split.test.ts)
- [kill-warpruntime-split.test.ts](../../../../test/unit/scripts/kill-warpruntime-split.test.ts)

## Why it mattered
Expand All @@ -34,6 +34,6 @@ tests and helpers rather than by more hidden source imports.

## Witness

- `npm exec vitest run test/unit/scripts/runtime-host-product-seam.test.ts test/unit/scripts/openwarpgraph-composition-root.test.ts test/unit/scripts/runtime-controller-host-types.test.ts test/unit/domain/services/controllers/ForkController.test.ts test/unit/domain/warp/WarpGraphRuntimeBridge.test.ts test/unit/domain/WarpCore.content.test.ts test/unit/scripts/delete-warpruntime-class-split.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `npm exec vitest run test/unit/scripts/runtime-host-product-seam.test.ts test/unit/scripts/openwarpgraph-composition-root.test.ts test/unit/domain/WarpGraph.public-sync.test.ts test/unit/scripts/runtime-controller-host-types.test.ts test/unit/domain/services/controllers/ForkController.test.ts test/unit/domain/warp/WarpGraphRuntimeBridge.test.ts test/unit/domain/WarpCore.content.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `npm run typecheck`
- `git diff --check`
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
`API_kill-warpruntime`
- added and updated the ratchets:
- [migrate-warpruntime-test-helper-split.test.ts](../../../../test/unit/scripts/migrate-warpruntime-test-helper-split.test.ts)
- [delete-warpruntime-class-split.test.ts](../../../../test/unit/scripts/delete-warpruntime-class-split.test.ts)
- [openwarpgraph-composition-root.test.ts](../../../../test/unit/scripts/openwarpgraph-composition-root.test.ts)
- [WarpGraph.public-sync.test.ts](../../../../test/unit/domain/WarpGraph.public-sync.test.ts)
- [kill-warpruntime-split.test.ts](../../../../test/unit/scripts/kill-warpruntime-split.test.ts)

## Why it mattered
Expand All @@ -30,5 +31,5 @@ another giant test-surface bomb inside one blocker note.

## Witness

- `npm exec vitest run test/unit/scripts/migrate-warpruntime-test-helper-split.test.ts test/unit/scripts/delete-warpruntime-class-split.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `npm exec vitest run test/unit/scripts/migrate-warpruntime-test-helper-split.test.ts test/unit/scripts/openwarpgraph-composition-root.test.ts test/unit/domain/WarpGraph.public-sync.test.ts test/unit/scripts/kill-warpruntime-split.test.ts`
- `git diff --check`
36 changes: 32 additions & 4 deletions test/conformance/castQuarantineGraduation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import { join, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import ts from 'typescript';
import { describe, expect, it } from 'vitest';
import { z } from 'zod';

const REPO_ROOT = fileURLToPath(new URL('../../', import.meta.url));
const SRC_ROOT = join(REPO_ROOT, 'src');
const quarantineManifestSchema = z.object({
files: z.array(z.string()),
}).passthrough();

type CastHit = {
readonly path: string;
Expand All @@ -17,6 +21,11 @@ function readRepoFile(path: string): string {
return readFileSync(join(REPO_ROOT, path), 'utf8');
}

function readManifest(path: string): z.infer<typeof quarantineManifestSchema> {
const parsed: unknown = JSON.parse(readRepoFile(path));
return quarantineManifestSchema.parse(parsed);
}

function collectTypeScriptFiles(root: string): readonly string[] {
const files: string[] = [];
for (const entry of readdirSync(root, { withFileTypes: true })) {
Expand All @@ -43,11 +52,17 @@ function findCastHits(): readonly CastHit[] {
function findCastHitsInFile(file: string): readonly CastHit[] {
const source = readFileSync(file, 'utf8');
const sourceFile = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);
const lines = source.split(/\r?\n/u);
const hits: CastHit[] = [];

const visit = (node: ts.Node): void => {
if (isEscapeHatchCast(node)) {
const location = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
const endLocation = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
if (lineRangeHasDoubleCastSuppression(lines, location.line, endLocation.line)) {
ts.forEachChild(node, visit);
return;
}
hits.push({
path: relative(REPO_ROOT, file),
line: location.line + 1,
Expand All @@ -61,6 +76,15 @@ function findCastHitsInFile(file: string): readonly CastHit[] {
return hits;
}

function lineRangeHasDoubleCastSuppression(lines: readonly string[], startLine: number, endLine: number): boolean {
for (let line = startLine; line <= endLine; line++) {
if (lines[line]?.includes('nosemgrep: ts-no-double-cast')) {
return true;
}
}
return false;
}

function isEscapeHatchCast(node: ts.Node): boolean {
if (!ts.isAsExpression(node)) {
return false;
Expand All @@ -74,12 +98,16 @@ function isEscapeHatchCast(node: ts.Node): boolean {

describe('cast quarantine graduation', () => {
it('graduates the 0025A cast manifest to an empty file list', () => {
const manifest = readRepoFile('policy/quarantines/0025A-casts.json');
const manifest = readManifest('policy/quarantines/0025A-casts.json');

expect(manifest).toMatch(/"files"\s*:\s*\[\s*\]/u);
expect(manifest.files).toStrictEqual([]);
});

it('keeps src free of double-cast and any-cast escape hatches', () => {
expect(findCastHits()).toStrictEqual([]);
it('keeps the 0025A cast manifest aligned with unsuppressed parser-discovered escape hatches', () => {
const manifest = readManifest('policy/quarantines/0025A-casts.json');
const hitPaths = [...new Set(findCastHits().map((hit) => hit.path))]
.sort((left, right) => left.localeCompare(right));

expect(hitPaths).toStrictEqual(manifest.files);
});
});
Loading
Loading