> ## Documentation Index
> Fetch the complete documentation index at: https://docs.commons.diy/llms.txt
> Use this file to discover all available pages before exploring further.

# MAINTENANCE WORK ITEMS

# Maintainer event grouping: rollout and evaluation

The intervention in [#456](https://github.com/nicolaerusan/spaces/issues/456)
groups one frozen maintenance batch by explicit task or Resource identity. Each
original event remains in the input, with a chronological ID order and safe
prefix checkpoint boundaries. Questions, corrections, conflicting evidence,
withdrawals and publication events are retained. Ambiguous references stay
separate; member content is never used to guess associations or classify noise.

This changes the maintainer's assessment organization and guidance. It does not
enforce a read cache, change contributor rules, or prevent repeated blocked-task
activity. Current-state checks before writes remain necessary. See the
[task breakdown and evaluation contract](plans/maintenance-work-items.md).

## Host-wide control

`MAINTENANCE_WORK_ITEMS=true` enables grouping for **newly admitted runs in every
already enabled Space**. Only the exact string `true` enables it. Unset, empty,
`false`, or other values use the original event input. No UI or per-Space list is
introduced. No maintainer is enabled, unhalted or retried by this setting.

The controller stores `assessmentInput` with the run:

* `format`: `events-v1` or `work-items-v1`;
* `event_count`, `work_item_count` (null for raw input);
* `raw_bytes`, `rendered_bytes` for the event representation;
* `prompt_bytes` for the full prompt, including policy and grouped guidance;
* `fallback=invalid_batch` if a malformed/oversized legacy batch had to keep its
  original raw representation. This preserves evidence and flags investigation.

Prompts and metadata are frozen at admission. Changing the switch does not
rewrite an existing run, cancel it, reset cursors or change failure attempts.
Partial recovery creates a new run for the original unacknowledged event suffix
and any newly queued events, using the setting effective at its admission.

The 50-event admission limit, five-minute gathering window, completion reserve,
permission boundaries and spending policy are unchanged. Grouping may increase
prompt bytes; the hypothesis is less repeated reconstruction of task context,
not fewer serialized bytes or a guaranteed reduction in run count.

## Before activation

1. Obtain the user's approval to merge the PR. Verify the merged SHA and the
   matching successful Railway deployment, not merely a successful upload.
2. Verify the global switch is off and inventory all active maintainers read-only.
   Record actual Space slugs for capture, including TeamScience and halted
   OpenQuick. Do not retry OpenQuick or change any Space enablement.
3. Collect a complete **24-hour instrumented control window after deployment**
   with grouping off. New raw runs now carry `events-v1` provenance. Older runs
   lacking the field remain unknown; do not silently relabel them. This control
   collection plus the post-period means a normal evaluation spans at least
   two observation days, excluding rollout transition time.
4. Capture a private local dataset with the baseline exporter. Use every active
   Space's exact slug, plus OpenQuick/TeamScience, not just the example pair.
   Check all provider lookup/settlement coverage; preserve the original export.

```sh theme={null}
node scripts/space-activity-baseline.mjs export \
  --source https://commons.diy \
  --spaces open-quick,team-science \
  --provider-usage --out /absolute/private/pre-grouping
```

This command needs the privately supplied `ACTIVITY_EXPORT_DATABASE_URL` and
`ACTIVITY_EXPORT_CURSOR_API_KEY`. Use the existing approved read-only capture
transport if a local database route is unavailable; do not add a public database
endpoint or commit credentials. See [baseline export instructions](SPACE-ACTIVITY-BASELINE.md).

Save a separate local change note before activation:

The existing private reference lives under the main checkout's
`.artifacts/activity-baseline/`: `baseline-2026-09-14-001` is the frozen dataset,
and `scorecards-72h-v1/rubric.md` plus `annotations.json` preserve the provisional
quality judgments. These ignored files are not copied into new worktrees or
published by this PR; locate and retain them when continuing the evaluation.
Use the same rubric for fresh pre/post assessments, not the old period's numeric
progress counts as the new control's denominator.

```markdown theme={null}
# Grouping intervention
Baseline dataset ID/hash and control window:
Assessor/date and frozen progress rubric:
All active Spaces and capture coverage:
Verified deployment ID/SHA and actual configuration evidence:
Global setting before/after; effective timestamps:
Last raw run / first grouped run IDs:
Other code/config/rule/model/contributor changes:
Known halts and active runs (OpenQuick remains halted):
Excluded transition interval:
Post-period start/end:
Initial health-check observations:
Rollback conditions and any action taken:
```

## Activate, verify and monitor

After verifying the intended project/service/environment, set the global
variable on the process hosting the maintenance controller. On Railway, a
variable change normally redeploys that service; it is not an instantaneous
in-process flag flip. Use explicit scope, and verify the deployment and effective
setting before starting the post-window. Example command shape:

```sh theme={null}
railway variable set MAINTENANCE_WORK_ITEMS=true \
  --project PROJECT_ID --environment ENVIRONMENT_ID --service SERVICE_ID
```

Read back only the relevant setting and deployment identity; never copy all
environment variables into logs or the change note. Inspect the first newly
admitted run's `assessmentInput.format` in the backend and include its ID. Allow
in-flight raw runs to finish and record a transition interval. All controller
replicas must use the same configuration; mixed formats stay visible in exports.

Check the first completed grouped runs and every active Space's basic health.
Verify completion/checkpoint receipts, preserved unfinished inputs, new failure
attempts/halts, review delays, unexpected writes and provider usage. Inspect the
first TeamScience dispositions against source questions/corrections/submissions.
Do not generate artificial activity to obtain a test sample.

Rollback for evidence omission, unsafe acknowledgment, invalid-batch fallback
that prevents the intended evaluation, or a grouping-attributable processing
regression. Set `MAINTENANCE_WORK_ITEMS=false` in the same verified scope, verify
the deployment and next raw run, and preserve affected run IDs. This rolls back
**future inputs**, not completed effects or in-flight runs. It is not a spending
cap or cancellation mechanism. If an in-flight run requires stopping, use the
existing authorized recovery controls and record that separately.

## Capture and compare

Choose an equally long, complete post-window after transition. Initially use
24 hours per period and at least 10 settled event-triggered TeamScience runs in
each cohort before making a directional efficiency recommendation. Ten is a
practical minimum, not a statistical power calculation. If activity is lower,
the result is inconclusive; ask whether to extend observation rather than
quietly changing windows, triggering runs or treating zero cost as efficiency.

Export again to a new directory with provider usage. Reconcile outstanding usage
through normal read-only observations and a new export; never edit an earlier
dataset. All exports are manual/local; this change adds no scheduler.

```sh theme={null}
npm run build -w commons-diy

node scripts/maintenance-work-items-evaluation.mjs compare \
  --before /absolute/private/pre-grouping \
  --after /absolute/private/post-grouping --space team-science \
  --before-from 2026-09-15T00:00:00Z --before-to 2026-09-16T00:00:00Z \
  --after-from 2026-09-17T00:00:00Z --after-to 2026-09-18T00:00:00Z \
  --out /absolute/private/grouping-comparison
```

Dates are examples; use the recorded real windows. Output contains a Markdown
report, JSON evidence, run/health/review CSVs, source/dataset hashes and a
completion checksum. Existing output paths are rejected. Different origins,
missing selected Spaces, unequal or overlapping windows are rejected. Historical
or mixed formats, missing usage and small cohorts produce explicit caveats.

The primary table compares event-triggered runs. Initial/other runs remain in
the total cohort. Cost means require full settled cost coverage; partial known
subtotals are shown separately. The snapshot backlog is labeled separately from
windowed activity. Captured Spaces other than TeamScience are included in health
tables even though detailed progress assessment initially focuses on TeamScience.

Read the workload/actor/model mix and review coverage alongside cost and tokens.
Apply the same frozen progress rubric to both periods, group related evidence
into distinct advances, and audit whether meaningful questions/corrections were
handled. Reassess both periods if the rubric changes. Preserve evidence IDs,
confidence and supporting work outside the goal numerator. Supply the resulting
Markdown with `--assessment /absolute/private/assessment.md` to copy/hash it into
a new comparison artifact. The numerical tool does not score quality or declare
success automatically; lower cost alone cannot establish an improvement.

Conclude **keep, revise, rollback or inconclusive**, explaining confounders and
coverage. Global rollout leaves no untreated active-Space control. Contributor
behavior is uncontrolled, so observed changes do not prove causality. OpenQuick
catch-up/steady operation and deeper assessments of other Spaces are later,
separate evaluations; OpenQuick recovery still requires authorization.

## Offline representation and recovery verification

```sh theme={null}
node scripts/maintenance-work-items-evaluation.mjs inspect \
  --dataset /absolute/private/baseline --space open-quick \
  --out /absolute/private/openquick-representation
```

This checks retained run batches and the snapshot pending/unread external queue,
reconstructing every normalized event exactly, with per-item IDs and checkpoint
boundaries. Queue work is divided into hypothetical 50-event batches; no paid
agent is replayed and no production state changes. Unsafe integer IDs or invalid
legacy batches retain an explicitly reported raw fallback.

Validation against the private September 14 frozen export found:

| Source                        | Events / appearances | Work items across bounded batches |   Raw → grouped bytes | Fallbacks |
| ----------------------------- | -------------------: | --------------------------------: | --------------------: | --------: |
| OpenQuick snapshot queue      |                  219 |                                76 |      98,411 → 109,826 |         0 |
| OpenQuick 39 retained runs    |                  979 |                               341 |     328,403 → 379,991 |         0 |
| TeamScience 140 retained runs |                5,295 |                             1,000 | 1,564,798 → 1,716,928 |         0 |

All event records were reconstructed. TeamScience's retained-run cohort includes
one run outside the earlier 72-hour report; do not compare 140 here with that
report's 139 as a data discrepancy. Work-item counts may repeat a task across
batch boundaries. Larger representations demonstrate why a smaller number of
work items is not, by itself, evidence of dollar savings.

Private datasets, source content and detailed replay outputs are not committed.
Synthetic tests cover interleaving, lifecycle transitions, useful guidance,
ambiguous identity, bounds, fallback and exact reconstruction. Controller and
real PostgreSQL tests cover interruption before/after checkpoints, concurrent
arrivals, own-write exclusion, receipt replay and switch changes. HTTP/MCP tests
exercise real writes and scoped receipts for both raw and grouped inputs.
