Skip to content

feat(packs): compound, ground, and enforce domain knowledge via Compound Packs - #1549

Draft
kieranklaassen wants to merge 26 commits into
mainfrom
feat/ce-packs-v0
Draft

feat(packs): compound, ground, and enforce domain knowledge via Compound Packs#1549
kieranklaassen wants to merge 26 commits into
mainfrom
feat/ce-packs-v0

Conversation

@kieranklaassen

@kieranklaassen kieranklaassen commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

A repo can teach the whole Compound Engineering pipeline its own domain rules by declaring them: a packs: list in CE config names each knowledge source — a repo-relative folder, a ~/absolute path, or a git URL pinned to a tag, sha, or branch (with path: subfolder scoping; pasted GitHub …/tree/<ref>/<sub> URLs work as-is) — and selects one pack, several, or everything the source publishes. Compound Packs then flow through every stage: planning grounds in matching rules (ce-brainstorm, ce-plan), review enforces them (ce-code-review flags violating diffs, ce-doc-review flags contradicting plan text), and capture recognizes them/ce-compound detects when an insight is already prescribed by a pack rule instead of re-capturing it, and can route a prescriptive, cross-repo capture straight into a writable pack (or scaffold one) with the learning-to-rule rewrite. Every influence is cited: (pack: <id>, <path within the pack>).

