compiling-project-guidelines
Skill9 starsChanged 3 months agoApache-2.0View on GitHub
Compile scattered guideline sources into one scope-aware COMPILED-GUIDELINES.md for other skills and ult-context-generate's Constraints layer. Do NOT use to enforce rules at runtime.
In this repository22 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .cursor/rules/compiling-project-guidelines.mdcCursor rule
- .cursor/rules/demo-consume-context.mdcCursor rule
- .cursor/rules/demo-write-user-stories.mdcCursor rule
- .cursor/rules/ult-autoscaffold-content.mdcCursor rule
- .cursor/rules/ult-cep-retrofit.mdcCursor rule
- .cursor/rules/ult-cep-wizard.mdcCursor rule
- .cursor/rules/ult-codegraph.mdcCursor rule
- .cursor/rules/ult-context-generate.mdcCursor rule
- .cursor/rules/ult-institutional-memory-distill.mdcCursor rule
- .cursor/rules/ult-onboarding-index.mdcCursor rule
- .cursor/rules/ult-repo-layout.mdcCursor rule
- demo-consume-contextSkill
- demo-write-user-storiesSkill
- autoscaffold-contentSkill
- cep-retrofitSkill
- cep-wizardSkill
- codegraphSkill
- context-generateSkill
- institutional-memory-distillSkill
- onboarding-indexSkill
- repo-layoutSkill
The file
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 6 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 63
Read this before doing anything else.
- Distinctive: line 83
Run these steps in order. Don't skip step 2's scope-tagging to "save time" — that's where the quality of everything downstream is decided.
- Distinctive: line 110
Do not silently skip a source the user points you at because it's an unfamiliar format — ask for help reading it before giving up on it.
- Distinctive: line 152
Keep a running scratch list shaped like:
- Very specific: line 160
If the source file's own frontmatter carries generated_by: ult-autoscaffold-content and status: draft, note that alongside its SOURCE line …
- Very specific: line 243
Write to the resolved compiled_guidelines path (see the path-resolution note above).
- Distinctive: line 260
Use exactly this shape (organized prose with scope as a first-class structural element — not a database, not YAML, a Markdown file a human …
- Very specific: line 309
Every ### Scope: heading carries both a path glob (so consumers can match against it mechanically) and a short human label (so a reviewer …
- Very specific: line 312
Every bullet under ## Global and ## Scoped Guidance carries a [constraint_class] prefix (D11) — compliance, convention, or scheduling, as …
- Very specific: line 329
When /ult-compile-guidelines is invoked and the resolved compiled_guidelines path (starter_kit/project_guidelines/COMPILED-GUIDELINES.md by …
- Very specific: line 382
If a source is genuinely unreadable (corrupted file, format none of the ult-read-* skills handle), say so plainly, list it as "not compiled …
- Distinctive: line 386
If the user has no guideline sources at all, say so and stop — don't fabricate a compiled file from generic best practices.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Compiling Project Guidelines
Overview
Large C/C++/Go/Java codebases (often ~500 KSLOC, sometimes multi-repo) almost always carry their
own design and coding conventions — scattered across CONTRIBUTING.md, .github/instructions/,
architecture docs, PDFs, wiki exports, and tribal knowledge. Project teams will not adopt any
workflow skill that quietly violates those conventions.
This skill is the one-time (and on-demand) compiler: it reads whatever guideline sources a team already has — without asking them to migrate to a new schema or folder convention — and produces a single, predictable, human-readable file that every other skill can cite before it reads, writes, modifies, reviews, or judges project code.
Run this:
- Once, during project setup (
/ult-compile-guidelines) - Again on demand whenever guideline sources change ("update my compiled guidelines — I added
docs/payments-conventions.md")
For multi-repo projects, run it once per repo — scopes are path globs relative to that repo, so no cross-repo machinery is needed.
Output: starter_kit/project_guidelines/COMPILED-GUIDELINES.md — see
the format spec below. This is the only artifact this
skill produces. There is no registry, no schema, no state machine, no decision log file — the
compiled file carries its own provenance and its own conflict-resolution history.
compiled_guidelines (D20 Phase 2, D21 §16.4): the output path above is
the compiled_guidelines path-slot — the registry's only kind: file slot,
resolved via ult-repo-layout/SKILL.md's "Path resolution algorithm (§15.5 +
§16.2)," not a hardcoded path. If /ult-repo-layout init|reconcile has run
for this project, read project_layout.slots.compiled_guidelines.path
(confirmed by its .layout-slots.yaml marker — kind: file, file:
COMPILED-GUIDELINES.md); otherwise fall back to the slot's resolved
default — {workspace_root}/cache/project-guidelines/COMPILED-GUIDELINES.md
if layout.workspace_root is set, else
starter_kit/project_guidelines/COMPILED-GUIDELINES.md (unchanged from before
Phase 2). Note the bucket reassignment under workspace_root: this file
re-roots to cache/, not inputs/ — it is a derived artifact, no longer
colocated with the raw starter_kit/project_guidelines/ drop-zone sources
once workspace_root is set. Resolve it once per run and substitute it for
starter_kit/project_guidelines/COMPILED-GUIDELINES.md everywhere it appears
below.
The load-bearing principle: scope-awareness, applied while reading — not while resolving
Read this before doing anything else. Everything below depends on it.
Large and multi-repo codebases routinely contain legitimate, non-conflicting, module/component-specific conventions — legacy vs. new code, differing build systems per service, language-specific idioms within a polyglot monorepo. "Legacy drivers use K&R brace style" and "new modules use Allman style" are two correct entries, not a conflict. Flattening that layered reality into one global answer — or defaulting to a global pattern when a more specific one actually governs — produces guidance that looks authoritative while being wrong for the area it's applied to. That's worse than no compiled guidance at all, because wrong-with-confidence is harder to catch in review than no-guidance-given.
The fix is procedural: tag scope as you read each source, before you ever compare sources to
each other. Untagged guidance defaults to scope = Global. If you do this consistently, the
later "find conflicts" step becomes trivial and almost always comes up empty — because most
apparent disagreements between docs written years apart turn out to be correctly-scoped
differences, not contradictions. Skipping or shortcutting this step is the single most likely way
this skill produces a bad compiled file, so do not let yourself rush past it.
The flow
Run these steps in order. Don't skip step 2's scope-tagging to "save time" — that's where the quality of everything downstream is decided.
Step 1 — Gather sources
Auto-suggest candidates from conventional locations:
.github/instructions/*.instructions.md.github/copilot-instructions.mdCONTRIBUTING.mddocs/guidelines/**,docs/architecture/**- anything already sitting in
starter_kit/project_guidelines/(except.pointer.md) - the resolved
how_dimension.how_l2.pathdirectory, if set incontext-config.yaml— glob its contents. This is whereult-autoscaffold-contentwritesCODING-STANDARDS.md,TESTING-GUIDELINES.md, per-moduleCONTEXT.mdfiles, andinterfaces/*.mdwhen a project has none of these yet; once they exist, this step's job is to fold them in like any other source, not to regenerate them.
Then show the user what you found and ask them to confirm, add, or remove paths —
including pointing you at PDFs, DOCX, wiki exports, or style-guide documents that auto-discovery
can't see. For binary formats, read them with whatever's available in this project — a
PDF/DOCX-reading skill if one is installed, or a lightweight library you install for the occasion
(e.g. pdfplumber/python-docx) — and extract the plain text before folding it into the
compiled file.
Do not silently skip a source the user points you at because it's an unfamiliar format — ask for help reading it before giving up on it.
Step 2 — Extract WITH scope tags (the step that must not be shortcut)
While reading each source, record not just what the guidance says but where it claims to apply: a directory/module/component name, a path glob, a language/build-target boundary, an explicit "legacy vs. new" distinction, a service name, etc.
For every rule you extract, you should be able to answer: "if an engineer were touching path X,
would this rule apply?" If the source doesn't say, the scope is Global — don't guess a
narrower scope into existence, and don't widen a narrow one to Global either.
Real sources very often state scope by named functional area rather than by path — a
learnings.md tagging entries [Auth], [DB], [UI], [Ops]; a design doc that says "this
file is scoped to visual language only, it must not change CRUD semantics or backend behavior."
That's a legitimate scope statement, not a vague one — but consumers of the compiled file match
against the paths their task touches (see CONSUMING-COMPILED-GUIDELINES.md step 2), not
against topic tags. So when you encounter a named-area scope, resolve it to the path footprint
that area actually occupies in this codebase (a quick grep/glob for the area's
characteristic names is usually enough — e.g., [Auth] → wherever auth/login/session
logic lives) and write the ### Scope: heading with those real globs, keeping the area name as
the human label so the why stays traceable. If a clean path mapping genuinely doesn't exist
for a named area (it's cross-cutting, or the codebase doesn't group by it), say so in the entry
rather than forcing a glob that would never match anything — and note in "Noted Tensions" that
this guidance is topic-scoped, not path-scoped, so a human applying it has to recognize the
topic of their change, not just its location.
Also tag each rule's constraint_class (D11) — this drives the conflict check in
step 4 and lets ult-context-generate load this file as the project's Constraints
layer:
compliance— a regulatory, legal, security, or audit requirement. Narrower scopes may tighten acompliancerule but never loosen it (step 4 checks this). Look for cited standards (GDPR, SOC2, MISRA, DO-178C, internal security policy) or language like "must", "required by", "audit", "retention".scheduling— a sequencing, phasing, or dependency constraint ("migrate consumers before removing the old endpoint", "feature flag rolls out region-by-region").convention— everything else: coding style, architecture choices, naming, tooling. This is the default — if a rule doesn't clearly read ascomplianceorscheduling, tag itconvention. Most guideline docs are conventions.
Keep a running scratch list shaped like:
RULE: <the guidance, paraphrased faithfully — don't editorialize>
SCOPE: <Global | path-glob + short label>
CONSTRAINT_CLASS: compliance | convention | scheduling
SOURCE: <file path + the line/section that said so>If the source file's own frontmatter carries generated_by:
ult-autoscaffold-content and status: draft, note that alongside its
SOURCE line — a scaffold-generated draft rule is real input, but the
final compiled file's Sources: footer (step 6) should say so, same as it
already states each source's modified date.
Step 3 — Group by scope, not by source document
Guidance that shares a scope and topic gets merged into one entry. Guidance with different scopes is kept as separate entries even when it looks superficially similar or contradictory.
This is where the scope-tagging from step 2 pays off: "legacy drivers use K&R" and "new modules
use Allman" are not weighed against each other here — they're filed as two entries under two
different ### Scope: headings, full stop.
Step 4 — Escalate only genuine conflicts
Two kinds of genuine conflict get escalated here. Both are narrow by design — the point is to keep the human Q&A focused on things that genuinely need a judgment call.
1. Same-scope conflict (original trigger): the same rule, claimed for the same
scope, stated two incompatible ways — e.g., two documents both describe
services/payments/** and disagree on which test framework is canonical for it.
2. Vertical compliance conflict (D11 Type 1): a narrower-scope compliance entry
that would loosen a broader-scope compliance entry on the same topic, where the
narrower scope's path glob sits inside the broader scope's (every scope sits inside
Global). Example: Global says "[compliance] all PII deleted within 2 years"; a
services/guest-accounts/** entry says "[compliance] guest account activity logs
retained indefinitely for fraud analysis." Same topic (data retention), narrower
scope, and the narrower entry loosens the broader requirement — escalate it.
A narrower entry that tightens a broader compliance entry (e.g., "Global: 2 years" → "payments/**: 90 days") is not a conflict — narrower-tightens-broader is the expected, healthy case. Only loosening escalates.
Anything that resolves by scoping is not a conflict — it was already filed as two entries in step 3. Do not escalate:
- Differences that turn out to be about different scopes (that's step 3's job, already done)
- Stylistic rewording of the same rule for the same scope (that's the same rule — merge it, cite both sources)
- A newer doc superseding an older one on the same point for the same scope where the newer doc says so explicitly (note the supersession in the entry, don't escalate it)
- A narrower
complianceentry that tightens (rather than loosens) a broader one on the same topic
Keeping this list short is the point: it keeps the human Q&A focused on things that genuinely need a judgment call, instead of forcing the engineer to adjudicate every textual difference between documents written years apart by different authors.
Step 5 — Resolve flagged conflicts interactively, one at a time
For each same-scope conflict from step 4, ask the user directly and concretely:
"Source A (
<file>) says<X>for<scope>. Source B (<file>) says<Y>for the same scope. Which is current — or does each actually apply to a different sub-scope I should split out?"
For each vertical compliance conflict from step 4, frame it differently — the question is whether the narrower scope's exemption is legitimate, not which source is "more current":
"
<broader scope>requires<X>(compliance, from<source>).<narrower scope>appears to loosen this to<Y>(from<source>). Is<narrower scope>genuinely exempt for a documented reason — or should it be tightened to comply with<X>?"
Three possible outcomes for a vertical conflict:
- Exempted — the user confirms a documented reason for the exemption. Record as resolved with that reason.
- Corrected — the user says the narrower scope should comply. Update that entry's text (step 3's grouping) to the tightened value and record as resolved.
- Unresolved — the user can't decide on the spot (needs sign-off from
compliance/legal/another team). Record as unresolved, naming who it's escalated to.
ult-context-generate(D11 Step 5.5) carries unresolved vertical conflicts forward into any feature whose scope they touch.
One question at a time. Record the resolution and the user's stated reason verbatim (or
close to it) directly into the compiled file's ## Noted Tensions section — that log is the
only "decision persistence" this design needs. It lives in the one artifact everyone already
reads, so it can't drift out of sync with a separate state store (because there isn't one).
Step 6 — Write the compiled file
Write to the resolved compiled_guidelines path (see the path-resolution note
above). Its pre-D21 default — the standard, predictable path when
layout.workspace_root is unset:
starter_kit/project_guidelines/COMPILED-GUIDELINES.mdColocated with whatever raw sources the team already drops in
starter_kit/project_guidelines/ — the same starter-folder convention as
starter_kit/threat_modeling/ — so provenance sits one folder away from the
artifact it produced, when layout.workspace_root is unset. Once set,
compiled_guidelines re-roots to {workspace_root}/cache/project-guidelines/
while the raw sources stay under
{workspace_root}/inputs/starter-kit/project_guidelines/ — colocation is a
property of the pre-D21 default, not a guarantee.
Use exactly this shape (organized prose with scope as a first-class structural element — not a database, not YAML, a Markdown file a human can open and skim):
# Project Guidelines (Compiled)
> Generated by /ult-compile-guidelines on <YYYY-MM-DD>
> Sources:
> - <source file> (modified <date>)
> - <source file> (modified <date>, scaffold-generated draft — see its own frontmatter)
> Re-run /ult-compile-guidelines after changing any source above — this file does not auto-update.
## How consuming skills should use this file
1. Identify the file paths / components your current task touches.
2. Find every section under "Scoped Guidance" whose path pattern matches those paths.
The MOST SPECIFIC matching scope governs that area — it overrides "Global" for anything
inside it. Do not apply Global guidance where a more specific scope exists and conflicts with it.
3. Where no scoped section matches, "Global" applies.
4. State which scope(s) you used in your output.
## Global
- [convention|compliance|scheduling] <guidance that genuinely applies everywhere, one bullet per rule>
## Scoped Guidance
### Scope: `<path-glob>` — "<short human label>"
- [convention|compliance|scheduling] <guidance that applies only within this scope>
## Noted Tensions (resolved during compilation — preserved across re-runs)
- <date>: <Source A> (<its scope>) says <X>; <Source B> (<its scope>) says <Y>.
Resolved as <scope split | supersession | other> — see entries above.
Confirmed by <who> as <their stated reason>.
- <date>: [VERTICAL/COMPLIANCE] `<broader scope>` requires <X>; `<narrower scope>`
would loosen this to <Y>.
Status: Exempted — <reason> | Corrected — narrower entry now reads <Z> | Unresolved — escalated to <who> on <date>
## Recent Observations (pending compile)
- <date> [<skill-name>]: <observation — a new lint rule, a convention that appears
to have drifted from what's documented, anything guideline-relevant noticed
while doing unrelated work>Notes on filling this in:
- The header's source list is load-bearing — it's what makes the staleness nudge in
CONSUMING-COMPILED-GUIDELINES.mdpossible. Record the real modification date of each source at compile time. ## Globalholds only guidance that is genuinely scope-free. If you're unsure whether something is Global or just under-specified in its source, prefer filing it as Global and note the ambiguity rather than inventing a scope the source never stated.- Every
### Scope:heading carries both a path glob (so consumers can match against it mechanically) and a short human label (so a reviewer immediately understands why that boundary exists — "legacy", "new service", "vendor-supplied", etc.). - Every bullet under
## Globaland## Scoped Guidancecarries a[constraint_class]prefix (D11) —compliance,convention, orscheduling, as tagged in step 2.ult-context-generatereads this tag when loading this file as the project's Constraints layer. ## Noted Tensionsis append-only across re-runs (see below) — it is the project's compiled history of "we looked at this, and here's what we decided and why."[VERTICAL/COMPLIANCE]entries withStatus: Unresolvedare howult-context-generate(D11 Step 5.5) finds open compliance questions that touch a feature's scope.## Recent Observations (pending compile)is also append-only between re-runs, but for a different reason: it's an inbox, not a log. Entries are written by consuming skills viaCONSUMING-COMPILED-GUIDELINES.mdstep 5 — a lightweight, unreviewed note left between compile runs. Triage it on the next/ult-compile-guidelinesrun (see "On re-run" below); the section should be empty immediately after a compile. Omit the section entirely if it would be empty.
On re-run (updating an existing compiled file)
When /ult-compile-guidelines is invoked and the resolved compiled_guidelines
path (starter_kit/project_guidelines/COMPILED-GUIDELINES.md by default — see
the path-resolution note above) already exists:
Triage
## Recent Observations (pending compile)first, before anything else. For each entry: if it's straightforward new guidance, fold it into## Globalor## Scoped Guidanceas a new rule (tagging it with a[constraint_class]per step 2, same as any other source material). If it conflicts with existing compiled guidance, run it through the step 4/5 conflict flow below and let the outcome land in## Noted Tensions. Either way, remove the entry from## Recent Observationsonce triaged — the section should be empty (or omitted entirely) by the time this compile finishes.Entries attributed
[ult-context-generate]are a special case: these describe a conflict a human already resolved once, at that skill's Step 9 human-approval gate (seeult-context-generate/SKILL.mdStep 9.5) — not a fresh observation awaiting a decision. Fold these in as a pre-resolved## Noted Tensionsentry directly, citing the source context package'sidfor traceability. Do not re-run them through the step 4/5 Q&A — re-asking a question the human already answered violates the "don't re-litigate" principle in step 3 below.- Read it first. Its
## Noted Tensionslog tells you which conflicts were already raised, how they were resolved, and why. - Carry forward resolved tensions whose underlying sources haven't changed since — don't
re-litigate them. If a source involved in a previously-resolved tension has changed, surface
it to the user as "this was previously resolved as
<X>— still applies, or has something changed?" rather than re-running the full Q&A from scratch. 3a. Re-checkStatus: Unresolvedvertical conflicts — ask the user once per re-run whether there's now an answer ("<broader scope>vs<narrower scope>on<topic>was escalated to<who>— has that come back?"). If yes, update the entry to Exempted/Corrected. If still pending, carry it forward unchanged. - Only run the full step 4/5 conflict flow on genuinely new material — new sources,
changed sections of existing sources, or
## Recent Observationsentries flagged in step 1 as conflicting. - Rewrite the file in place, preserving prior
## Noted Tensionsentries and appending new ones. The compiled file is its own state — there is no separateconflicts.resolved.jsonor decision log to keep in sync.
What this skill deliberately does not do
- It does not execute, lint, or validate anything described in the guidance — it only reads and organizes prose. There is nothing here that runs commands sourced from guideline text.
- It does not gate, block, or enforce. A scope mismatch downstream is a one-line note for human review, not a stop-the-line condition — there is no waiver workflow because there is no gate to waive.
- It does not require teams to restructure their existing docs, adopt a new schema, or move
anything out of where it already lives —
starter_kit/project_guidelines/is a place to drop additional sources if a team wants to, not a mandatory relocation target. - It does not change how any other skill executes its own work. It only gives them one more file
to read first, when one exists. See
CONSUMING-COMPILED-GUIDELINES.md(colocated in this skill's directory) for the exact protocol every code-facing skill follows to consume the file this skill produces.
When something doesn't fit this flow
If a source is genuinely unreadable (corrupted file, format none of the ult-read-* skills
handle), say so plainly, list it as "not compiled — could not read <file>" in the output file's
header, and continue with the rest. Don't block the whole compile on one bad source.
If the user has no guideline sources at all, say so and stop — don't fabricate a compiled file from generic best practices. A compiled file that doesn't reflect this project's actual conventions is worse than no compiled file, for the same reason stated in the scope-awareness principle above: it looks authoritative while being wrong.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

