Skip to content

MIP-0076 tasks

Ordered delivery of MIP-0076 as stacked PRs (/marola-devkit:mip-tasks, stack). Branch mip-0076/<k>-<slug> in the repo the row lands in; rows of one repo stack on that repo's previous row, and merge bottom-up with stack restack after each squash-merge. Each row's delivers cell starts with the repo its PR lands in (MIP-0070's spelling, read by tasks-to-issues). §n are the MIP's; "the MIP's tests" are its §7 names. A devkit bump moves the flake input, every @v…/devkit-ref: in .github/workflows/ and the marketplace ref in .claude/settings.json together. Every row that touches README.md or docs/** ends with docs-lint green, which gates every repo, so a page names just wiring or just graph only from the row that bumps that repo to the tag shipping the recipe.

# slug delivers tests (must exist before the PR) depends on
1 wiring-extract marola-devkit — §5.1's extractor without the gate: scripts/wiring.py (stdlib + PyYAML; ps.pyyaml added to the flake's python), wiring in tools, a wiring *args recipe in devkit.just. Reads .gitmodules, the devkit's tree under .devkit, every repo's workflows, pin files, and the scripts, justfiles, Dockerfiles, docker-compose*.yml and build.sbt naming a pin or image (Decision 2); branch artifacts (api-docs, site-data) as well as release assets and images (Decision 1); a workflow step that opens a PR in or pushes to another marola-dev repo (Decision 3). If the row passes ~400 lines, extraction and rendering split into two PRs. Renders the four tables between the wiring:start/wiring:end markers of a given file; each reusable-workflow call shows its ref. docs/4-reference_tools.md row wiring --self-test (in tests/self-tests.sh, Decision 6) with the MIP's dispatch_types_listened, dispatch_send_step, reusable_workflow_ref_and_event_type, release_upload_assets, image_publish, deploy_pages_site, pin_file_and_reader, plus branch_artifact_api_docs, branch_artifact_site_data, compose_image_reader, cross_repo_pr (marola-ml's compile-prompt.yml), cross_repo_push (a fixture ingest workflow pushing to marola-oods). nix flake check. A run over a fresh --recurse-submodules umbrella clone, its block pasted in the PR –
2 wiring-check marola-devkit — wiring --check: regenerates the block and fails on any difference, on a dispatch type listened for but never sent or sent but never listened for, and on an artifact with no reader unless wiring.allow (at the umbrella root, Decision 4) lists it with a one-line reason wiring --self-test adds check_fails_on_stale_block, check_fails_on_orphan_dispatch, check_fails_on_unread_artifact, allow_entry_needs_reason. Run over today's umbrella clone: fails on submodule-updated only (output in the PR) 1
3 notify-every-push marola-devkit — §5.5 step 1's half for notify-umbrella.yml: sends submodule-updated on every call, and also submodule-docs-updated when git diff --name-only over the pushed range (github.event.before..github.sha, a zero or unreachable before counted as a docs change) touches README.md or docs/**; the event-type input goes; the header's caller snippet loses paths:. docs/4-reference_workflows.md's row actionlint. One call from a scratch repo at this branch: a code-only push sends only submodule-updated, a docs push sends both, a first push sends both (run links in the PR) –
4 devkit-wiring-release marola-devkit — CHANGELOG.md entry and the flake's version; human: tag the next minor (v0.5.0 at the time of writing) just quality green. nix flake check. nix run github:marola-dev/marola-devkit/<tag>#wiring -- --self-test from outside the repo 1, 2, 3
5 wiring-block marola — devkit bumped to row 4's tag; just wiring replaces the hand-written table between the markers in docs/2-Building-marola/REPOS.md, the compiled-prompt PRs included (Decision 3); wiring.allow with its entries; the page says the block is generated and by what. Not yet gated A second just wiring leaves no diff. Every fact of the old hand-written table is in the block, nothing hand-written after wiring:end (list in the PR). scripts/agents_repos_check.sh, docs-lint and just docs green 4
6 app-notify marola-app — devkit bumped to row 4's tag; paths: dropped from the notify-umbrella.yml caller (§5.5 step 3) just quality and actionlint green. After merge, the push's notify run logs dispatched submodule-updated and pointer-sync runs on repository_dispatch (run links) 4
7 site-notify marola-site — devkit bumped to row 4's tag; paths: dropped from the notify-umbrella.yml caller (§5.5 step 3). From v0.3.1, so v0.4.x's changes come along (the devkit's CHANGELOG.md) just quality and actionlint green. After merge, the push's notify run logs dispatched submodule-updated and pointer-sync runs on repository_dispatch (run links) 4
8 corpus-notify marola-corpus — devkit bumped to row 4's tag; paths: dropped from the notify-umbrella.yml caller (§5.5 step 3) just quality and actionlint green. After merge, the push's notify run logs dispatched submodule-updated and pointer-sync runs on repository_dispatch (run links) 4
9 ml-notify marola-ml — devkit bumped to row 4's tag; paths: dropped from the notify-umbrella.yml caller (§5.5 step 3) just quality and actionlint green. After merge, the push's notify run logs dispatched submodule-updated and pointer-sync runs on repository_dispatch (run links) 4
10 oods-notify marola-oods — devkit bumped to row 4's tag; paths: dropped from the notify-umbrella.yml caller (§5.5 step 3). After marola-dev/marola-oods#7 (v0.3.0 → v0.4.1) merges, or in its place if it has not just quality and actionlint green. After merge, the push's notify run logs dispatched submodule-updated and pointer-sync runs on repository_dispatch (run links) 4
11 pointer-sync-wiring marola — §5.4: pointer-sync.sh regenerates the wiring block in the commit that moves the pointers; pointer-sync.yml gets Nix (installer and cache) so wiring is on PATH, and its stale comment on submodule-updated goes pointer-sync.sh --self-test adds wiring_block_regenerated_with_pointers (a fake wiring on PATH: the pointer commit carries the block change) and no_block_change_no_commit. actionlint. A workflow_dispatch run's sync PR (link) 5
12 graph-tool marola-devkit — §5.2: scripts/graph.sh as graph, pkgs.graphify (nixpkgs 0.9.66) in runtimeDeps, a graph *args recipe. build runs extract . --code-only --no-label then update . with GRAPHIFY_OUT under ${XDG_CACHE_HOME:-$HOME/.cache}/marola-graph/<repo> and build.json (HEAD, git submodule status); every call under env -i with §5.2's five variables, and unshare -rn when it can (a notice when not); query defaults to --budget 400; query/path/explain pass --graph and print a staleness line. docs/4-reference_tools.md row graph --self-test with a fake graphify recording argv and environment: the MIP's env_scrubbed, no_auto_refresh_set, refuses_extract_without_code_only, output_outside_checkout, uninitialised_submodule_fails, stale_notice_on_new_head, query_default_budget_400. nix flake check 4
13 routing-skill marola-devkit — §5.3: plugins/marola-devkit/skills/routing/SKILL.md, the four routing rules and nothing else; docs/4-reference_plugin.md row claude plugin validate .. The skill names only just graph, never bare graphify, and only the umbrella's REPOS.md and its docs.marola.dev page for wiring (grep in the PR) 12
14 devkit-graph-release marola-devkit — CHANGELOG.md entry and the flake's version; human: tag the next minor (v0.6.0 at the time of writing). The code repos take it with their next routine bump (Decision 5) just quality green. nix flake check. nix run github:marola-dev/marola-devkit/<tag>#graph -- --self-test from outside the repo 12, 13
15 wiring-gate marola — §5.4: quality-other runs wiring --check; the CI quality-other job checks out submodules and gets wiring from the devkit shell; CI-CD.md, NEW-REPO.md and DOCS-SITE.md say notify-umbrella runs on every push and submodule-updated is sent. Only after a pointer-sync PR has moved all five submodules past rows 6–10, so no allow entry covers submodule-updated §7 "CI": quality-other red on a test branch adding an unread pin and on one adding an unsent dispatch type, green on this branch (run links). just quality green 6, 7, 8, 9, 10, 11
16 graph-umbrella marola — devkit bumped to row 14's tag; .graphifyignore (**/vendor/**, the non-canonical board.schema.json); §5.4's AGENTS.md paragraph in "The repos", naming the wiring block, just graph and the routing skill, and no pin file §7 "Live": the 8 questions on a fresh --recurse-submodules clone by the skill's rule, at least 7 of 8 right first, 0 tokens in graphify's report footer (table in the PR). agents_repos_check.sh, agents-check, docs-lint green 14, 15
17 graph-ci marola — §5.4's graph job in ci.yml: path-filtered to the submodule gitlinks and flake.lock, just graph build on the PR's pinned commits, graph.json and build.json uploaded with 7-day retention; nothing committed or deployed actionlint. A run on this PR uploads the artifact, and its log says whether unshare -rn worked on ubuntu-latest (§8's open item; run link) 16
18 mip-implemented marola — MIP-0076 flipped to Implemented with every PR number and the summed Cost: mip_graph.py --check. wiring --check green on main, and row 16's re-test linked 5, 11, 15, 16, 17

Decisions

Stale claims first: the MIP is accepted, so it stays as written and these rows follow today's code (checked 2026-10-04 on every repo's main and devkit v0.4.1).

  1. The API docs are a branch, not a release asset. §5.1 and §11 name api-docs.tar.gz as a wiring.allow entry. MIP-0074 retired that asset (its tasks 35 and 36): marola-ml has no release.yml, and marola-app's attaches only ml-resources-<tag>.tar.gz. Each repo's api-docs branch is now pushed by the devkit's reusable api-docs.yml, and site-data by app workflows and the umbrella's site-data-push.sh. §5.1's source table has no rule for a branch artifact, so row 1 adds one. If fetch-api-docs.sh's <repo> template still defeats the reader rule, the allow entry names the api-docs branch instead of the tarball.
  2. The ml image has a reader. §5.1 says no workflow or script reads ghcr.io/marola-dev/marola-ml; marola-app's docker-compose.yml:54 runs it as ollama-local in the local profile. Compose files are not among §4's reader sources, so row 1 adds docker-compose*.yml image: lines, and the allow entry is then not needed. The maintainer's decision to keep the image is unaffected, and the maintainer confirmed dropping the allow entry (2026-10-05). REPOS.md's "Nothing yet" for it is stale too, and row 5 replaces it.
  3. Cross-repo writes are parsed too (maintainer, 2026-10-05). MIP-0074 task 27 wrote one hand-written table of ten rows inside the markers; §5.1 plans four generated tables, and two of today's facts are neither pins nor dispatches: the compiled-prompt PRs (a gh pr create against marola-app in marola-ml's compile-prompt.yml) and the OODS ingest (an app workflow pushing to marola-oods, arriving with MIP-0056). Row 1's extractor recognises a workflow step that opens a PR in, or pushes to, another marola-dev repo, so both stay inside the generated block and nothing is hand-written after it.
  4. wiring.allow lives at the umbrella root: the extractor runs there, and the facts it excepts are org-wide. The MIP leaves the location open.
  5. Two devkit releases, one consumer bump. §5.5 releases after step 1 and after step 2, and step 3 bumps each code repo. The code repos bump to row 4's tag, which carries the notify-umbrella change they need; row 14's graph and skill reach them with their next routine bump ("every repo gets it with its next devkit bump", §5.2). Only the umbrella takes row 14's tag in this MIP (maintainer, 2026-10-05).
  6. Self-tests, not pytest. §7 says "pytest with fixture repos"; the devkit has no pytest on its PATH, and every tool there is tested as <tool> --self-test from tests/self-tests.sh. Rows 1, 2 and 12 keep §7's case names under that convention.
  7. The umbrella's CI needs more than §5.4 says. Its quality-other job checks out without submodules and takes its tools from nix develop .#lint, and pointer-sync.yml has no Nix at all. Rows 11 and 15 add both.
  8. The gap is still there, at newer refs. On 2026-10-04 every code repo's notify-umbrella.yml keeps paths: [README.md, "docs/**"] and no event-type, at @v0.4.1 (app, corpus, ml), @v0.3.1 (site) and @v0.3.0 (oods), not the Appendix's @v0.2.4. graphify is still 0.9.66 at the devkit's locked nixpkgs (b4fd65b). The "one-line change in five repos" of the Effort row is a full devkit bump in each, two of them across v0.4.x.

Ordering: the extractor goes first because a run over the real workspace (row 1's last test) is what can still change the block's shape. Row 15 waits on all five consumer rows and a pointer-sync merge because wiring --check reads the pinned commits: it passes only once every pinned caller really sends submodule-updated.