Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ec9a33c
docs(maintenance): add regression review and cleanup plan
bravew Oct 14, 2026
1bb2040
docs(maintenance): add LESSONS.md and track the regression plan as epics
bravew Oct 14, 2026
d182f23
docs(process): require PR verification and attribution evidence (#235)
bravew Oct 14, 2026
5f36770
ci: run quality and test jobs on every non-draft PR (#232)
bravew Oct 14, 2026
0fad805
ci: run quality and test jobs on every non-draft PR (#232)
bravew Oct 14, 2026
9b67b60
docs(process): add the weekly and pre-release maintenance review runb…
bravew Oct 14, 2026
d5ce909
docs(channels): add per-provider ownership and contract matrix (#243)
bravew Oct 14, 2026
e238ae6
docs(process): add incident records, empty blocklist schema, and poli…
bravew Oct 14, 2026
d084a8b
fix(api): resolve app-owned data through getAppDir() (#242)
bravew Oct 14, 2026
f016cd6
docs: update architecture pages from manifests, database call path, a…
bravew Oct 14, 2026
f56cc0c
test(api): prove every migration runs against its own schema (#261)
bravew Oct 14, 2026
c253fd8
refactor(video): type withVideoRefResolution so tests need no casts (…
bravew Oct 14, 2026
092816a
fix(api): make unsupported 501 routes truthful and pin V1 task route …
bravew Oct 14, 2026
331e2d8
refactor(video): extract overlay library tools from video-edit-server…
bravew Oct 14, 2026
cc7164e
merge: bring main (E1 merge gate) into epic branch
bravew Oct 15, 2026
49c5c6e
merge: bring main (E1 merge gate) into epic branch
bravew Oct 15, 2026
b8168f2
Merge remote-tracking branch 'origin/main' into merge/193-onto-main
bravew Oct 15, 2026
b1465cb
Merge remote-tracking branch 'origin/main' into merge/194-onto-main
bravew Oct 15, 2026
3c4fe79
docs(channels): fix ownership decision link fragment (#288)
bravew Oct 15, 2026
6a4cc42
fix(publish): migrate archives from the actual legacy home path (#287)
bravew Oct 15, 2026
c8bf707
Merge remote-tracking branch 'origin/epic/193-architecture-ownership'…
bravew Oct 15, 2026
1eed6f1
Merge remote-tracking branch 'origin/main' into merge/194-onto-main
bravew Oct 15, 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
59 changes: 50 additions & 9 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,56 @@
## Summary
## Intent and scope

<!-- What does this PR change, and why? -->
<!-- Complete each field. Use unknown or not applicable with a reason when evidence is unavailable. Guidance: AGENTS.md and LESSONS.md at the repository root. -->

## Test plan
Intent and resulting behavior:

<!-- How did you verify this? Include commands run and their results. -->
Affected contracts and consumers:

- [ ] `pnpm validate`
- [ ] `pnpm test:fast`
- [ ] Manually tested in the app (describe the flow)
## Verification evidence

## Related issues
Exact checked commit SHA:

<!-- Closes #123 -->
Node and pnpm versions:

<!-- Run the closest workspace checks and pnpm validate. Record each command, its outcome, and relevant failures. pnpm validate is not a test suite. Recheck after changing the head; skipped or cancelled checks are not passes. -->

| Command or check | Outcome and evidence |
| --- | --- |
| `pnpm validate` | |
| Closest changed-surface check | |

Regression evidence:

<!-- For behavior changes, name the failing scenario and the test at the actual caller boundary, with before/after results. For documentation-only changes, record link, command, source, and rendering checks instead. Explain any missing regression coverage. -->

Unverified cases and skipped checks, with reasons:

## Attribution

Accountable contributor:

Authoring tool/configuration, if known (otherwise `unknown`):

Session reference, if known (otherwise `unknown`):

<!-- Use an opaque reference. Keep private session URLs and identifiers out of public PR text. Product names in code or titles are not authorship evidence. -->

## Corrective change

<!-- Complete for a corrective PR; otherwise write not applicable. Attribute an introducing change only when proven. -->

Original finding link:

Introducing PR or commit, with causal evidence (or `unknown`):

Reproducible failing scenario:

Review/check gap that let it escape:

Prevention test or check and its result:

## Related issue

<!-- Close the implemented sub-issue, not its parent epic. Replace N below. -->

Closes #N
153 changes: 153 additions & 0 deletions doc/maintenance/2026-10-14-weekly-dry-run/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Weekly maintenance review, 2026-10-14

Dry run of the process in [review-process.md](../review-process.md), produced
against this worktree's checked head. It exercises the report format and records
real check output. It is not a scheduled run; no recurring job exists.

Owner: unassigned. The owner field is defined in
[review-process.md](../review-process.md#cadence-and-owner). This dry run was
produced by an implementing agent, and assigning the recurring owner is a
maintainer decision tracked in [#199](https://github.com/bravew/Neumar/issues/199).
Reviewer: implementing agent for #230.
Head: `d182f23f27100a18066d5804f2ec4f774f41dd98` (`issue/230-weekly-maintenance-review`,
rebased onto `origin/epic/194-maintenance-process`).
Node and pnpm: Node v26.11.1, pnpm 11.22.0. The Node baseline CI uses is 22; see
Unverified.
Previous report: none. This is the first run, so every trend is a baseline.

## Comparability with the earlier review

The earlier review was measured at `c0926618`. This head differs from it only in
tracked documentation: `git diff --stat c0926618 HEAD -- src src-api packages`
is empty, so the source, API, and shared-package trees are byte-identical. The
warning counts, allowlist entries, suppression counts, orphan candidates, and
migration files below are therefore directly comparable to the baseline. No
product behavior changed between the two heads.

## Check outcomes

Every command below was run in this worktree on the head above. The exit code and
counts are the real output.

| Command | Result | Notes |
| --- | --- | --- |
| `pnpm validate` | Pass, exit 0 | Emitted 453 frontend lint warnings and 0 lint errors. All sub-checks passed: brand, critique-i18n, locale parity, design-system flags, design media catalog, uuid routing, ag-ui version (0.0.59 lockstep), plugin registry (226 entries), HyperFrames skill, FFmpeg skill (2.4.2, 42 tools), HyperFrames upgrade check, frontend and API typecheck, root and API format, component size (897 files scanned, 68 allowlisted). The HyperFrames upgrade check reports an available update 0.8.80 to 0.8.155 and changed no files. |
| `pnpm test:fast` | Fail, exit 1 | Frontend: 399 files, 1776 tests, all passed. API: 2 failed, 593 passed, 3 skipped files; 2 failed, 3859 passed, 7 skipped tests. Both failures are detailed below. |
| `pnpm --filter neumar-api lint` | Pass, exit 0 | 10 warnings, 0 errors. |
| `pnpm --filter neumar-api exec tsc -p tsconfig.json --noEmit` | Pass, exit 0 | Includes API test files. |
| `pnpm lint` (frontend) | Pass, exit 0 | 453 warnings, 0 errors. |
| `cargo check --manifest-path src-tauri/Cargo.toml --locked` | Fail, exit 101 | Failed in the `neumar` build script because the sidecar resource `src-api/dist/neumar-api-aarch64-apple-darwin` does not exist. This is a missing build artifact, not a source defect; see Unverified. |

### `pnpm test:fast` failures

1. `test/unit/agent-runtimes/resolve.test.ts` line 251, "resolves
npm-installed OpenCode through the shared extended PATH". This is the known
test-isolation failure tracked in [#195](https://github.com/bravew/Neumar/issues/195)
and named in [LESSONS.md](../../../LESSONS.md). The resolver finds the host's
Homebrew OpenCode before the temporary npm fixture. It reproduces on this host
because Homebrew OpenCode is installed.
2. `test/unit/plugins/loader.test.ts`, "invalidates loader generation when
watched skill files change". The failure is `Error: Hook timed out in
30000ms` in the file's `afterEach`, which tears down the plugin hot-reload
watcher. Re-running the file alone passed: 7 tests passed in 22.00s. This is a
load-sensitive timing failure under the full parallel run, not a reproduction
in isolation. It is a new observation with no tracking issue, and it is
selected for a bounded cleanup pull request below. It is not the `#195`
failure and should not be reported as one.

## Findings

Severity follows the earlier review: P0 urgent containment, P1 fix before
expanding the affected feature, P2 planned cleanup. A finding carried from the
earlier review names its source review and commit.

| ID | Surface | Finding | Evidence | Owner | Status |
| --- | --- | --- | --- | --- | --- |
| W1 | New warnings and suppressions | The frontend warning baseline is unchanged at 453, but 28 `eslint-disable-next-line` directives exist under `src/`, of which 25 suppress `react-hooks/exhaustive-deps`. API code adds 71 more, and 5 `@ts-expect-error` directives exist. No new suppression was introduced in this window. | `pnpm lint`, `grep -rn eslint-disable-next-line src/` | unassigned | Open, carried from the 2026-10-13 review |
| C1 | Size ceilings | The allowlist still holds 68 entries and no ceiling changed in this window. Nine entries are obsolete: the file is at or below the 350-line default, so the allowance is unnecessary. | `scripts/component-size-allowlist.json`; `node scripts/check-component-size.mjs` | unassigned | Open, carried from the 2026-10-13 review; tracked in [#217](https://github.com/bravew/Neumar/issues/217) |
| O1 | Orphan candidates | Four API modules named in the earlier review remain present with no importer found by exact-path search: `extensions/mcp/sandbox-server.ts`, `core/config/hierarchy.ts`, `shared/services/pipeline/cli-dispatch.ts`, `shared/services/video-analysis.ts`. This run confirmed the absence of importers, not their removal. | `grep -rn` for each path under `src-api/src` | unassigned | Open, carried from the 2026-10-13 review; tracked in [#218](https://github.com/bravew/Neumar/issues/218) |
| U1 | Unsupported surfaces | The chat plugin apply route returns 501, and the memory extract and consolidate routes return 501. All three messages are truthful and direct callers elsewhere. Both `/task/:taskId` and `/task-v2/:taskId` remain mounted, and both settings shells remain live. No change in this window. | `src-api/src/app/api/plugins.ts:330`, `src-api/src/app/api/memory.ts:497`, `:524`, `src/app/router.tsx:57,65` | unassigned | Open, carried from the 2026-10-13 review; tracked in [#223](https://github.com/bravew/Neumar/issues/223) |
| M1 | Migrations | The migrations directory holds 60 files: 58 numbered migrations plus `runner.ts` and `utils.ts`. None changed in this window. The migration-drift finding from the earlier review is unchanged and still needs the full-registry run against fresh, current, and drifted snapshots. | `git diff c0926618 HEAD -- src-api/src/shared/db` is empty | unassigned | Open, carried from the 2026-10-13 review; tracked in [#225](https://github.com/bravew/Neumar/issues/225) |
| S1 | Security | The P0 daemon binding finding is unchanged and unfixed. The default listener still omits `hostname`, and privileged routes are reachable without JWT unless `WEBUI_AUTH=true`. | `src-api/src/http-daemon.ts:478`, `src-api/src/app/middleware/jwt.ts:12`, `src-api/src/app/api/sandbox.ts:179` | unassigned | Open, carried from the 2026-10-13 review; tracked in [#200](https://github.com/bravew/Neumar/issues/200) |
| S2-S9 | Security | The remaining security findings S2 through S9 are unchanged. The source trees are identical to the reviewed baseline, so none has been fixed. | [01-findings.md](../2026-10-13-regression/01-findings.md) | unassigned | Open, carried from the 2026-10-13 review; tracked in [#201](https://github.com/bravew/Neumar/issues/201) to [#207](https://github.com/bravew/Neumar/issues/207) |
| R1-R6 | Unresolved regressions | All six regressions from the earlier review are unchanged. R6 (the `resolve.test.ts` isolation bug) reproduced in this run. | `pnpm test:fast`; [01-findings.md](../2026-10-13-regression/01-findings.md) | unassigned | Open, carried from the 2026-10-13 review; tracked in [#211](https://github.com/bravew/Neumar/issues/211) to [#216](https://github.com/bravew/Neumar/issues/216) and [#195](https://github.com/bravew/Neumar/issues/195) |
| T1 | Unresolved regression (new) | The plugin loader test times out under the full parallel run and passes alone. This is a load-sensitive timing assumption a user meets on a busy machine, and it is the class [LESSONS.md](../../../LESSONS.md) calls out. | `pnpm test:fast` (2 failed), isolated `pnpm test:api test/unit/plugins/loader.test.ts` (7 passed, 22.00s) | unassigned | New, observed in this run |
| E1 | Expired exceptions | No exception registry exists yet. Exceptions are named in the earlier review's findings, but none carries an owner, a reason, and an expiry in a machine-readable place, so none can be listed as expired. | [review-process.md](../review-process.md#review-scope) surface 8 | unassigned | New, observed in this run |

## Metrics

The previous column is the value the 2026-10-13 review recorded, carried from
[README.md](../2026-10-13-regression/README.md) and
[03-lessons-and-contributors.md](../2026-10-13-regression/03-lessons-and-contributors.md).
This run is the baseline for the metrics the earlier review did not record.

| Metric | This run | Previous | Trend |
| --- | ---: | ---: | --- |
| Escaped regressions introduced since the last report | 1 (T1, new) | 6 (R1 to R6) | Baseline. R1 to R6 predate this run and are not counted again. |
| Time to repair, escaped regressions closed since the last report | Not applicable, none closed | R6 introduced `83c425bb`, still open | Baseline. R6 has been open since the initial snapshot. |
| Required-check execution on merged heads | Not measured. No merges in the window, and the CI job conditions were read rather than exercised. | 77 of 84 merged PRs never ran the automatic quality and test jobs | Unchanged by this run. The `quality` and `test` jobs in `.github/workflows/ci.yml` still require a `release/` or `release-v` head or a manual dispatch. |
| Unresolved P0 findings | 1 (S1) | 1 (S1) | No change. |
| Unresolved P1 findings | 9 (S2, S3, S4, S5, S6, S7, S9, R1, R3) | same set | No change. Source trees are identical to the baseline. |
| Expired exceptions | 0, because no registry exists | not recorded | Baseline. |

Deletion count is not a metric and is not recorded.

## Cleanup selected

These are the bounded cleanup pull requests this run selects. Each names one
finding and the check that will show the change. None is started by this report.

| Scope | Finding | Closing check |
| --- | --- | --- |
| Isolate the plugin hot-reload teardown in `src-api/test/unit/plugins/loader.test.ts` so the watcher closes within the hook timeout, and assert the watcher stops deterministically instead of relying on a 30s hook budget. | T1 | `pnpm test:api test/unit/plugins/loader.test.ts` passes, and `pnpm test:fast` shows no hook timeout. |
| Remove the nine obsolete allowlist entries whose files already fit the 350-line default. | C1 | `pnpm check:component-size` passes with 59 allowlisted entries. |
| Remove one proven API orphan, starting with the smallest, after an exact-path caller search across the workspaces and the CLI and plugin entry points. | O1 | `pnpm --filter neumar-api lint`, API typecheck, and the affected API tests pass. |

The other findings are carried, not selected this run. S1 remains the highest
priority and is already tracked in [#200](https://github.com/bravew/Neumar/issues/200).

## LESSONS.md

No change. This run found no failure pattern that is not already a lesson. The
two failures it observed map to existing rules: the `resolve.test.ts` failure is
the "test isolation: stub the seam, not the environment" lesson, and the plugin
loader timeout is the "a red under load is a timing assumption a user will meet
on a busy machine" clause of the "when a check fails in your area, fix it or file
it" lesson. Neither adds a new pattern, so neither "Seen" count is incremented
here; incrementing requires a review day, and this is a dry run.

The promoted lesson, seen on three review days and moved to
[AGENTS.md](../../../AGENTS.md), is the same process the runbook defines. This dry
run is the first review day for the new process itself, so nothing is promoted
yet.

## Unverified

- **Node 22 baseline.** This run used Node v26.11.1, the same local runner the
earlier review used. CI uses Node 22. The `resolve.test.ts` and plugin loader
failures were not reproduced under Node 22.
- **`cargo check`.** The command failed in the Tauri build script because the
sidecar resource `src-api/dist/neumar-api-aarch64-apple-darwin` is absent. The
Rust source was not checked. Producing that artifact needs the API binary build
step, which was not run. This is not evidence of a Rust defect.
- **Browser end-to-end tests.** `pnpm test:e2e:browser` was not run. It starts its
own API and a browser, and no browser scenario was in scope for a
documentation change.
- **Gate evals.** `pnpm test:gate` was not run. It needs `EVALS_TIER=gate` and
the eval fixtures, and no eval surface changed.
- **Live providers and packaged desktop.** No provider credentials were used and
no packaged build was produced, so no live-provider or desktop behavior is
verified.
- **Required-check execution on merged heads.** Read from
`.github/workflows/ci.yml` job conditions, not exercised against a pull request
in this window. The metric is carried from the earlier review, not re-measured.
- **Exception registry.** No machine-readable exception registry exists, so the
expired-exception metric cannot be measured beyond "none recorded".
- **Link check.** Every relative link in the runbook and this report was resolved
against the checkout by hand; no automated link checker was run.

## Scheduling

Scheduling the review is a separate maintainer decision and is not live. No
workflow, cron, or external job runs this process. This report is a manual dry
run.
43 changes: 43 additions & 0 deletions doc/maintenance/incidents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Contributor policy records

Date: 2026-10-14. This directory holds the records that the contributor quality
policy in
[03-lessons-and-contributors.md](../2026-10-13-regression/03-lessons-and-contributors.md)
asks for: the incident record template, the empty blocklist, and the replay of
the thresholds against the documented historical cases.

The policy starts without names. No contributor, vendor, model family, or agent
session is identified here, and the blocklist is empty.

| File | Purpose |
| --- | --- |
| [incident-record-template.md](incident-record-template.md) | Blameless incident record format |
| [blocklist.json](blocklist.json) | Empty blocklist with the entry schema |
| [blocklist-schema.mjs](blocklist-schema.mjs) | Schema constants and validation, shared by the check and its tests |
| [fixtures/blocklist-valid.json](fixtures/blocklist-valid.json) | A valid entry used only to exercise the schema |
| [fixtures/blocklist-invalid.json](fixtures/blocklist-invalid.json) | An entry missing a required field, used only to exercise rejection |
| [policy-replay.md](policy-replay.md) | Each documented historical case placed against the thresholds |

## Rules this directory follows

- An incident record names the contract that failed and the gate that missed it.
It does not judge a person. The practice is blameless postmortem
([Google SRE](https://sre.google/sre-book/postmortem-culture/)).
- A record counts only after two reviewers or a maintainer with an independent
verification artifact confirm it.
- The blocklist stays empty until the policy's own evidence bar is met and a
maintainer records a decision. Each entry must carry evidence, affected scope,
effective date, expiry, remediation, and an appeal link.
- A block applies to a demonstrated contributor or tool configuration. It is not
a blacklist of a vendor or a model family.

## Checks

```bash
node doc/maintenance/incidents/check-blocklist.mjs doc/maintenance/incidents/blocklist.json
node --test doc/maintenance/incidents/check-blocklist.test.mjs
```

The first command validates the committed blocklist. The test runs the same
validator against both fixtures and asserts the valid entry is accepted and the
entry missing a required field is rejected.
Loading
Loading