pseudomonorepos — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pseudomonorepos (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Not a true monorepo. Not loosely coupled either. A parent repo that adds children (often as git submodules) primarily so the parent can host a context-v/ that aggregates context across them.~/code/lossless-monorepo/ or any of its descendantsDon't rush into creating. Before writing a new spec, prompt, blueprint, doc, or substantial code:
context-v/:astro-knots/context-v/blueprints/X.md and lossless-monorepo/context-v/explorations/Y.md — should we extend those, link to them, or write something new?"[[wikilinks]]. Re-stating without linking is a smell.Sometimes assembling patterns, finding prior work, and writing context-v files slows speed to ship. That's a real tradeoff. When the user signals "just ship it":
context-v/issues/ or context-v/explorations/ as a one-liner: "Shipped X without searching for prior patterns. Refactor candidate: connect to existing work in [[…]]?"We aspire to refactor afterwards — to make sense of things, connect them, write the missing blueprint, file the reminder. Speed-to-ship is granted; amnesia is not.
pseudomonorepo/
├── .git
├── .gitmodules # children referenced as submodules (sometimes)
├── context-v/ # PARENT-level context spanning children
│ ├── specs/
│ ├── blueprints/ # cross-cutting patterns across children
│ ├── prompts/
│ ├── reminders/
│ ├── explorations/
│ └── issues/
├── changelog/ # ship log — see Universal directories below
├── child-a/ # submodule, has its own context-v/ + changelog/
├── child-b/ # submodule, has its own context-v/ + changelog/
└── child-c/ # could itself be a pseudomonorepo (nested)Each level is authoritative for its own scope. Children own their internals. The parent owns the space between children.
Aspiration: every pseudomonorepo, true monorepo, and project repo has these two top-level siblings:
| Directory | Purpose |
|---|---|
context-v/ | Living documentation (specs, prompts, blueprints, reminders, explorations, issues). See context-vigilance skill. |
changelog/ | Ship log — dated records of what changed and when. The progress trail. |
Reality: placement of changelog/ varies. Some projects have it nested at context-v/changelog/, some have it parallel at the repo root. Aspiration is parallel. When working in a project, respect the existing placement; only normalize when explicitly asked.
When scaffolding a new repo at any level, create both as siblings at the root.
The canonical loop for any meaningful unit of work in the Lossless ecosystem:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ START │ → │ PROGRESS │ → │ REFLECT │ → │ PUBLISH │ → │ MARKET │
│ │ │ │ │ │ │ │ │ │
│ project/ │ │ project/ │ │ parent/ │ │ parent/ │ │ astro- │
│ context- │ │ change- │ │ context- │ │ change- │ │ knots │
│ v/ │ │ log/ │ │ v/ │ │ log/ │ │ site │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
↑ │
└──────────── feedback / next iteration ──────────────────────────────────────┘flowchart LR
A["<b>START</b><br/>project/context-v/<br/><i>spec, prompt, blueprint</i>"]
B["<b>PROGRESS</b><br/>project/changelog/<br/><i>what shipped, when</i>"]
C["<b>REFLECT</b><br/>parent/context-v/<br/><i>cross-cutting blueprint, lessons</i>"]
D["<b>PUBLISH</b><br/>parent/changelog/<br/><i>announce across the family</i>"]
E["<b>MARKET</b><br/>astro-knots site<br/><i>essay, gallery, walkthrough</i>"]
A --> B --> C --> D --> E
E -.->|feedback| APhase definitions:
| Phase | Where | What |
|---|---|---|
| Start | project/context-v/ | Write the spec, prompt, or blueprint that frames the work |
| Progress | project/changelog/ | Log what shipped and when, with links back to the spec |
| Reflect | parent-pseudomonorepo/context-v/ | Lift learnings to the cross-cutting level: new blueprints, refined patterns |
| Publish | parent-pseudomonorepo/changelog/ | Announce the change at the family level |
| Market | An Astro Knots site | Public-facing essay, gallery entry, or walkthrough where it fits |
Not every unit of work runs the full loop. Small fixes might stop at Progress. Significant patterns should run all five. The loop is aspiration, not mandate. But every phase skipped is a candidate for refactor debt (see references/search-first.md).
A dedicated `lossless-loop` (working title) skill is forthcoming to fully encode this workflow.
A pseudomonorepo's splash, site, or gallery should surface not only its own changelog/ and context-v/ — it should roll up those of its submodules into one feed at the parent level. A reader landing on content-farm/splash/ should see ship notes from image-gin, cite-wide, and the rest, not just from content-farm itself.
Mechanism preference: the GitHub Content API, authenticated, at build time. For each submodule registered in the parent's .gitmodules, derive the API endpoint from the url = line, query /contents/changelog/ and /contents/context-v/ against the configured branch, and merge results into the parent's content collections. This avoids cloning every submodule into CI and stays cheap under the 5000-req/hr authenticated rate limit.
Provenance matters. Every rolled-up entry should carry which submodule it came from as visible metadata, so a reader can filter to just one plugin's notes (/changelog?from=image-gin) and so the parent isn't pretending to have authored its children's work.
Status: aspirational. The first two splashes (memopop-site, content-farm/splash) render local-only content as of writing. When you scaffold a new splash, log roll-up as Phase 2 work in that splash's spec — don't pretend Phase 1 is "done" if roll-up is missing; it's done-with-a-known-follow-up.
The same pattern composes up the tree: a parent pseudomonorepo's splash rolls up its children's content, and its parent rolls up its children — eventually feeding the long-stated "Lossless Changelog" umbrella view at the org level (see the changelog-conventions skill).
See references/content-rollup.md for the full mechanism — endpoint shape, auth, failure modes, loader sketch.
It is very common in this tree to relocate a child repo from one parent path to another. Examples:
astro-knots/sites/calmstorm-decks/ → ai-labs/dididecks-ai/client-sites/calmstorm-decks/This is the highest-risk operation in the tree. When done wrong, it silently destroys:
.env / secrets (lost — .env.example is not authoritative)This actually happened on 2026-05-12: a calmstorm-decks move from astro-knots/sites/ to ai-labs/dididecks-ai/client-sites/ produced a fresh clone with no .env, on a stale development branch missing 19 commits of auth/play work from main. The old directory had already been deleted. Hours of recovery followed.
Claude is under NO circumstances to "go along" with a relocation request until all three preconditions are explicitly verified and acknowledged by the user — one acknowledgment per precondition, not bundled.
For the repo about to move:
git fetch --all --prune
git branch -vv # [ahead N] / [behind N] / [gone]
git log --branches --not --remotes --oneline # local-only commits
git status # working tree clean?
git stash list # any parked work?Refuse to proceed if any branch shows [ahead N], any commits appear in the --not --remotes query, the working tree is dirty, or any stash exists. Surface exactly what is unsynced.
git ls-remote --heads origin # authoritative remote list
git branch -a # local + remote-tracking
diff <(git branch | tr -d ' *') \
<(git ls-remote --heads origin | awk '{print $2}' | sed 's|refs/heads/||')Refuse to proceed if local branches exist with no matching remote and the user has not explicitly listed them as disposable.
cat .gitignore
ls -la
find . -maxdepth 2 \( -name ".env*" -o -name "*.local" -o -name ".secrets*" \) 2>/dev/null
# Plus: enumerate every var the SOURCE actually reads (not just .env.example,
# which lags behind code):
grep -rhoE '(process\.env|import\.meta\.env)\.[A-Z_][A-Z_0-9]*' src scripts db astro.config.* 2>/dev/null | sort -uRefuse to proceed if any .env* or .secrets* exists and the user has not confirmed a recovery path (password manager, separate .env.backup outside the directory, 1Password, Vercel/Netlify env panel, deployed-host UI).
`.env.example` is NOT authoritative — it routinely lags behind. The grep above against process.env / import.meta.env is the truth. The auth/db stack in particular often has 3–5 historical names for the same value (e.g., ASTRO_DB_REMOTE_URL / ASTRO_DB_URL / TURSO_DB_URL / DIDIDECKS_TURSO_DB_URL all pointing at the same database). The source shows them all; .env.example may show only one.
Default template:
Before I touch this — moving a repo within the tree is the riskiest operation we do, and we've already lost env vars + unpushed work from exactly this kind of move. Three preconditions:
>
1. Local branches synced. [output ofgit branch -vv+ status] — branches X, Y are[ahead]by N commits. Push or document-as-lost? 2. Remote branches catalogued. Remote has A, B, C. Local has A, B, C, D. Branch D is local-only — push it or confirm disposable? 3. Env/secrets backed up. Source reads vars: [list from grep]. Where is the canonical copy you'd recover from?
>
Each one gets its own acknowledgment. I won't bundle them.
Do not combine the three checks into a single "looks good, proceeding" beat. Bundled confirmations are how vars get lost.
If you arrive after the move (fresh clone, missing secrets, stale branch):
find ~ -type d -name '<repo>' 2>/dev/null | grep -v node_modules
ls ~/.Trash | grep -i '<repo>'
ls ~/.claude/projects/ | grep -i '<repo>' # encoded old paths
ls ~/Library/Caches/claude-cli-nodejs/ | grep -i '<repo>'Old paths are recoverable as session-cache directory names (the directory names encode the absolute path of the working copy).
Precondition 3.
--date=iso` reveals where the lost work might be reachable on a different branch. The new clone may not be on the tip branch.
Pseudomonorepos and their submodules share a three-tier branch model: `development` → `main` → `master`.
development is where most work lands.main is what development gets promoted to when it reaches something noteworthy.master is stable — updated only when the dust has settled.Aspiration: when the parent is on a tier, every submodule is on the same tier. Parent on development → all submodules on development. Same for main and master. Look for root-level scripts like switch-all-to-development-branch.sh before writing your own.
Reality: humans get lazy. Work piles up in development and rarely gets promoted; main sometimes becomes the de-facto working branch; master is often the most stale branch in the repo. That's expected, not broken.
When a submodule is missing a tier (e.g. development doesn't exist), create it from the leading branch with a non-destructive push (git branch development origin/master && git push origin development:development). When development is behind main/master, fast-forward it up — don't roll the gitlink backwards by switching to a stale branch.
After changing a submodule's tracked branch: update branch = in the parent's .gitmodules, run git submodule sync, and commit both the .gitmodules change and the submodule pointer. An entry without a branch = line is a smell.
Don't auto-realign as a side effect of unrelated work. Same drift policy as everything else in this skill: observe, surface, get explicit authorization.
See references/branch-alignment.md for the full recipe (FF mechanics, divergence checks, push-to-default-branch caveats).
The hierarchy can be:
root pseudomonorepo
└── theme-level pseudomonorepo
└── collection-level pseudomonorepo
└── true monorepo (npm workspaces, etc.)
└── individual project / repoNot every project sits at every level. The point is: walk up until you stop finding `context-v/` to be sure you've checked all relevant context.
The anchor pseudomonorepo is `lossless-monorepo` (<https://github.com/lossless-group/lossless-monorepo>), locally at ~/code/lossless-monorepo/ (paths vary on collaborators' machines).
Rank-ordered children (most relevant first):
| Path | Intent |
|---|---|
ai-labs/ | Work where we monkey with AI + Agents on complex workloads |
astro-knots/ | The family of websites — feature-rich, opinionated |
content-farm/ | Currently almost entirely Obsidian plugins (we use Obsidian for content) |
tidyverse/ | Tools, libs, scripts for cleaning up other things |
For details, current state, and intent-vs-reality notes, see references/the-tree.md.
Honest note: The root and most pseudomonorepos are imperfectly maintained. Don't assume context-v/ is complete or current. Search it; treat what you find as starting points; surface gaps when you see them.Drift policy: Walking the tree will reveal far more inconsistencies than consistencies. Observe, note, surface — but do not auto-clean as a side effect of unrelated work. Normalization is a separate, explicitly-authorized task. The user runs parallel agent sessions; silent fixes break others' work. Full policy in ~/.pi/agent/AGENTS.md.This skill is not a silo — it composes with the others:
context-v/. The two are two halves of the same idea: this skill says where to look and when to look up; context-vigilance says what the docs you find should look like.astro-knots/ is one of the four children. Working in any Astro Knots site means walking up to lossless-monorepo/ for cross-site context.astro-knots/ or as its own child.When working in this tree, multiple skills apply at once. Don't pick one — let them all inform what you do.
pwd. Walk up. Note which pseudomonorepo level(s) sit above you.context-v/: for dir in $(walk-up-to-root); do
ls "$dir/context-v/" 2>/dev/null
done grep -ril "keyword" $(find ~/code/lossless-monorepo -type d -name context-v 2>/dev/null)context-vigilance conventions to whatever you write.references/anatomy.md — what makes something a pseudomonorepo, identification heuristicsreferences/the-tree.md — current state of the lossless-monorepo tree (living doc)references/search-first.md — concrete recipes for finding prior workreferences/lifecycle-workflow.md — the 5-phase Start → Progress → Reflect → Publish → Market loop, with diagramsreferences/branch-alignment.md — the development → main → master tier model and how to keep parent + submodules alignedreferences/content-rollup.md — how parent splashes/sites should aggregate changelog/ and context-v/ from their submodules via the GitHub Content APIcontext-vigilance/SKILL.md — the documentation framework that context-v/ followsastro-knots/SKILL.md — the websites child of the tree~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.