Survey
Produce a fast architecture survey of the current repository without reading source implementation files.
Hard Gate
The output is research, not canonical Feature intent. Do not write Feature, Plan, or code artifacts from this skill. Do not invoke specstudio:retrofit automatically.
When To Use
- A user wants a cheap architecture overview of an existing repository.
- A user is deciding whether retrofit is worth running.
- A future
specstudio:retrofit run needs a survey-output-schema-v1 input.
Skip when the user wants behavior, requirements, or acceptance criteria derived from code. That is retrofit, not survey.
Inputs and flags
Supported invocations:
specstudio:survey
specstudio:survey --scope <subdir>
specstudio:survey --slug <slug>
specstudio:survey --output-dir <path>
specstudio:survey --json
Flag behavior:
--scope <subdir> limits the file inventory and manifest reads to that subtree, while repo state still records the whole-repo HEAD.
--slug <slug> overrides slug derivation.
--output-dir <path> overrides the default spec/research/.
--json writes only the JSON artifact and skips Markdown rendering.
Unknown flags are refused.
Step 1 - Pre-flight
- Determine repo root with
git rev-parse --show-toplevel. If that fails, use the current directory and record git_available: false.
- Resolve
scope from --scope, defaulting to repo root.
- Derive
slug from, in order:
package.json#name
pyproject.toml [project].name
go.mod module basename
Cargo.toml [package].name
- repository directory basename
--slug override, if supplied
- Sanitize slug to lowercase
a-z0-9-, collapse repeated dashes, and trim leading/trailing dashes.
- Set output paths:
- JSON:
<output-dir>/<slug>-survey.json
- Markdown:
<output-dir>/<slug>-survey.md
- Default output dir:
spec/research/
Step 2 - File inventory
Prefer:
git ls-files
When scoped, filter the inventory to paths under the scope.
If git is unavailable, use find and exclude obvious generated or dependency directories:
.git
node_modules
.venv, venv, __pycache__
dist, build, target, .next, .turbo
.cache, .pytest_cache
Record the scan method as git-ls-files or find-fallback.
Step 3 - Repo state
When git is available, record:
head_sha: git rev-parse HEAD
dirty_tree: whether git status --short is non-empty
status_short: literal lines from git status --short
When git is unavailable, record:
git_available: false
head_sha: null
dirty_tree: null
status_short: []
Step 4 - Allowed manifest reads only
Read content only from the operational allowlist at skills/shared/survey-manifest-allowlist.md. The current v1 categories are:
- JavaScript / TypeScript:
package.json, pnpm-workspace.yaml, lerna.json, nx.json, turbo.json, tsconfig*.json, next.config.*, vite.config.*, nuxt.config.*, astro.config.*, package-lock.json, pnpm-lock.yaml, yarn.lock
- Python:
pyproject.toml, setup.py, setup.cfg, requirements*.txt, poetry.lock, Pipfile, Pipfile.lock, tox.ini
- Go:
go.mod, go.sum, go.work
- Rust:
Cargo.toml, Cargo.lock
- Other languages:
Gemfile, composer.json, *.csproj, *.sln, pom.xml, build.gradle*
- Infra and ops:
docker-compose*.yml, Dockerfile, terraform/*.tf, serverless.yml, helm/Chart.yaml, kustomization.yaml
- CI and tooling:
.github/workflows/*.yml, .gitlab-ci.yml, .circleci/config.yml, Makefile, justfile, Taskfile.yml
- Release and packaging:
.goreleaser.yml, .goreleaser.yaml, release-please-config.json, .release-please-manifest.json, .releaserc, .releaserc.json, .changeset/config.json
- Runtime pinning:
.tool-versions, .nvmrc, .python-version, .ruby-version
- SpecScore:
specscore.yaml
- Docs: root
README*, ARCHITECTURE*, CONTRIBUTING*; top-level docs/** filenames only unless a doc file is small enough to read under the size cap
Generated release outputs remain excluded. Do not read dist/**, packaged archives, generated checksums, generated changelogs, or binary artifacts as release manifests.
Size cap for any single text read: 80 KB. If an allowlisted file exceeds the cap, do not read it. Record a warning: skipped due to size.
Step 5 - Monorepo detection
Detect monorepo signals before synthesis:
pnpm-workspace.yaml
nx.json
lerna.json
turbo.json
go.work
- Cargo workspace members in root
Cargo.toml
- multiple root package directories indicated by manifests
If monorepo signals are present and no --scope was supplied:
- Refuse to synthesize a whole-repo survey.
- Identify the signal paths.
- Recommend rerunning with
specstudio:survey --scope <subdir>.
- Do not write artifacts.
Step 6 - Build the structured survey
Construct a JSON object with this minimum shape:
{
"schema": "survey-output-schema-v1",
"slug": "<slug>",
"scope": "<scope-or-null>",
"scan_method": "git-ls-files",
"repo_state": {
"git_available": true,
"head_sha": "<sha>",
"dirty_tree": false,
"status_short": []
},
"file_inventory_summary": {
"total_files": 0,
"by_extension": {},
"top_level_dirs": []
},
"manifest_inventory": [],
"detected_frameworks": [],
"architecture_summary": "",
"directory_clusters": [],
"research_zones": [],
"sensitive_path_inventory": [],
"warnings": []
}
Populate:
file_inventory_summary: counts by extension, top-level directory counts, test path counts, docs path counts.
manifest_inventory: allowlisted files read, skipped, or absent.
detected_frameworks: framework/tool signals inferred from manifests and filenames.
directory_clusters: hierarchical directory groups, max depth 3, max 12 children per parent.
research_zones: proposed bounded zones for retrofit researchers, each with path roots, file counts, and one-line purpose.
sensitive_path_inventory: filename-pattern hints only.
warnings: dirty tree, skipped oversized manifests, monorepo refusal signals when scoped, ambiguous slug signals.
Do not invent behavior from source. If a conclusion depends only on file names or manifests, phrase it as inferred.
Step 7 - Sensitive path inventory
Flag filename-pattern hints for:
.env*
secrets/**
*.pem
*.key
**/fixtures/**
- git-crypt markers
- submodule entries
- LFS pointer-looking files
- lockfile mismatch hints, such as multiple package-manager lockfiles
Label the section explicitly: "Filename-pattern hints only; not a content secret scan."
Step 8 - Write JSON first
Create the output directory if needed. Write the JSON artifact first. Sort object keys where practical and keep arrays in deterministic path order.
If --json is set, skip Markdown rendering and go to indexing/lint/staging.
Step 9 - Render Markdown from JSON
Render Markdown from the JSON artifact. The Markdown must contain:
# Survey: <title>
**Status:** Current
**Date:** <YYYY-MM-DD>
**Repo SHA:** <sha-or-unavailable>
**Scope:** <scope-or-repo-root>
**JSON:** <relative path to json>
## Summary
## Architecture
## Directory Clusters
## Research Zones
## Detected Frameworks
## Sensitive Path Inventory
## Warnings
## Open Questions
- Footer:
*This document follows the https://specscore.md/research-artifact-specification*
Use Mermaid diagrams only when they add clarity. Always include text lists so the artifact remains useful without Mermaid rendering.
Step 10 - Research index
For default output under spec/research/, ensure spec/research/README.md exists.
If absent, create:
# Research
Research artifacts produced by SpecStudio skills.
## Contents
| Artifact | Description |
|---|---|
## Open Questions
None at this time.
---
*This document follows the https://specscore.md/index-specification*
Add or update one row for the survey:
| [<slug>-survey](<slug>-survey.md) | Architecture survey for `<scope-or-repo>`. |
Do not duplicate rows for the same survey slug.
Step 11 - Lint and fix once
Run:
specscore spec lint
If lint fails, make one focused fix pass for the generated artifacts and rerun lint. If violations remain, surface them with paths and stop.
Step 12 - Stage
Stage all generated or updated files:
git add <json> <markdown-if-written> <research-index-if-updated>
Never commit. Report the staged paths.
Output summary
End with:
- JSON path
- Markdown path, unless
--json
- Research index path, if updated
- Lint result
- Staged paths
- Any warnings, especially dirty tree and sensitive-path hints
Relationship to retrofit
specstudio:retrofit consumes the JSON artifact. Survey does not invoke retrofit automatically. If the user wants to continue, recommend running retrofit with the generated JSON path once retrofit ships.
1---2name: survey3description: Produces a fast architecture survey for an existing codebase without reading source implementation files. Scans the file tree, reads only allowlisted structural manifests, writes JSON-first survey artifacts under spec/research/, and stages the results. Use before retrofit or when the user wants a cheap architecture overview of an existing repo. Trigger: "specstudio:survey", "/survey", "/specstudio:survey", "survey this repo", "architecture survey", "map this repo".4---56# Survey78Produce a fast architecture survey of the current repository without reading source implementation files.910## Hard Gate1112<HARD-GATE>13This skill MUST NOT read source implementation file contents. It may list source file paths and count them, but it must not open implementation files such as `*.js`, `*.ts`, `*.py`, `*.go`, `*.rs`, `*.java`, `*.cs`, `*.rb`, `*.php`, `*.swift`, or `*.kt`, unless the file is explicitly allowed as a structural manifest below.1415The output is research, not canonical Feature intent. Do not write Feature, Plan, or code artifacts from this skill. Do not invoke `specstudio:retrofit` automatically.16</HARD-GATE>1718## When To Use1920- A user wants a cheap architecture overview of an existing repository.21- A user is deciding whether retrofit is worth running.22- A future `specstudio:retrofit` run needs a `survey-output-schema-v1` input.2324Skip when the user wants behavior, requirements, or acceptance criteria derived from code. That is retrofit, not survey.2526## Inputs and flags2728Supported invocations:2930- `specstudio:survey`31- `specstudio:survey --scope <subdir>`32- `specstudio:survey --slug <slug>`33- `specstudio:survey --output-dir <path>`34- `specstudio:survey --json`3536Flag behavior:3738- `--scope <subdir>` limits the file inventory and manifest reads to that subtree, while repo state still records the whole-repo HEAD.39- `--slug <slug>` overrides slug derivation.40- `--output-dir <path>` overrides the default `spec/research/`.41- `--json` writes only the JSON artifact and skips Markdown rendering.4243Unknown flags are refused.4445## Step 1 - Pre-flight46471. Determine repo root with `git rev-parse --show-toplevel`. If that fails, use the current directory and record `git_available: false`.482. Resolve `scope` from `--scope`, defaulting to repo root.493. Derive `slug` from, in order:50 - `package.json#name`51 - `pyproject.toml [project].name`52 - `go.mod` module basename53 - `Cargo.toml [package].name`54 - repository directory basename55 - `--slug` override, if supplied564. Sanitize slug to lowercase `a-z0-9-`, collapse repeated dashes, and trim leading/trailing dashes.575. Set output paths:58 - JSON: `<output-dir>/<slug>-survey.json`59 - Markdown: `<output-dir>/<slug>-survey.md`60 - Default output dir: `spec/research/`6162## Step 2 - File inventory6364Prefer:6566```bash67git ls-files68```6970When scoped, filter the inventory to paths under the scope.7172If git is unavailable, use `find` and exclude obvious generated or dependency directories:7374- `.git`75- `node_modules`76- `.venv`, `venv`, `__pycache__`77- `dist`, `build`, `target`, `.next`, `.turbo`78- `.cache`, `.pytest_cache`7980Record the scan method as `git-ls-files` or `find-fallback`.8182## Step 3 - Repo state8384When git is available, record:8586- `head_sha`: `git rev-parse HEAD`87- `dirty_tree`: whether `git status --short` is non-empty88- `status_short`: literal lines from `git status --short`8990When git is unavailable, record:9192- `git_available: false`93- `head_sha: null`94- `dirty_tree: null`95- `status_short: []`9697## Step 4 - Allowed manifest reads only9899Read content only from the operational allowlist at [`skills/shared/survey-manifest-allowlist.md`](../shared/survey-manifest-allowlist.md). The current v1 categories are:100101- JavaScript / TypeScript: `package.json`, `pnpm-workspace.yaml`, `lerna.json`, `nx.json`, `turbo.json`, `tsconfig*.json`, `next.config.*`, `vite.config.*`, `nuxt.config.*`, `astro.config.*`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`102- Python: `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements*.txt`, `poetry.lock`, `Pipfile`, `Pipfile.lock`, `tox.ini`103- Go: `go.mod`, `go.sum`, `go.work`104- Rust: `Cargo.toml`, `Cargo.lock`105- Other languages: `Gemfile`, `composer.json`, `*.csproj`, `*.sln`, `pom.xml`, `build.gradle*`106- Infra and ops: `docker-compose*.yml`, `Dockerfile`, `terraform/*.tf`, `serverless.yml`, `helm/Chart.yaml`, `kustomization.yaml`107- CI and tooling: `.github/workflows/*.yml`, `.gitlab-ci.yml`, `.circleci/config.yml`, `Makefile`, `justfile`, `Taskfile.yml`108- Release and packaging: `.goreleaser.yml`, `.goreleaser.yaml`, `release-please-config.json`, `.release-please-manifest.json`, `.releaserc`, `.releaserc.json`, `.changeset/config.json`109- Runtime pinning: `.tool-versions`, `.nvmrc`, `.python-version`, `.ruby-version`110- SpecScore: `specscore.yaml`111- Docs: root `README*`, `ARCHITECTURE*`, `CONTRIBUTING*`; top-level `docs/**` filenames only unless a doc file is small enough to read under the size cap112113Generated release outputs remain excluded. Do not read `dist/**`, packaged archives, generated checksums, generated changelogs, or binary artifacts as release manifests.114115Size cap for any single text read: 80 KB. If an allowlisted file exceeds the cap, do not read it. Record a warning: `skipped due to size`.116117## Step 5 - Monorepo detection118119Detect monorepo signals before synthesis:120121- `pnpm-workspace.yaml`122- `nx.json`123- `lerna.json`124- `turbo.json`125- `go.work`126- Cargo workspace members in root `Cargo.toml`127- multiple root package directories indicated by manifests128129If monorepo signals are present and no `--scope` was supplied:1301311. Refuse to synthesize a whole-repo survey.1322. Identify the signal paths.1333. Recommend rerunning with `specstudio:survey --scope <subdir>`.1344. Do not write artifacts.135136## Step 6 - Build the structured survey137138Construct a JSON object with this minimum shape:139140```json141{142 "schema": "survey-output-schema-v1",143 "slug": "<slug>",144 "scope": "<scope-or-null>",145 "scan_method": "git-ls-files",146 "repo_state": {147 "git_available": true,148 "head_sha": "<sha>",149 "dirty_tree": false,150 "status_short": []151 },152 "file_inventory_summary": {153 "total_files": 0,154 "by_extension": {},155 "top_level_dirs": []156 },157 "manifest_inventory": [],158 "detected_frameworks": [],159 "architecture_summary": "",160 "directory_clusters": [],161 "research_zones": [],162 "sensitive_path_inventory": [],163 "warnings": []164}165```166167Populate:168169- `file_inventory_summary`: counts by extension, top-level directory counts, test path counts, docs path counts.170- `manifest_inventory`: allowlisted files read, skipped, or absent.171- `detected_frameworks`: framework/tool signals inferred from manifests and filenames.172- `directory_clusters`: hierarchical directory groups, max depth 3, max 12 children per parent.173- `research_zones`: proposed bounded zones for retrofit researchers, each with path roots, file counts, and one-line purpose.174- `sensitive_path_inventory`: filename-pattern hints only.175- `warnings`: dirty tree, skipped oversized manifests, monorepo refusal signals when scoped, ambiguous slug signals.176177Do not invent behavior from source. If a conclusion depends only on file names or manifests, phrase it as inferred.178179## Step 7 - Sensitive path inventory180181Flag filename-pattern hints for:182183- `.env*`184- `secrets/**`185- `*.pem`186- `*.key`187- `**/fixtures/**`188- git-crypt markers189- submodule entries190- LFS pointer-looking files191- lockfile mismatch hints, such as multiple package-manager lockfiles192193Label the section explicitly: "Filename-pattern hints only; not a content secret scan."194195## Step 8 - Write JSON first196197Create the output directory if needed. Write the JSON artifact first. Sort object keys where practical and keep arrays in deterministic path order.198199If `--json` is set, skip Markdown rendering and go to indexing/lint/staging.200201## Step 9 - Render Markdown from JSON202203Render Markdown from the JSON artifact. The Markdown must contain:2042051. `# Survey: <title>`2062. `**Status:** Current`2073. `**Date:** <YYYY-MM-DD>`2084. `**Repo SHA:** <sha-or-unavailable>`2095. `**Scope:** <scope-or-repo-root>`2106. `**JSON:** <relative path to json>`2117. `## Summary`2128. `## Architecture`2139. `## Directory Clusters`21410. `## Research Zones`21511. `## Detected Frameworks`21612. `## Sensitive Path Inventory`21713. `## Warnings`21814. `## Open Questions`21915. Footer: `*This document follows the https://specscore.md/research-artifact-specification*`220221Use Mermaid diagrams only when they add clarity. Always include text lists so the artifact remains useful without Mermaid rendering.222223## Step 10 - Research index224225For default output under `spec/research/`, ensure `spec/research/README.md` exists.226227If absent, create:228229```markdown230# Research231232Research artifacts produced by SpecStudio skills.233234## Contents235236| Artifact | Description |237|---|---|238239## Open Questions240241None at this time.242243---244*This document follows the https://specscore.md/index-specification*245```246247Add or update one row for the survey:248249```markdown250| [<slug>-survey](<slug>-survey.md) | Architecture survey for `<scope-or-repo>`. |251```252253Do not duplicate rows for the same survey slug.254255## Step 11 - Lint and fix once256257Run:258259```bash260specscore spec lint261```262263If lint fails, make one focused fix pass for the generated artifacts and rerun lint. If violations remain, surface them with paths and stop.264265## Step 12 - Stage266267Stage all generated or updated files:268269```bash270git add <json> <markdown-if-written> <research-index-if-updated>271```272273Never commit. Report the staged paths.274275## Output summary276277End with:278279- JSON path280- Markdown path, unless `--json`281- Research index path, if updated282- Lint result283- Staged paths284- Any warnings, especially dirty tree and sensitive-path hints285286## Relationship to retrofit287288`specstudio:retrofit` consumes the JSON artifact. Survey does not invoke retrofit automatically. If the user wants to continue, recommend running retrofit with the generated JSON path once retrofit ships.