← The kit's docs / specs/
Survey: a Scoped Dashboard of context-v
One command turns every context-v/ folder in scope into a dashboard, a task list, and a map, the way graphify turns code into a graph.
- Path
- context-v/specs/Survey-a-Scoped-Dashboard-of-Context-V.md
- Authors
- Michael Staton
- Augmented with
- Claude Code on Claude Opus 5.5
- Tags
- Context-Vigilance · Dashboards · Pseudomonorepos · Agent-Skills · Three-Mode-Theming
Why Care?
A
context-v/
folder is easy to write into and hard to see. One repo with thirty docs is fine. A tree of repos, each with its own
context-v/
, is not: our own tree has 93 of them holding about 2,200 docs, and nobody (human or agent) can answer
"what's in flight, what's stuck, what did we promise and never close"
without opening files one by one.
Graphify answers
"what is this codebase"
with one command and a file you open. Archify answers
"how does this system flow"
the same way.
Survey
answers
"what is the state of our context"
: run it, and get a dashboard, a task list, and a map of every
context-v/
in the scope you asked for.
The scope is the point. Inside one repo it's a status page for that project. At the root of a tree it's a portfolio view across every child. In between, it can follow just the repos relevant to today's work.
Role and voice
Written as VP Product : what it is, who it's for, what done looks like. Engineering choices appear only where they constrain the product (zero dependencies, privacy). The Spikes section at the end is written as VP Engineering and compares the first attempts.
Who it's for
-
The operator at the start of a week or a session: "what's open across everything I own?"
-
An agent at
/cv:kickoff: a cheap, structured read of the scope before choosing what to load. The agent reads the report, not the HTML. -
A collaborator handed one repo: "what's the state of this project's thinking?"
The jobs it does
Added 2026-10-28, after the first spikes, from the operator:
-
Status: what's in flight, open, stuck, and done, at the chosen scope.
-
Cleanup: find messy metadata and stubs, then delete, complete, or close them on purpose. Signals:
empty(under 40 words of prose), maturity by content lines (stubunder 100,worked-onfrom 500, the same cut as the corpus manifest),maybe_done(every checkbox ticked, status still open), stale open docs, missing or mismatched frontmatter, and unmapped statuses. The survey lists candidates; a separate, deliberate pass edits them. -
Think like a CTO: who is making progress quickly , and which specs and issues are in my option set to assign .
-
Momentum comes from one
git logper repo over a 90-day window: commits in 7 and 30 days, agent-assisted share (fromCo-Authored-Bytrailers), commits touchingcontext-v/, docs added, docs closed. A repo counts as the operator's when the operator (git config user.name) committed there in 30 days; forks and pinned upstream repos are listed separately so their authors don't inflate "who's moving." -
Option set: ready to assign (Signed-Off, Ready, Approved), needs a decision (In-Review, Proposed), open issues , and stalled in flight (in flight but untouched for 30 days, or in a quiet repo). Ranked by readiness: acceptance criteria present, maturity, recent change, repo momentum, minus stale.
-
What it produces
One run, one output folder, three things in it:
| Output | For | Shape |
survey.json
|
tools, future runs, diffing | Every doc in scope with path, repo, folder, type, title, lede, status (raw and normalized), dates, open-checkbox count, health flags |
SURVEY.md
|
agents (and terminals) |
The same picture in a few hundred lines: counts, in-flight work, open tasks, drift. Modeled on graphify's
GRAPH_REPORT.md
|
survey.html
|
humans | A single self-contained page (no network, no build step) with three views and three modes |
The three views
-
Dashboard. Counts by repo × lifecycle bucket and by folder. Freshness (what moved this week, what hasn't moved in 90 days). Health: missing frontmatter, missing
type, missing lede, statuses that don't map to the canon. -
Task list. The actionable slice: specs and plans that are
Signed-OfforImplementing, issues still open, the newest handoff per repo, and unchecked- [ ]items inside plans, prompts, and handoffs, each linked to its file and line. -
Map. The tree itself: repos nested as they sit on disk, each showing its
context-v/folders and a status mix, so you can see where the thinking is dense, where it's thin, and where it's stale.
The three modes (hard rule)
Every survey page ships
light, dark, and vibrant
modes, per the
theme-system
contract used by every Astro Knots site and splash:
data-mode
on
<html>
, a pre-paint script so there is no flash, a labeled three-button toggle, and the choice remembered per viewer. Tier 1 named tokens plus Tier 2 semantic tokens per mode. The default palette borrows the kit splash's (amber, sodium, lime on ink); a repo with a
DESIGN.md
or
theme.css
may later supply its own.
Scopes
Scope is resolved from where you run it plus one flag. A
repo
is any directory with a
.git
entry (a folder for a clone, a file for a submodule). Each
context-v/
belongs to the nearest repo above it.
| Scope | Flag | What's included | Typical use |
| Repo |
--scope repo
|
This repo's
context-v/
folders only; child repos excluded
|
Status page for one project |
| Tree |
--scope tree
(default at a repo with child repos)
|
This repo and every repo below it | Portfolio view; at the anchor root it's the global view |
| Lineage |
--scope lineage
|
This repo and every ancestor repo up to the top | "What did the parents decide that governs me?" |
| Pick |
--repos a,b,c
|
Named repos (paths or names), each scanned as
repo
|
The handful relevant to today's task |
context-v-corpus
is the natural home of the global view: a tree scan from the anchor root, run there.
Always skipped:
node_modules/
,
dist/
,
.git/
, every
context-v/extra/
(scratch, private by convention), the corpus's collated copies (
context-v-corpus/corpus/
), and anything listed in a
.surveyignore
at the scope root. Upstream study repos (read-only
studies/
mounts) are skipped by default because they aren't ours;
--include-studies
brings them in.
Status normalization
Status in the wild is messy. A sample of
ai-labs/
alone:
Draft
334,
Shipped
89,
Active
81,
Open
57,
shipped
51,
Resolved
23,
Open · Jotted
16,
Reference
11,
Proven-Once
6, and a long tail. The survey keeps the raw value and adds a
lifecycle bucket
:
| Bucket | Raw values (case-insensitive, first word wins) |
| Open | Draft, Proposed, Open, In-Review, Jotted, Idea, Stub |
| In flight | Signed-Off, Ready, Implementing, In-Progress, Active |
| Done | Shipped, Partially-Shipped (flagged partial), Resolved, Decided, Complete |
| Parked | Deferred, Stale, Blocked, Untested |
| Closed | Superseded, Archived |
| Reference | Reference, As-observed-*, Proven-Once, Living |
| Unmapped | anything else, listed verbatim in the health panel |
| None |
no
status:
key
|
The survey
never edits a doc.
Per the drift policy, it surfaces (unmapped statuses, missing keys,
Draft
untouched for 90+ days) and leaves fixing to a deliberate pass.
Command and skill shape
-
Skill:
agent-skills/survey/withSKILL.mdandscripts/. Ships in thecvplugin as/cv:survey; any Agent Skills tool gets it as "the survey skill." -
Two stages, like graphify:
scan.py(deterministic, no judgment) writessurvey.json;render.pywritesSURVEY.mdandsurvey.htmlfrom it. Re-rendering never rescans. -
The agent's part: pick the scope (ask if it's unclear), run the scripts, read
SURVEY.md, and reply with the three or four things that most need attention. The agent adds judgment; the scripts add none. -
Output location:
context-v/extra/survey/in the scope root by default. That folder is already gitignored by the practice, so a survey of private work never lands in a commit by accident.--outoverrides. -
Where our own views live (2026-10-28): the code stays in this kit; the views of the Lossless tree live in
context-v-corpus, built by itsscripts/refresh-survey.shintosurvey/views/<scope>/and copied into the corpus splash (splash/public/survey/). The kit's splash carries copies as examples (splash/public/examples/survey/), on its/survey/page. -
--publicdrops docs markedpublish: falseorprivate: true, repos underclient-sites/orcollaborations/, and absolute paths, for a survey meant for a public page. Optional; our own views don't use it.
Hard constraints
-
Python 3 standard library only. PyYAML is used when present, with the same top-level-key fallback the frontmatter hook uses. No
pip installto get a dashboard. -
The HTML is one file. Inline CSS, inline JS, inline data. Opens from disk, works offline, can be attached or published as-is.
-
Read-only. Never writes outside the output folder.
-
Fast enough to run casually: a full tree scan of ~2,500 docs under 5 seconds. Dates come from frontmatter, falling back to file mtime; no per-file
git log. -
Private by default. Outputs land in a gitignored folder. Nothing generated from real project content is committed to this kit.
Acceptance criteria
-
/cv:surveyin a single repo with no children produces all three outputs for that repo alone. -
At the anchor root with
--scope tree, everycontext-v/in the tree except skipped paths appears, attributed to the right repo. -
--scope lineagefrom a leaf lists the leaf and each ancestor, nothing else. -
Every doc with a
status:lands in exactly one bucket; unmapped values are listed verbatim with counts. -
The task list shows unchecked
- [ ]items with file and line, and each links to the file. -
The HTML toggles light, dark, and vibrant with no flash on load, and remembers the choice.
-
The HTML renders with JavaScript disabled enough to read the dashboard (counts are server-rendered into the markup).
-
SURVEY.mdfor the full tree fits in under 600 lines. -
The scan of the whole Lossless tree finishes in under 5 seconds on a laptop without git (
--no-git), and under 10 with it.
Open questions
-
Name.
survey(verb and noun, already the word the context-vigilance skill uses for "look at what's there"). Alternatives:lookout,vista,overview. Decide before it ships. -
Is "Active" in flight or reference? In this tree it's used both ways (blueprints that are current, plans being worked). First pass: in flight for specs, plans, prompts, issues; reference for blueprints, reminders, habits.
-
Diffs. Comparing two
survey.jsonfiles ("what moved since last Monday") is the obvious second feature. Out of scope for v1, but the JSON should carry agenerated_atand stable doc IDs (site_uuid, else path) so it's possible. -
Publishing. The corpus could publish its global survey to its splash. That needs the
publish:and private-file filters the roll-up already applies. Later. -
GitHub tasks. The
gh-cli-projects-tasks-conventionsskill links tasks to context-v docs; a later version could join open GitHub items to the docs they point at.
Spikes (VP Engineering)
One shared scanner, three throwaway renderers, each trying a different answer to "what should the first screen be?" All three honor the three-mode rule. Code:
agent-skills/survey/scripts/
(
scan.py
is meant to survive; the
spike_*.py
renderers are meant to be compared, then merged or thrown out). No
SKILL.md
yet, so nothing is discoverable as a skill until this spec is signed off.
-
Spike A, Ledger: dense, table-first dashboard. Repo × bucket matrix, sortable doc table, health panel.
-
Spike B, Board: task-first. Kanban columns by lifecycle bucket, plus the open-checkbox list, filtered by repo.
-
Spike C, Map: tree-first. Nested repos as a collapsible map with status-mix bars and freshness heat.
Findings, round one (2026-10-28)
All three were run against four real scopes (this kit alone,
ai-labs
as a tree, the kit's lineage, and the whole Lossless tree) and checked in all three modes with headless-Chrome screenshots.
The scanner earned its keep first.
The first whole-tree run reported 1,651 docs. 619 of those were copies: splash roll-ups at
splash/src/rollup/context-v/<child>/
that mirror child repos' docs into the parent. All three renderers surfaced it as "folders named after repos." The scanner now skips
rollup/
directories and any
context-v/
under a
src/
segment. Real count:
1,032 docs in 50 repos with a
context-v/
(105 repos scanned), in 2.2s.
ai-labs
on its own dropped from 522 to 56.
| Spike | Best at | Weak at | Page size (whole tree) |
| A, Ledger | "Where is the open work piled up?" The repo × lifecycle matrix reads in one glance and every cell clicks through to the doc table |
One-row matrix at repo scope; the health panel is swamped by
no_type
(most docs predate the OKF
type
rule)
|
1.0 MB |
| B, Board | "What should I work on?" The In-flight column (85 items, newest first, with checkbox counts) is the most useful single thing any spike produced |
At tree scope, Open (461) is mostly hygiene, not work; client-site
narratives/
drafts crowd it
|
0.6 MB |
| C, Map | Finding things across 105 repos: nested tree, status-mix bars, search that opens a match's parents | You have to drill to learn what's in flight; the freshness strip is mostly grey because most dates are old | 0.6 MB |
Recommendation (VP Eng):
one page, three tabs, built by one
render.py
, with the
default tab chosen by scope
: Board for
repo
,
lineage
, and
pick
; Ledger for
tree
. Map is always the second tab, with its heat grid capped to the top 20 repos. Keep Board's In-flight column and checkbox rail, Ledger's matrix and click-through table, Map's tree and search; drop the rest.
Before merging, settle these (each spike answered them differently):
-
One definition per metric. "Open tasks" came out as 811 (checkboxes in task folders) in Ledger and Board and 1,406 (every folder) in Map. The spec's definition wins: task folders only.
-
One bucket palette. The spikes gave "open" and "in flight" different colors. Bucket colors become Tier 2 tokens, defined once per mode.
-
Health ranks actionable flags first.
unmapped_status,yaml_error, andstalebeforeno_typeandno_lede, which collapse into one "pre-OKF" line until the tree is migrated. -
Domain folders.
narratives/andslides-content/(deck workspaces) count as reference, not open work, unless their status says otherwise. -
file://links work locally but not from a published page. Fine for v1 (output is local by design); revisit with publishing. -
Known scanner gap: the anchor's
context-v/agent-skillsis itself a submodule, so its skills show as an empty repo. Treat a repo whose root is anagent-skills/folder as skills.
Spike files (
spike_ledger.py
,
spike_board.py
,
spike_map.py
) stay until the merged
render.py
replaces them.
Related
-
Commands and Agent Skills for Context V : the full command catalog this joins
-
Context V Is an OKF Profile : why every doc has a
type, which the survey groups by -
agent-skills/pseudomonorepos/: the tree shape that scopes are built on -
theme-systemandmaintain-splash-pages(Lossless skills): the three-mode contract