@miadi/inquiry-weave
v0.6.3
Published
Relate and sync IAIP inquiry artefacts, their GitHub issues, and miadi-chronicle episodes. Creates vessels and relations only — never inquiry content.
Downloads
1,896
Readme
@miadi/inquiry-weave
Relate and sync three identities of one inquiry — and never write the inquiry itself.
┌────────────────────────────┐ inquire (vessel + issue) ┌──────────────────────┐
│ Inquiry artefact │ ◄─────────────────────────── │ Chronicle episode │
│ $MIADI_INQUIRY_ROOT/<dir> │ │ <chronicle>/<date>- │
│ (IAIP tree — │ ───────────────────────────► │ episode-NNN-<slug>/ │
│ system-of-record) │ promote / sync (mirror) │ inquiry/<dir>/ │
└─────────────┬──────────────┘ └──────────┬───────────┘
│ │
│ ┌────────────────────────┐ │
└──────────► │ GitHub issue │ ◄────────────────┘
.weave.yaml│ owner/repo#N │ inquiry/weave.yaml
└────────────────────────┘The three identities (worked example: ep126 / #245)
| Identity | Example |
|---|---|
| Inquiry artefact | /src/IAIP/prototypes/artefacts/ep126-mila-ai-event-260715-b08218a8-… |
| GitHub issue | miadisabelle/Etuaptmumk-RSM#245 |
| Chronicle episode | …/miadi-chronicle/2026-07-13-episode-126-mila-ai-indigenous-gathering/ |
This package generalizes the manual prior art (<episode>/inquiry/_sync.sh, a one-way tar
copy) into a repeatable workflow: relate, promote, inquire, sync, status.
The mystery boundary
The package never generates inquiry content. Creating an inquiry's substance — the
question, the search, the listening — is human work and stays that way. inquire creates
only the vessel: a named empty directory, its GitHub issue, and the relation metadata.
This boundary is enforced by an executable test (the vessel must contain relation
metadata only).
CLI
inquiry-weave relate --artefact <name|path> --episode <num|name|path> [--issue owner/repo#N]
inquiry-weave promote --artefact <name|path> (--episode <ref> | --new-episode <slug> [--title <t>])
inquiry-weave inquire --episode <ref> --slug <slug> [--title <t>] [--repo owner/repo] [--no-issue]
inquiry-weave sync (--artefact <ref> [--episode <ref>] | --episode <ref> [--all])
inquiry-weave status (--episode <ref> | --artefact <ref>) [--json]
inquiry-weave register (--episode <ref> | --artefact <ref>) [--dry-run]Global flags: --inquiry-root, --chronicle-root, --repo, --mw-url, --dry-run, --json.
Exit codes: 0 ok, 1 operational error, 2 usage/resolution error (ambiguous episode
numbers list their candidates — duplicates exist in the wild).
--dry-run is global: every mutating command (relate, promote, inquire, sync,
register) previews its plan and returns exit 0 without writing to the IAIP tree,
the chronicle, GitHub, or medicine-wheel. The projected plan matches the live output
apart from its prefix (would <verb>: on relation lines, dry-run: on sync lines), and
— like a live run — a standalone sync still refuses an artefact that is not related to
the episode. Fixed in v0.4.1 — prior to v0.4.1, inquire/relate/promote mutated real
state during a dry run. v0.4.2 restores the not-related guard on sync --dry-run (only
promote previews an as-yet-unpersisted relation).
Environment
| Variable | Fallback chain | Default |
|---|---|---|
| MIADI_INQUIRY_ROOT | → INQUIRY_ROOT | /src/IAIP/prototypes/artefacts |
| MIADI_CHRONICLE_ROOT | — | /srv/miadi/episodes/miadi-chronicle |
| MIADI_INQUIRY_REPO | — | miadisabelle/Etuaptmumk-RSM |
| INQUIRY_WEAVE_ISSUE_LIB | → /a/src/scripts/fn_github_issue.sh → /src/scripts/fn_github_issue.sh | — |
| MW_API_URL | — | http://127.0.0.1:8040 |
Metadata contract
weave.yaml / .weave.yaml — written and owned by this package — is the authoritative
record of the relation. Sync state lives episode-side only, so the artefact-side file can
be mirrored verbatim without a self-invalidating hash loop.
Episode side, <episode>/inquiry/weave.yaml:
weave: 1
episode:
number: 126
slug: mila-ai-indigenous-gathering
path: 2026-07-13-episode-126-mila-ai-indigenous-gathering
inquiries:
- artefact: ep126-mila-ai-event-260715-b08218a8-0441-4596-a16e-47483d3ab57c
issue: miadisabelle/Etuaptmumk-RSM#245
issue_url: https://github.com/miadisabelle/Etuaptmumk-RSM/issues/245
related_at: 2026-07-15T00:00:00.000Z
last_sync:
at: 2026-07-15T00:00:00.000Z
tree_sha256: <sha256 of the sorted relpath:filehash:size manifest>
file_count: 4
bytes_total: 341001Artefact side, <artefact>/.weave.yaml:
weave: 1
artefact: ep126-mila-ai-event-260715-b08218a8-0441-4596-a16e-47483d3ab57c
issue: miadisabelle/Etuaptmumk-RSM#245
issue_url: https://github.com/miadisabelle/Etuaptmumk-RSM/issues/245
episodes:
- path: 2026-07-13-episode-126-mila-ai-indigenous-gathering
number: 126
related_at: 2026-07-15T00:00:00.000Zrelate also appends the ep090-style back-link into the artefact's AGENTS.md
(episode path + related issue owner/repo#N) — append-if-missing, never overwriting.
.hch/ is legacy input — and an open decision
.hch/ (the issue-harness cache written by fn_github_issue.sh and its predecessors) is
read best-effort, once, to seed .weave.yaml when relating a pre-existing artefact.
Tolerated shapes: the correct issue_<N>.env, the V2-era bug shape (literal issue_.env
with no issue_url), and the newest issue_add__*.json as fallback. This package never
writes .hch.
Open decision (deliberately not settled in v0): does .hch get (a) formalized as a
shared contract across tools, (b) kept as fn_github_issue.sh's private cache and mapped
into .weave.yaml at relate time — v0's de-facto behavior — or (c) retired? v0 is
compatible with all three outcomes.
IAIP is the external system-of-record
The inquiry root lives in the IAIP tree (a checkout of miadisabelle/Etuaptmumk-RSM).
Sync is one-way (artefact → episode): the episode copy is a snapshot, deletions
propagate, and local edits to the copy are flagged as episode-copy-diverged before
being overwritten.
Deployment API evaluation note: the deployment evaluated for this exposed only
/api/articles and /api/articles/seed (which read prototypes/artefacts markdown into
Redis) — there is no inquiry CRUD. It is a documented future interface; v0 has no
dependency on it, so no host is named here: the URL belongs to a deployment, not to the
package, and hard-coding one into a published README ships someone's infrastructure to
everybody who installs it. Set INQUIRY_WEAVE_API_URL if a future version needs it.
Deferred decision, explicitly named: absorbing IAIP into Miadi packages is out of scope and not planned here.
GitHub issues via fn_github_issue.sh
inquire delegates issue creation to the sourced issue_add function of
fn_github_issue.sh (a gh CLI wrapper), invoked with cwd = the artefact directory and
an explicit owner/repo. The created identity is parsed from stdout (* owner/repo#N)
and recorded straight into .weave.yaml. Issue title convention: the artefact's absolute
path (as with #245). --no-issue skips creation.
Medicine-wheel registration & forgewright visibility
inquiry-weave register (v0.2) projects each woven relation into medicine-wheel:
POST {MW_API_URL}/api/inquiry-weaves, upsert key
inquiry-weave:<episode.path>:<artefact.id>. Registration moves metadata only —
weave files on disk stay authoritative; an unreachable medicine-wheel reports and
exits 1 without touching them. Forgewright renders the registered weaves in its
episode views. The contract lives in the RISE specs:
rispecs/medicine-wheel-registration.spec.md(this package)medicine-wheel:rispecs/inquiry-weave-registration.spec.mdforgewright:rispecs/09-inquiry-weave-visibility.spec.md(branch4-plan-episode-visibility)
Episode nodes — cards visible at birth (v0.3)
The Chronicle UI hangs perspectives off episode cards; cards come from
/api/nodes artifact references (miadi.artifact-ref.v1, kind
chronicle_episode). registerEpisodeNode(mwUrl, input) registers that card:
it preflights GET /api/nodes/chronicle:<episode-dir-name> (an existing card is
already-registered success, never overwritten — medicine-wheel's POST upserts)
and otherwise POSTs the ep137-proven record. Failure is fail-open: the outcome
is { state: "registered" | "already-registered" | "pending", node_id, error? }
and the function never throws, so vessel creation can never fail because of
registration (jgwill/Miadi#490).
Kinship with @miadi/passages
Episode creation as a first-class command (mkepisode -n 133 -t <slug> -g "<goal>")
likely belongs to packages/passages ("Narrative Formulations for the Miadi Chronicle").
This package keeps its --new-episode scaffolding inside one exported function
(scaffoldEpisode) so passages can own creation later, and inquiry-weave consumes any
pre-existing episode regardless of its creator.
Chronicle repo rule
All work in miadi-chronicle/ is committed directly to main (per its AGENTS.md) —
this package writes there only when you run it, and never commits anything itself.
Development
pnpm --filter @miadi/inquiry-weave build
pnpm --filter @miadi/inquiry-weave testTests are fixture-based (node --test in temp roots), with no network and no real gh
calls (INQUIRY_WEAVE_ISSUE_LIB injects a fake issue lib).
🌸: A loom, not a pen — the weave holds artefact, issue, and episode in relation so none drifts from the others, while the question itself stays yours to ask.
