mirror of
https://github.com/EveryInc/compound-engineering-plugin.git
synced 2026-09-19 01:09:55 +08:00
cc0743fbb2
Restructure the always-loaded body from 25,865 to 7,993 CRLF-adjusted bytes (under Codex's 8,000-byte Agent Plugins prompt bound) by relocating the context-gathering table and branch/PR-state resolution, the commit and push mechanics, the composition gates, and the apply routes plus the babysit handoff mechanics into references the body names at the step that needs them. Relocation was verbatim. The body keeps what must fire without a read: the ask-tool rule, the three modes and the pipeline modifier, the stack opt-in gate, the argv/snapshot/ unknown-vs-empty rules from Context, `<root>` resolution with the parity block, the never-`git add -A` and `exclude:` bounds, the read mandates, and the completion gate that makes the run not-done until ce-babysit-pr owns the PR. Contract tests split by load-time accordingly. Claude-Session: https://claude.ai/code/session_01VKhf7iAsmem2ARmutqBzQS
87 lines
3.6 KiB
TypeScript
87 lines
3.6 KiB
TypeScript
import { readFile, access } from "fs/promises"
|
|
import path from "path"
|
|
import { describe, expect, test } from "bun:test"
|
|
|
|
const REPO_ROOT = path.join(import.meta.dir, "..")
|
|
const FIXTURE = path.join(REPO_ROOT, "tests", "fixtures", "ce-config-layers-rule.md")
|
|
|
|
// Ordinary-key cascade is byte-duplicated into every independent reader
|
|
// (skills cannot import siblings). Canonical text lives once in the fixture.
|
|
const CONSUMERS = [
|
|
"skills/ce-plan/SKILL.md",
|
|
"skills/ce-brainstorm/SKILL.md",
|
|
"skills/ce-ideate/SKILL.md",
|
|
"skills/ce-product-pulse/SKILL.md",
|
|
"skills/ce-sweep/SKILL.md",
|
|
// ce-commit-push-pr resolves the ordinary keys at Step 4, in the reference
|
|
// the body mandates before composition.
|
|
"skills/ce-commit-push-pr/references/compose.md",
|
|
"skills/ce-work/SKILL.md",
|
|
"skills/ce-promote/references/spiral-cli.md",
|
|
"skills/ce-code-review/references/cross-model-review.md",
|
|
"skills/ce-doc-review/references/cross-model-review.md",
|
|
]
|
|
|
|
const START = "<!-- ce-config-layers:start -->"
|
|
const END = "<!-- ce-config-layers:end -->"
|
|
|
|
async function canonicalBlock(): Promise<string> {
|
|
const fixture = await readFile(FIXTURE, "utf8")
|
|
const start = fixture.indexOf(START)
|
|
const end = fixture.indexOf(END)
|
|
expect(start).toBeGreaterThanOrEqual(0)
|
|
expect(end).toBeGreaterThan(start)
|
|
return fixture.slice(start, end + END.length)
|
|
}
|
|
|
|
describe("config-layers rule shared-asset parity", () => {
|
|
test("the fixture defines a single delimited block", async () => {
|
|
const block = await canonicalBlock()
|
|
expect(block.startsWith(START)).toBe(true)
|
|
expect(block.endsWith(END)).toBe(true)
|
|
const fixture = await readFile(FIXTURE, "utf8")
|
|
expect(fixture.split(START).length).toBe(2)
|
|
expect(fixture.split(END).length).toBe(2)
|
|
})
|
|
|
|
test("every independent reader contains the canonical block verbatim", async () => {
|
|
const block = await canonicalBlock()
|
|
for (const rel of CONSUMERS) {
|
|
const p = path.join(REPO_ROOT, rel)
|
|
await access(p)
|
|
const content = await readFile(p, "utf8")
|
|
expect(content, `${rel} is missing the config-layers block`).toContain(block)
|
|
}
|
|
})
|
|
|
|
test("the canonical block pins its load-bearing clauses", async () => {
|
|
const block = await canonicalBlock()
|
|
expect(block).toContain("config.local.yaml")
|
|
expect(block).toContain("config.yaml")
|
|
expect(block).toContain("Gitignore does not change resolution")
|
|
expect(block).toContain("invalid value continues to the next layer")
|
|
expect(block).toContain("including an empty list or map")
|
|
expect(block).toContain("Do not** use this rule for `docs_root`")
|
|
})
|
|
|
|
test("cross-model peer resolution continues past an invalid local scalar", async () => {
|
|
for (const rel of [
|
|
"skills/ce-code-review/references/cross-model-review.md",
|
|
"skills/ce-doc-review/references/cross-model-review.md",
|
|
]) {
|
|
const content = await readFile(path.join(REPO_ROOT, rel), "utf8")
|
|
expect(content, rel).toContain("invalid value continues to the next layer")
|
|
expect(content, rel).not.toContain("first active value wins")
|
|
}
|
|
})
|
|
|
|
test("pulse and sweep first-run on key-unset, not file-missing", async () => {
|
|
const pulse = await readFile(path.join(REPO_ROOT, "skills/ce-product-pulse/SKILL.md"), "utf8")
|
|
const sweep = await readFile(path.join(REPO_ROOT, "skills/ce-sweep/SKILL.md"), "utf8")
|
|
expect(pulse).toContain("`pulse_product_name` is unset after cascade")
|
|
expect(pulse).not.toContain("or config file missing")
|
|
expect(sweep).toContain("`feedback_sources` unset after cascade")
|
|
expect(sweep).not.toContain("Config file missing")
|
|
})
|
|
})
|