Skip to content
Merged
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
101 changes: 101 additions & 0 deletions 1-formats/deed/mappings/ai-manifest-decision.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: CC-BY-SA-4.0
= Decision spec — `0-AI-MANIFEST.a2ml` → deed era (family 7)
Campaign: standards#837 · Frame: link:README.adoc[mappings/README] ·
Status: **DECISION REQUIRED (owner)** — raised by the first live
conformance finding of the wave (marid, verified 2026-09-19): a
*renamed-not-translated* `0-AI-MANIFEST.deed` carrying INI content already
exists in the wild. Renames are not translations; this spec exists so the
wave converts ~900 generated files instead of ~900 ad-hoc moves.

== 0. Naming collision (wave rule #1: do not conflate)

**`0.2-AI-MANIFEST.a2ml` (cartridge directory-manifests) is a DIFFERENT
family.** Found during recon: `1-formats/sub-specs/cartridges/`
and `docs/wikis/0.2-AI-MANIFEST.a2ml` carry YAML-ish `key: value`
directory-manifest content (boJ cartridge system, governed by
`cartridge-v1.json` schema) — unrelated to the per-repo agent-allocation
file. The wave must match on the agent-allocation *content shape*, never
on the filename alone. Sub-family separation recorded here; cartridge
manifests get their own spec when their registry moment comes (linked to
the #732 rename batch, not this campaign).

== 1. Source surface (family 7 proper)

`<repo>/0-AI-MANIFEST.a2ml` at repo root — generated, ~900 estate copies
per the #646 audit note. Instance norm (marid, 2026-09-18 vintage):

[cols="1,3"]
|===
| Section | Content

| `[metadata]` | `version`, `last-updated` (strings)
| `[project]` | `name`, `purpose` (strings)
| `[ai-allocation]` | `agents` = array of `{ name, role }` (the estate's agent-identity table: CLAUDE / CHATGPT / GEMINI / VIBE …)
| `[policy]` | `rules` = array of prose-rule strings
| `[work-allocation]` | `items` = array of `{ agent, task }`
|===

== 2. The options on the table

**A. `(manifest …)` clauses on the repo deed (RECOMMENDED).** AI-MANIFEST
content is *repo state*: who is allocated here, under what policy. The
one-deed-per-repo doctrine already lands AGENTIC/PLAYBOOK here; the
allocation manifest is the same epistemic kind. Fields map cleanly with
zero invented grammar.

**B. `*_praxis.deed`.** Rules-shaped? The policy rules are *prose*, not
machine rules — no `:when`/`:then`, no precedent for `:priority`
proration; forcing them into praxis invents exactly the field shapes the
grammar's provisional-note forbids. Recorded and rejected; not asked for.

== 3. Field table (option A; translator refuses anything else — P-2a)

[cols="2,3,4"]
|===
| a2ml surface | deed path | transform / type

| `[metadata] version` / `last-updated` | `(manifest :version "…" :last-updated "…")` | verbatim STRINGs
| `[project] name` | `(manifest :project "Marid")` | verbatim STRING — cross-checked against deed `:canonical-name` (P-6 analogue; mismatch fails closed: catches a manifest read into the wrong repo)
| `[project] purpose` | `(manifest :purpose "…")` | verbatim STRING
| `[ai-allocation] agents[]` | one clause per entry: `(agent :name CLAUDE :role "…")` | `name` → SYMBOL (agent identities ARE identifiers — estate greps depend on the literal symbol; closed seen-set extended by ruling, never silently), `role` → STRING verbatim
| `[policy] rules[]` | `(policy (rules ("rule text" "rule text")))` | list of STRINGs — order is semantic here, and *list order is preserved by the grammar* (a list is a value, unlike clause order); no invented rule-ids
| `[work-allocation]` items[] | `(work :agent GEMINI :task "…")` per entry | agent → SYMBOL (same identity table as `:name`s above; agent in items[] but not in agents[] fails closed — allocation without a declared identity), task → STRING
|===

== 4. Must-preserve + wave rules (the hazard table)

1. **No renames. Only translations.** A `.deed` file contains a deed. The
marid `0-AI-MANIFEST.deed` class (INI content, `.deed` name, root
location, no dispatch pattern) fails on three independent counts —
the whole-tree deed-lint CI gate (already in standards'
`deed-conformance.yml;` wave repos inherit it) is what kills this class
on contact, not review-eyeballs.
2. **Agent-identity table verbatim.** `:name CLAUDE` etc. are estate-wide
greppable constants; any fourth-name propagation anomaly is flagged
(P-9 analogue).
3. **The no-duplicate-tasks invariant** rides as a policy rule text
verbatim; translators dedupe nothing, interpreters dedupe nothing —
the text itself is the contract.
4. **Generator-first for the wave.** ~900 files are *generated*: convert
the generator's emit surface BEFORE the files (the #645 lesson: fix at
source, then re-propagate). The 6a2/A2ML generator home is an
owner-information dependency (same hunt as #646's, now with a deed-era
destination).

== 5. Acceptance (once ruled)

* Zero `0-AI-MANIFEST.deed` files containing `=` as a field separator
exist estate-wide (the in-the-wild rename class: zero).
* Every converted repo's deed carries `(manifest …)` with agent symbol
counts matching its old a2ml arrays one-for-one.
* `grep -rn ":name CLAUDE\b" --include='*_chora.deed'` reproduces the
pre-wave allocation table byte-for-meaning.

== 6. Ruling asks

. Option A confirm (or an alternative home — with reasons, so the next
family spec inherits the principle).
. Whether the agent *seen-set* is closed-and-ruled (CLAUDE/CHATGPT/
GEMINI/VIBE) or open-with-review — translator default without an answer:
open + flag-any-unknown (fails captured, not blocked).
. Generator location/home for the wave's source-fix step (owner-info).
Loading