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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ coverage/
.env.local
tests/e2e/.env.test
.vitest-cache/
.codex/night-loop/
# Local Claude artifacts stay ignored, but shared agent skills are tracked.
.claude/*
!.claude/skills/
18 changes: 9 additions & 9 deletions context/map/artifact-1-territory.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- GENERATED by tools/repo-map/scan.mjs — do not hand-edit. Run `npm run repo-map`. -->

> Scan of `7e3dab4` (2026-07-28) · window: last 12 months · engine: tools/repo-map
> Scan of `c823d6d` (2026-07-28) · window: last 12 months · engine: tools/repo-map

**Where the work actually happens.** Git-history activity over the last 12 months, noise filtered (lockfiles, generated files, assets). Activity is a signal of *risk of accidental regression*, not of quality.

Expand All @@ -11,11 +11,11 @@
| Area | Commits |
| --- | --- |
| `src/lib` | 75 |
| `context/map` | 54 |
| `context/changes` | 53 |
| `context/map` | 50 |
| `tests/e2e` | 32 |
| `src/commands` | 30 |
| `package.json` | 28 |
| `package.json` | 29 |
| `.github/workflows` | 19 |
| `context/archive` | 19 |
| `tests/get-command.test.ts` | 13 |
Expand All @@ -30,15 +30,15 @@

| File | Commits |
| --- | --- |
| `package.json` | 28 |
| `package.json` | 29 |
| `src/commands/get.ts` | 16 |
| `.github/workflows/ci.yml` | 14 |
| `tests/get-command.test.ts` | 13 |
| `src/lib/writer.ts` | 12 |
| `context/map/artifact-1-territory.md` | 10 |
| `context/map/artifact-2-structure.md` | 10 |
| `context/map/artifact-3-contributors.md` | 10 |
| `context/map/repo-map.md` | 10 |
| `context/map/artifact-1-territory.md` | 11 |
| `context/map/artifact-2-structure.md` | 11 |
| `context/map/artifact-3-contributors.md` | 11 |
| `context/map/repo-map.md` | 11 |
| `README.md` | 9 |
| `tests/writer.test.ts` | 9 |
| `context/map/graph/coupling.json` | 8 |
Expand All @@ -51,8 +51,8 @@
| Area | 2026-Q2 | 2026-Q3 |
| --- | --- | --- |
| `src/lib` | 34 | 1 |
| `context/map` | 0 | 11 |
| `context/changes` | 28 | 1 |
| `context/map` | 0 | 10 |
| `tests/e2e` | 11 | 0 |
| `src/commands` | 23 | 0 |

Expand Down
4 changes: 2 additions & 2 deletions context/map/artifact-2-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- GENERATED by tools/repo-map/scan.mjs — do not hand-edit. Run `npm run repo-map`. -->

> Scan of `7e3dab4` (2026-07-28) · window: last 12 months · engine: tools/repo-map
> Scan of `c823d6d` (2026-07-28) · window: last 12 months · engine: tools/repo-map

**How it is built.** Static import graph of `src` plus a file inventory of every module. Folders show where the code is; the graph shows what actually depends on what.

Expand All @@ -12,7 +12,7 @@
| --- | --- | --- |
| commands (CLI surface) | `src/commands` | 5 |
| lib (core logic) | `src/lib` | 19 |
| tests | `tests` | 46 |
| tests | `tests` | 47 |

## Circular dependencies in `src`

Expand Down
4 changes: 2 additions & 2 deletions context/map/artifact-3-contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- GENERATED by tools/repo-map/scan.mjs — do not hand-edit. Run `npm run repo-map`. -->

> Scan of `7e3dab4` (2026-07-28) · window: last 12 months · engine: tools/repo-map
> Scan of `c823d6d` (2026-07-28) · window: last 12 months · engine: tools/repo-map

**Who to ask before you change something.** Bots and AI agents (Claude, Codex, Copilot, dependabot…) are filtered out — this is about humans who hold undocumented context. Answers "who has context on this area", not "who changed this line" (that is `git blame`).

Expand All @@ -20,8 +20,8 @@
| Area | Ask (commits) |
| --- | --- |
| `src/lib` | “mkczarkowski” (29), psmyrdek (4) |
| `context/changes` | “mkczarkowski” (28) |
| `context/map` | Marcin Czarkowski (1) |
| `context/changes` | “mkczarkowski” (28) |
| `tests/e2e` | “mkczarkowski” (8), psmyrdek (3) |
| `src/commands` | “mkczarkowski” (19), psmyrdek (4) |
| `package.json` | “mkczarkowski” (7), Przemek Smyrdek (1) |
18 changes: 9 additions & 9 deletions context/map/repo-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- GENERATED by tools/repo-map/scan.mjs — do not hand-edit. Run `npm run repo-map`. -->

> Scan of `7e3dab4` (2026-07-28) · window: last 12 months · engine: tools/repo-map
> Scan of `c823d6d` (2026-07-28) · window: last 12 months · engine: tools/repo-map
>
> Operational map of the territory, built from cheap deterministic signals (git history + import graph), synthesized for decisions — not an essay. A new developer should know in ~15 min where things live, what is dangerous, and where to start. Refresh with `npm run repo-map`.

Expand All @@ -19,7 +19,7 @@
graph TD
commands["commands (CLI surface)<br/>5 files"]
lib["lib (core logic)<br/>19 files"]
tests["tests<br/>46 files"]
tests["tests<br/>47 files"]
```

## 2. Terrain — where the project lives
Expand All @@ -29,11 +29,11 @@ Top active areas (full table in `artifact-1-territory.md`):
| Area | Commits |
| --- | --- |
| `src/lib` | 75 |
| `context/map` | 54 |
| `context/changes` | 53 |
| `context/map` | 50 |
| `tests/e2e` | 32 |
| `src/commands` | 30 |
| `package.json` | 28 |
| `package.json` | 29 |
| `.github/workflows` | 19 |
| `context/archive` | 19 |

Expand Down Expand Up @@ -61,22 +61,22 @@ _No high-risk zones flagged this run._
| Area | Ask |
| --- | --- |
| `src/lib` | “mkczarkowski” (29), psmyrdek (4) |
| `context/changes` | “mkczarkowski” (28) |
| `context/map` | Marcin Czarkowski (1) |
| `context/changes` | “mkczarkowski” (28) |
| `tests/e2e` | “mkczarkowski” (8), psmyrdek (3) |
| `src/commands` | “mkczarkowski” (19), psmyrdek (4) |
| `package.json` | “mkczarkowski” (7), Przemek Smyrdek (1) |

## 6. First day — read these first

- `package.json` — 28 commits in window
- `package.json` — 29 commits in window
- `src/commands/get.ts` — 16 commits in window
- `.github/workflows/ci.yml` — 14 commits in window
- `tests/get-command.test.ts` — 13 commits in window
- `src/lib/writer.ts` — 12 commits in window
- `context/map/artifact-1-territory.md` — 10 commits in window
- `context/map/artifact-2-structure.md` — 10 commits in window
- `context/map/artifact-3-contributors.md` — 10 commits in window
- `context/map/artifact-1-territory.md` — 11 commits in window
- `context/map/artifact-2-structure.md` — 11 commits in window
- `context/map/artifact-3-contributors.md` — 11 commits in window

## 7. Limitations — what this map does NOT say

Expand Down
58 changes: 58 additions & 0 deletions context/night-loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Night loop runner

`scripts/night-loop.mjs` runs bounded, local Codex iterations against
`claude/context-loops-bootstrap`. It is intentionally narrower than the full
loop menu: config-only lint ratchets that already pass. Characterization work
is excluded until mutation proof can be executed mechanically; examples work
is excluded because its executable config cannot safely run in an unattended
outer gate.

## Safety contract

- Hard local-time deadline (default: the next `07:30`).
- One agent and one isolated git worktree at a time.
- Codex runs with `workspace-write`, `approval_policy=never`, and network
disabled. The runner—not the agent—performs authenticated GitHub operations.
- Maximum 8 iterations and 800,000 reported tokens by default. A single Codex
turn can overshoot the remaining token budget because usage is reported only
after the turn; no repair or later iteration starts after the ceiling.
- One base commit is pinned for the entire run. If the remote base advances,
the loop stops instead of comparing against a stale baseline.
- Exact differential gate: lint cannot regress; passing tests cannot decrease;
the pinned set of 8 build-dependent failures must remain byte-for-byte the
same. Characterization work must increase the passing-test count.
- At most two repair turns in the same Codex session. Persistent failure opens
an `automation` issue and preserves the failed worktree for diagnosis.
- Successful iterations open one small PR each. The runner never merges PRs.
- Agent and gate environments omit credential variables. Codex and outer gates
run without network; binary diffs and patches matching common secret formats
are rejected.

The machine must remain awake and online. Saved Codex authentication and `gh`
authentication must already work.

## Review and dry run

```bash
bun test tests/night-loop.test.ts
bun run night-loop -- --deadline 07:30 --dry-run
```

## Start an overnight run

```bash
nohup bun run night-loop -- --deadline 07:30 \
> .codex/night-loop-launcher.log 2>&1 &
```

State, command logs, final model outputs, and the final summary are written
under `.codex/night-loop/<run-id>/`. The directory is ignored by git.

Optional bounds:

```bash
bun run night-loop -- \
--deadline 2026-07-28T07:30:00+02:00 \
--max-iterations 4 \
--max-total-tokens 400000
```
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"repo-map": "node tools/repo-map/scan.mjs",
"repo-map:check": "node tools/repo-map/scan.mjs --check",
"examples:catalog": "node tools/examples-catalog/build.mjs",
"examples:catalog:check": "node tools/examples-catalog/build.mjs --check"
"examples:catalog:check": "node tools/examples-catalog/build.mjs --check",
"night-loop": "node scripts/night-loop.mjs"
},
"dependencies": {
"@clack/prompts": "0.9.1",
Expand Down
47 changes: 47 additions & 0 deletions scripts/night-loop-lib.d.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export interface LintSummary {
warnings: number;
errors: number;
}

export interface TestSummary {
pass: number;
fail: number;
}

export interface Baseline {
lint: LintSummary;
tests: TestSummary;
failedTests: string[];
}

export interface DiffStats {
files: number;
additions: number;
deletions: number;
binaryFiles: number;
}

export type LoopKind = "lint";

export function resolveDeadline(now: Date, value?: string): Date;
export function parseLintSummary(output: string): LintSummary;
export function parseTestSummary(output: string): TestSummary;
export function parseFailedTests(output: string): string[];
export function parseCodexEvents(output: string): {
threadId?: string;
totalTokens: number;
completedTurns: number;
};
export function parseNumstat(output: string): DiffStats;
export function validateScope(
kind: LoopKind,
paths: string[],
stats: DiffStats,
): string[];
export function validateDifferential(
kind: LoopKind,
baseline: Baseline,
candidate: Baseline,
): string[];
export function scanPatchForSecrets(patch: string): string[];
export function validateLintRuleChange(baseText: string, candidateText: string): string[];
Loading