Context
Sub-A of Epic #11319 (Trigger-Aware Workflows graduation from Discussion #11314). Implements the lint/schema primitive — the mechanical-enforcement substrate that future migration sub-tickets (Sub-B onwards) consume.
Strictly bounded scope: schema extension + lint logic + /create-skill discipline update. NO workflow migrations in this ticket. Migration is Sub-B+ lane.
Per Discussion #11314 §8 graduation target + @neo-gpt body-repair #4: lint/schema primitive PR ≠ workflow-migration PR. Migration blast-radius bounded one-skill-per-PR.
The Fix
Schema extension (skills.manifest.schema.json + skills.manifest.json)
Add per-skill field:
perFilePayloadBudget: positive integer (bytes); per-individual-file byte ceiling within references/. Calibrated empirical-floor per skill + 10-15% headroom. Optional with default null (no per-file enforcement) for v1 backwards-compat.
Add section-trigger declaration parser support. Canonical syntax per Discussion #11314 OQ1:
<h2 class="neo-h2" data-record-id="5">§<N> <Section Title></h2>
<!-- trigger: [condition] → read [sub-rule.md] -->
Lint logic extension (ai/scripts/lint-skill-manifest.mjs)
- Per-file payload byte check: walk
references/<file>.md; if wc -c exceeds perFilePayloadBudget (when set) → fail with extraction recommendation
- Section-trigger parse: regex
/^<!-- trigger: (.+?) → read (.+?\.md) -->$/m against post-header lines; build per-section index {anchor, trigger, sub_rule_path, body_size_bytes}
- Trigger-frequency × size heuristic: section with
body_size_bytes > 5_000 AND declared trigger matches rare-trigger pattern (heuristic: trigger string contains "openapi", "audit", "edge-case", "deprecation", etc. — extensible via manifest config) → flag as extraction candidate with Required-Action template
- Required-Action template:
"<skill>/references/<file>.md § is <size> bytes with declared trigger <trigger> (rare-firing class). Extract to sub-rule sibling file behind one-line trigger pointer per skill-authoring-guide.md §Map vs World Atlas. Reduce workflow body to: section header + <!-- trigger: ... --> pointer line."
/create-skill discipline update (skill-authoring-guide.md)
Append new subsection after existing §"Map vs World Atlas Constraint Placement":
- Recursive application rule (workflow files apply Map vs Atlas at section level)
- Canonical section-trigger syntax + example
- Cross-reference to lint enforcement:
lint-skill-manifest.mjs --base origin/dev will flag rare-trigger sections exceeding threshold
.github/workflows/skill-manifest-lint.yml
No structural change needed — workflow already invokes lint on .agents/skills/** PR changes. Extended lint behavior auto-fires.
Contract Ledger Matrix (per Epic #11319 inheritance)
| Target Surface |
Source of Authority |
Behavior |
Evidence |
.agents/skills/skills.manifest.schema.json |
This sub-ticket |
Add perFilePayloadBudget field schema; add section-trigger declaration support |
Schema documented inline |
.agents/skills/skills.manifest.json |
This sub-ticket |
Populate perFilePayloadBudget per-skill (calibrated empirical floor + 10-15% headroom; null where N/A for v1) |
Per-skill calibration table in PR body |
ai/scripts/lint-skill-manifest.mjs |
This sub-ticket |
Extend with per-file byte check + section-trigger parser + frequency × size heuristic |
Lint output validation in PR diff |
.agents/skills/create-skill/references/skill-authoring-guide.md |
This sub-ticket |
Append recursive-application subsection + canonical syntax + lint cross-ref |
/create-skill discipline cross-link |
Acceptance Criteria
Out of Scope (explicit)
- Workflow migrations (Sub-B onwards) — atlas-monolith file extractions
- AGENTS.md byte audit
assets//scripts/ folder audit
- Load-profile cross-skill aggregate budget
- KB ingestion (#11316 Epic lane)
- Reactive watcher / auto-sync on file changes (per Discussion #11314 OQ1 default + Option D rejection)
Avoided Traps
- Folding migration into this PR — bundled scope re-introduces blast-radius blur; one-skill-per-PR discipline preserves it
- Per-section metadata required on EVERY section — narrower framing: only sections that DO declare a trigger get parsed; sections without trigger comments are unaffected (zero metadata bloat on always-relevant sections)
- Hard byte threshold without trigger awareness — Option B rejection from Discussion #11314 §4; threshold + trigger-frequency combined is the load-bearing logic
- Substrate accretion (
AGENTS.md §13 + pull-request-workflow.md §1.1): Sub-A PR adds substrate (schema field + lint logic + ~20 lines to skill-authoring-guide.md). Net-expansion justified per slot-rationale: high-frequency × high-severity × machine-enforceable = keep slot for the schema field; compress-to-trigger default doesn't apply for v1 schema addition (no rule-body in always-loaded substrate; all enforcement is lint-script-internal). PR body documents slot-rationale per pull-request-workflow.md §1.1
Related
- Parent Epic: #11319
- Graduating Discussion: #11314
- Sibling Epic (KB ingestion): Gemini's #11316 graduation Epic (forthcoming; couples via
isAtlasMonolithSubRule metadata)
- Predecessor: #11275 / PR #11278 (aggregate
payloadBudget shipped; this extends to per-file)
- Lint script:
ai/scripts/lint-skill-manifest.mjs
- Test fixture:
test/playwright/unit/ai/scripts/lintSkillManifest.spec.mjs
- Empirical anchor files (post-Sub-A lint output):
pr-review-guide.md (57,388 B / 45 sections), pull-request-workflow.md (33,463 B)
Context
Sub-A of Epic #11319 (Trigger-Aware Workflows graduation from Discussion #11314). Implements the lint/schema primitive — the mechanical-enforcement substrate that future migration sub-tickets (Sub-B onwards) consume.
Strictly bounded scope: schema extension + lint logic +
/create-skilldiscipline update. NO workflow migrations in this ticket. Migration is Sub-B+ lane.Per Discussion #11314 §8 graduation target + @neo-gpt body-repair #4: lint/schema primitive PR ≠ workflow-migration PR. Migration blast-radius bounded one-skill-per-PR.
The Fix
Schema extension (
skills.manifest.schema.json+skills.manifest.json)Add per-skill field:
perFilePayloadBudget: positive integer (bytes); per-individual-file byte ceiling withinreferences/. Calibrated empirical-floor per skill + 10-15% headroom. Optional with defaultnull(no per-file enforcement) for v1 backwards-compat.Add section-trigger declaration parser support. Canonical syntax per Discussion #11314 OQ1:
<h2 class="neo-h2" data-record-id="5">§<N> <Section Title></h2> <!-- trigger: [condition] → read [sub-rule.md] -->Lint logic extension (
ai/scripts/lint-skill-manifest.mjs)references/<file>.md; ifwc -cexceedsperFilePayloadBudget(when set) → fail with extraction recommendation/^<!-- trigger: (.+?) → read (.+?\.md) -->$/magainst post-header lines; build per-section index{anchor, trigger, sub_rule_path, body_size_bytes}body_size_bytes > 5_000AND declaredtriggermatches rare-trigger pattern (heuristic: trigger string contains "openapi", "audit", "edge-case", "deprecation", etc. — extensible via manifest config) → flag as extraction candidate with Required-Action template/create-skilldiscipline update (skill-authoring-guide.md)Append new subsection after existing §"Map vs World Atlas Constraint Placement":
lint-skill-manifest.mjs --base origin/devwill flag rare-trigger sections exceeding threshold.github/workflows/skill-manifest-lint.ymlNo structural change needed — workflow already invokes lint on
.agents/skills/**PR changes. Extended lint behavior auto-fires.Contract Ledger Matrix (per Epic #11319 inheritance)
.agents/skills/skills.manifest.schema.jsonperFilePayloadBudgetfield schema; add section-trigger declaration support.agents/skills/skills.manifest.jsonperFilePayloadBudgetper-skill (calibrated empirical floor + 10-15% headroom; null where N/A for v1)ai/scripts/lint-skill-manifest.mjs.agents/skills/create-skill/references/skill-authoring-guide.md/create-skilldiscipline cross-linkAcceptance Criteria
skills.manifest.schema.jsonincludesperFilePayloadBudgetper-skill entry (positive integer; nullable for v1 opt-in)skills.manifest.jsonper-skill entries setperFilePayloadBudgetcalibrated empirically (PR body documents the calibration table)references/<file>.mdper skill. Per-file byte check fires whenperFilePayloadBudgetis set<!-- trigger: ... -->HTML comments; parser indexes section anchor + trigger string + sub-rule path + body size/create-skilldiscipline update.skill-authoring-guide.mdappended with recursive-application subsection + canonical syntax + lint cross-refpr-review-guide.mdorpull-request-workflow.mdbody changesperFilePayloadBudgetfield still pass (field is optional v1)test/playwright/unit/ai/scripts/lintSkillManifest.spec.mjsfor: section-trigger parser happy path, frequency × size heuristic fire, per-file byte threshold fire, backwards-compat null-fieldepic-reviewgatekeeper. Request/epic-reviewupon Sub-A PR openOut of Scope (explicit)
assets//scripts/folder auditAvoided Traps
AGENTS.md §13+pull-request-workflow.md §1.1): Sub-A PR adds substrate (schema field + lint logic + ~20 lines toskill-authoring-guide.md). Net-expansion justified per slot-rationale: high-frequency × high-severity × machine-enforceable =keepslot for the schema field;compress-to-triggerdefault doesn't apply for v1 schema addition (no rule-body in always-loaded substrate; all enforcement is lint-script-internal). PR body documents slot-rationale perpull-request-workflow.md §1.1Related
isAtlasMonolithSubRulemetadata)payloadBudgetshipped; this extends to per-file)ai/scripts/lint-skill-manifest.mjstest/playwright/unit/ai/scripts/lintSkillManifest.spec.mjspr-review-guide.md(57,388 B / 45 sections),pull-request-workflow.md(33,463 B)