The loop this closes: solve → capture → promote → declare → ground → enforce → recognize. config.local.yaml adds personal packs on top of the team list without replacing it. With no packs: key, behavior is byte-identical to today. Packs add zero entries to the skill roster — they are knowledge ingested into existing steps, not new skills. A pack-bearing plugin is just a git URL; a marketplace is just a catalog of URLs. Full guide with authoring examples: docs/skills/packs.md. Plan: docs/plans/2026-08-26-001-feat-ce-packs-config-sources-plan.md. Supersedes the closed convention-folder attempt (#1546).

Design decisions

  • A pack is data, not a callable — and not a skill. Markdown rules with title + situational applies_when frontmatter; matching is semantic per consuming stage, so stage-scoping is phrasing, not a schema field. A pack can carry arbitrary in-pack resources (subdirectories are invisible to discovery, reachable only through a rule that cites them) — big data rides along at zero context cost.
  • One resolver, six byte-identical copies (ce-plan, ce-brainstorm, ce-setup, ce-code-review, ce-doc-review, ce-compound; parity-tested like peer-job-runner.py). Strict YAML-subset parser with loud per-line errors, per-kind ref rules, tree-URL sugar, atomic ownership-checked caching under the CE scratch root, non-interactive git, JSON-always output.
  • Review and capture reuse the planning seam. Code review adds resolved roots to its existing learnings pass (local-tree reviews only); doc review passes packs through a {pack_constraints} template slot; compound's Related Docs Finder records pack_overlap and the assembly step gates the pack-covered and destination-routing decisions (interactive-only writes; non-interactive stays deterministic; git-sourced packs never written).
  • Reproducibility by construction: refs required, tags/shas exact, branches frozen per cache lifetime with drift surfaced by /ce-setup's Compound Packs health section.
  • Hardened against hostile config and sources (review-driven): --end-of-options + leading-dash guard, cache owner/symlink verification on create and reuse, path: containment, bounded non-interactive git, no submodule recursion, JSON-always failure mode, evidence-not-instructions at every consumer.

Validation

  • bun run test: 3,690 pass, 0 fail — 34 resolver cases (AE1–AE7, parser strictness, cache/ownership/option-injection, sha refs, tilde, CRLF, zero-indent, six-way parity), 3 check-health fixtures, and contract guards for every consuming stage including compound. release:validate + plugin:validate green.
  • Planning spot-check: config → resolver → researcher found the rule via applies_when, emitted the exact citation, and refused an injected instruction embedded in a pack body.
  • Review spot-check: a diff adding /api/invoices for a page's own data was flagged against no-parallel-json-api.md via both applies_when clauses, with the exact citation.
  • Code review (8 lenses): 17 findings, all applied — headlined by a git option-injection P0, the cache ownership gap, and a zero-indent packs: parse bug. Cross-model Codex pass attempted; skipped (peer CLI failed locally, no schema-shaped output).

Known residuals

Informational: tree-URL sugar can't disambiguate branch names containing / (warning points at explicit ref:/path:); frontmatter blocks over 4KB disqualify a file silently; the drift note needs reachable remotes; kebab-case ids documented, not enforced. Deferred by design: provider protocols, auto-update, per-pack pinning within a source, conflict detection, the git-pack upstream-commit flow for compound routing.

Post-Deploy Monitoring & Validation

No production/runtime infrastructure impact — bundled script, skill prose, tests, docs. Watch issue reports for: packs mentioned with no packs: key (R11 regression), hangs attributable to git fetches (should be impossible: non-interactive env + timeout), or resolver tracebacks (should be impossible: JSON-always guard).

Security Disclosure

Adds a script that fetches remote git repositories named in repo-committed config and parses user-authored YAML, consumed by planning, review, and capture. Mitigations shipped and tested: --end-of-options + leading-dash rejection (option injection), owner/symlink verification of the per-uid cache on create and reuse (cache poisoning), realpath containment for repo-relative sources and path: subfolders (traversal), non-interactive git with bounded timeout (credential-prompt hangs), no submodule recursion, argv-only subprocesses, pack content treated as untrusted evidence by every consumer (injection refusal exercised in the spot-check). Remote-tree reviews skip local pack resolution. Compound's pack writes are interactive-consent-only and never touch git caches. Residual: cloning URLs the repo's tracked config names is by design — a maintainer decision, like declaring a dependency.

Agent Disclosure

  • Model: Claude Code · Fable 5

Compound Engineering
Claude Code

A repo can track domain knowledge under .compound-engineering/packs/<id>/
as markdown files with applies_when frontmatter. ce-plan discovers the
packs at its research dispatch, the learnings-researcher searches them
as extra roots (reading every pack file's frontmatter rather than
grep-filtering), and pack-shaped constraints land in the plan with a
(pack: <id>, <path>) citation. ce-brainstorm's grounding scout quotes
matching pack files and the Product Contract cites them the same way.
Zero packs leaves behavior unchanged. No protocol, provider skill, or
config key — v0 of the CE Packs proposal.

Includes the plan artifact, the CE Pack glossary entry, and a greppable
contract test pinning the load-bearing tokens.
Supersedes the convention-folder v0 (PR #1546, closed): packs are now
declared in a packs: config list (repo path, ~ path, or git URL pinned
to a tag/sha/branch, with path:/tree-URL subfolder support), read from
both config layers additively. Plan is implementation-ready; the v0
consumption machinery on this branch is the base.
Turns the packs: config lists (config.yaml + config.local.yaml,
concatenated) into resolved pack roots: path and ref-pinned git sources,
GitHub tree-URL sugar, pack selection, id overrides, duplicate-id
errors, atomic cached clones under the CE scratch root, and
non-interactive git so missing credentials warn instead of hanging.
Byte-identical copies in ce-plan, ce-brainstorm, and ce-setup; 23 unit
tests cover AE1-AE7 plus parser strictness and cache reuse.
…rounding

ce-plan's Pack discovery and ce-brainstorm's grounding scout now run
packs-resolve.py and consume its roots; the researcher's standalone
fallback probes <root>/solutions/ only. Resolver errors and warnings
surface to the user once and never enter the plan. Contract test pins
the resolver invocation and the removed convention-folder glob.
Config template gains a commented packs: example (synced to the
committed example copy); check-health gains a CE Packs section that
runs the skill-local resolver, reports each resolved pack, flags config
errors as project issues, and best-effort notes a cached branch ref
behind upstream (silently skipped offline). Resolver roots now carry
url/ref metadata for git sources so the health check never re-parses
config. configuration.md documents the declared-sources shape.
Review findings applied: --end-of-options and a leading-dash guard stop
config-supplied refs/urls reaching git as options; the cache root and
cached checkouts get the peer-job-runner ownership/symlink check;
zero-indent packs: lists parse; a single-pack git source is named from
its URL tail instead of the sha cache key; git path: is contained to
the checkout; the publish race and unexpected failures degrade to valid
JSON; empty pack: selections warn; apostrophes no longer absorb
comments; check-health probes interpreter execution (python3/python/py)
and scopes the drift note to branch refs with a full non-interactive
git env. Citations are now (pack: <id>, <path within the pack>) so
git-sourced packs cite stably. 12 new regression tests.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf606c274f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +247 to +248
warnings.append(f"{label}: cached checkout {dest} is a symlink or not owned by this user; refetching")
shutil.rmtree(dest, ignore_errors=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject cached checkout symlinks before returning

When the keyed cache path is a directory symlink, os.path.isdir(dest) succeeds and _owned_dir(dest) rejects it, but shutil.rmtree(..., ignore_errors=True) leaves the symlink in place; the later os.replace failure is swallowed and dest is returned. I reproduced the resolver emitting pack roots from the symlink target despite warning that it was refetching, so a corrupted or poisoned cache can silently substitute arbitrary pack content. Unlink or reject the entry and return only after re-verifying the published directory; all three resolver copies are affected.

AGENTS.md reference: AGENTS.md:L46-L46

Useful? React with 👍 / 👎.

Comment on lines +302 to +306
try:
names = sorted(os.listdir(directory))
except OSError:
return False
return any(n.endswith(".md") and _is_knowledge_file(os.path.join(directory, n)) for n in names)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize knowledge files below the pack root

When an immediate pack directory organizes all of its documents below a nested folder, such as packs/rails/rules/routing.md, this direct-child-only check reports that the source publishes no packs. That contradicts the documented contract that deeper nesting is pack content and makes such packs unusable unless they add an unrelated top-level Markdown file. Determine whether an immediate pack directory contains valid knowledge files recursively while continuing to treat only the source's immediate directories as pack IDs.

Useful? React with 👍 / 👎.

Comment on lines +21 to +22
PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
"$PY" "$SKILL_DIR/scripts/packs-resolve.py"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define the resolver-unavailable failure condition

When none of python3, python, or py runs, this required discovery command exits before producing the JSON assumed by the following paragraph, but neither this block nor its duplicate in ce-brainstorm states whether the caller should continue or block. Since packs are optional, different agents can now abort planning, silently omit packs, or improvise resolution. State at the calling layer that resolver unavailability is surfaced once and proceeds with zero pack roots, or explicitly define it as a blocker, and apply the same condition to both consumers.

AGENTS.md reference: AGENTS.md:L132-L136

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Agentic security review of the CE Packs resolver and config-source changes found one medium issue: pack enumeration follows child directory and knowledge-file symlinks without the realpath containment already applied to git path: and repo-relative source:. Other modules reported no qualifying API, config-injection, platform-pattern, or privacy findings.

Open in Web View Automation 

Sent by Cursor Security Agent: Security Reviewer

Comment on lines +309 to +323
def enumerate_packs(source_root: str, self_name: str | None = None) -> dict:
"""Map published pack id -> dir. Immediate children only; self = single pack."""
if _has_knowledge_files(source_root):
name = self_name or os.path.basename(os.path.abspath(source_root))
return {name: source_root}
packs = {}
try:
children = sorted(os.listdir(source_root))
except OSError:
return packs
for name in children:
child = os.path.join(source_root, name)
if os.path.isdir(child) and not name.startswith(".") and _has_knowledge_files(child):
packs[name] = child
return packs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Agentic Security Review
Severity: MEDIUM

enumerate_packs treats immediate children as pack roots using os.path.isdir / open without rejecting symlink children or requiring realpath to stay under the already-contained source_root. Git path: and repo-relative source: already apply that containment, but published pack dirs are then appended as-is.

A git pack (or a later update of a branch-pinned pack) can ship a child directory or .md symlink whose target is outside the checkout. Downstream ce-plan / ce-brainstorm consumers then read every markdown file in each returned dir, so escaped host files can enter planning context and plan/dossier artifacts. The same resolver is copied to ce-brainstorm and ce-setup.

Impact: Untrusted pack content can steer the agent to read arbitrary files the local user can open, beyond the checkout the resolver claims to contain.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit cf606c2. Configure here.

ce-code-review resolves the repo's packs before its institutional-
learnings pass (local-tree reviews only) and its researcher searches
pack roots with the same read-all-frontmatter and evidence-not-
instructions rules, so a diff violating a matching rule is flagged
with a (pack: <id>, <path within the pack>) citation. ce-doc-review
fills a {pack_constraints} template slot so document reviewers flag
plan text contradicting a matching rule. Resolver byte-copies extend
to both skills (five-way parity); plan gains U8-U10.
docs/skills/packs.md: create-your-first-pack walkthrough, applies_when
writing guidance, the full entry reference, publishing a multi-pack
repo, per-stage behavior, and a troubleshooting table. Linked from the
README docs table, the docs index, the four consuming skill pages, and
configuration.md (which stays the config-key reference).
@kieranklaassen kieranklaassen changed the title feat(ce-plan): declare CE Packs as config sources with a tested resolver feat(ce-plan): ground planning and review in config-declared CE Packs Aug 26, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a175f1887a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

**CE generic conditional local prompt assets** (`agent-native-reviewer`, `learnings-researcher`) are dispatched only when selected by Stage 3, through the same deterministic foreground batch dispatch as the structured personas. Read their prompt files from `references/personas/`, then give them the same review context bundle the personas receive: entry mode, any PR metadata gathered in Stage 1, intent summary, review base branch name when known, `BASE:` marker, file list, diff, and `UNTRACKED:` scope notes. Do not invoke them with a generic "review this" prompt. Their output is unstructured and synthesized separately in Stage 6.
**CE generic conditional local prompt assets** (`agent-native-reviewer`, `learnings-researcher`) are dispatched only when selected by Stage 3, through the same deterministic foreground batch dispatch as the structured personas. Read their prompt files from `references/personas/`, then give them the same review context bundle the personas receive: entry mode, any PR metadata gathered in Stage 1, intent summary, review base branch name when known, `BASE:` marker, file list, diff, and `UNTRACKED:` scope notes.

Before composing the `learnings-researcher` dispatch, resolve any CE Packs declared in config by running this skill's resolver as one command:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Select pack review before the learnings dispatch gate

In a local review where CE Packs apply but <root>/solutions/ is absent or has no plausible path/title match, Stage 3 never selects learnings-researcher (references/select-and-route.md:18), so this discovery block is never reached and the declared pack constraints are silently ignored. Make applicable resolved packs an independent selection condition at the routing layer rather than resolving them only after the solutions-based gate has passed.

AGENTS.md reference: AGENTS.md:L134-L136

Useful? React with 👍 / 👎.

Comment on lines +321 to +322
if os.path.isdir(child) and not name.startswith(".") and _has_knowledge_files(child):
packs[name] = child

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject pack-directory symlinks that escape the checkout

When a configured git source publishes an immediate child that is a symlink to an existing external directory containing a valid knowledge file, os.path.isdir and _has_knowledge_files both follow it and the resolver emits that symlink as a pack root. I reproduced a cloned pack returning a root whose real path was outside the cached checkout; downstream agents are then instructed to read its Markdown, allowing a third-party pack to expose guessed local files to the model. Require every published pack directory's resolved path to remain within source_root before returning it.

Useful? React with 👍 / 👎.

})

describe("ce-setup check-health pack drift note", () => {
test("notes when a cached branch ref is behind upstream", async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Give the two-run health test enough time

This test runs the complete subprocess-heavy health check twice but retains Bun's 5-second default timeout. In the targeted suite I ran, it was killed at 5008 ms before the second assertion, so the new test can fail CI independently of product behavior; set an appropriate timeout for this describe/test as required for legitimately multi-second suites.

AGENTS.md reference: AGENTS.md:L185-L185

Useful? React with 👍 / 👎.

Comment on lines +426 to +431
override = entry.get("id")
if override is not None:
if len(selected) != 1:
errors.append(f"{label}: `id:` override requires the entry to install exactly one pack")
return
selected = {str(override): next(iter(selected.values()))}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce the documented pack ID format

When id: contains spaces, slashes, Unicode, or even an empty value, the resolver converts it to a string and publishes it unchanged despite docs/skills/configuration.md:72 defining pack IDs as kebab-case ASCII. I reproduced id: "bad id/with slash" returning that exact root ID, which produces ambiguous or malformed (pack: <id>, ...) citations instead of the promised loud configuration error. Validate both overrides and directory-derived IDs against the documented format before appending roots.

Useful? React with 👍 / 👎.

…t boundary

A pack can carry arbitrary data the load script never discovers: only
top-level .md files with title+applies_when are rules; any subdirectory
(resources/, data/, docs/) is inert storage reachable solely through a
rule that cites it. Examples show the layout, the rule-as-door pattern,
and the one repo = pack + plugin shape (skills ride the plugin door;
packs: cannot register skills). Plan defers pack-extras absorption.
Health-test file gains the prescribed setDefaultTimeout against the
documented under-load flake.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38db680214

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if indent == 0 and not (in_packs and line.lstrip().startswith("-")):
# A new top-level key ends the packs block; a zero-indent list item
# (`- source: ...`) is still part of it -- YAML allows both styles.
in_packs = line.rstrip() in ("packs:", "packs: []")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject malformed values assigned to packs

When a config contains packs: nope (or another unsupported inline value), this comparison simply leaves in_packs false, so the resolver returns empty roots with no warnings or errors and /ce-setup reports "No packs configured." This silently disables declared constraints despite the resolver's contract that unsupported packs shapes are loud configuration errors; distinguish an absent key or supported packs: [] from a present malformed value and append an error in all resolver copies.

Useful? React with 👍 / 👎.


The caller may pass a **search-root list**: `<root>/solutions/` plus zero or more CE Packs, each as an `id` and an absolute directory, and optionally a list of pack files the origin document already cites. With no list, probe `<root>/solutions/` only — packs are declared in CE config and resolved by the caller, not rediscovered here. Every step below that names `<root>/solutions/` applies to each search root, except Step 2's subdirectory probe and Step 3b's critical-patterns read, which stay scoped to `<root>/solutions/`. Pack-specific rules:

- **A pack is small and prescriptive, so do not grep-filter it.** Skip the Step 3 pre-filter for a pack root: read the frontmatter of every markdown file in the pack (Step 4), then score with Step 5. Apply the Step 3 pre-filter to a pack only when it holds more than 25 files. The grep-first path for `<root>/solutions/` is unchanged.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit pack discovery to top-level Markdown

When a pack uses the documented resources/notes.md layout, "every markdown file in the pack" directs the researcher to read that nested file and then report it as malformed for lacking applies_when, although docs/skills/packs.md:156-168 promises that every subdirectory is inert, never scanned, and never warned about. Define pack candidates as top-level .md files only in this prompt and the corresponding code-review/brainstorm consumer prompts so the runtime behavior actually preserves the resource boundary.

AGENTS.md reference: AGENTS.md:L108-L110

Useful? React with 👍 / 👎.

@kieranklaassen
kieranklaassen marked this pull request as draft August 26, 2026 23:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be57400736

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +88 to +90
if not IS_WINDOWS and not _owned_dir(path):
return False
return os.path.isdir(path) and os.access(path, os.W_OK)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Repair cache roots to mode 0700

When /tmp/compound-engineering-<uid> or its ce-packs child already exists as an owned, writable directory with mode 0755 or 0777, this check accepts it without repairing its permissions. Cached private pack checkouts can therefore be exposed to other local users, and a world-writable root also lets them plant entries in the cache namespace; chmod each managed root to 0700 and verify the resulting mode before using it.

AGENTS.md reference: AGENTS.md:L46-L46

Useful? React with 👍 / 👎.

Comment on lines +27 to +32
Before dispatching, resolve any CE Packs declared in config by running this skill's resolver:

```bash
SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>";
PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
"$PY" "$SKILL_DIR/scripts/packs-resolve.py"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move pack discovery ahead of brainstorm bypasses

When a software brainstorm is Lightweight, or its opening already has clear requirements, phase-0.md:47-59 skips Phase 1.1, so this resolver block never runs and declared prescriptive packs cannot shape the synthesis or Product Contract. Make pack resolution and tier-appropriate consumption a condition on every repo-backed software path that reaches brainstorm synthesis, rather than nesting it inside the Standard/Deep topic-scout path.

AGENTS.md reference: AGENTS.md:L134-L136

Useful? React with 👍 / 👎.

Comment on lines +440 to +443
def _main() -> int:
if shutil.which("git") is None:
print(json.dumps({"roots": [], "warnings": ["git binary not found; packs unavailable"], "errors": []}))
return 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve path packs when Git is unavailable

When git is absent but the config contains only repo-relative, home, or absolute path sources, this early return discards those live sources too and reports all packs unavailable. The design in docs/plans/2026-08-26-001-feat-ce-packs-config-sources-plan.md:164 limits missing-Git degradation to git entries, so resolver startup must still locate the project and process path entries while warning only for git-backed entries.

Useful? React with 👍 / 👎.

Capture now closes the loop: the resolver runs before Phase 1 dispatch
and the Related Docs Finder records pack_overlap, so an insight a pack
rule already prescribes is recognized (interactive: refine the rule,
capture the repo-specific nuance with a citation, or skip;
non-interactive: Documentation skipped with the citation) instead of
re-captured. Interactive Full mode can route a prescriptive, cross-repo
capture into a writable declared pack — or scaffold one plus its
config entry — with the learning-to-rule rewrite; git-sourced packs
render as upstream-manual and are never written. Write boundary names
the two consented writes. Sixth resolver copy, parity-gated.

Also renames the feature to Compound Packs (docs, prose, glossary,
health-check header; config key, citation marker, and script name
unchanged) and recommends compound-packs/ as the in-repo folder.
@kieranklaassen kieranklaassen changed the title feat(ce-plan): ground planning and review in config-declared CE Packs feat(packs): compound, ground, and enforce domain knowledge via Compound Packs Aug 26, 2026
Dogfooding in a clean repo showed the R8 skip-report only existed in
researcher prose — a pack author validating with check-health never saw
that a file was inert. The resolver now warns per skipped top-level .md
in each installed pack, so planning, review, and the health check all
surface it. Regression test added; six copies synced.
…e ambiguities

Twelve-scenario matrix executed through the product's real UX (resolver
CLI, shipped skill prose via fresh agents, check-health, docs
walkthrough) in a clean repo: 11 Pass, 1 Fixed (silent skip, 1a18a67).
Prose pinned per findings: pack rule reads are top-level-only with
subdirectories/non-md as assets, scout file:line pointers are
pack-relative, pack_overlap rule id is the filename stem.
# Conflicts:
#	README.md
#	skills/guides/packs.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant