Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Audit, plan, scaffold, and safely migrate research project structures across greenfield, existing Git/non-Git repositories, and monorepo subroots. Use for project folders, repository cleanup, source inventory, move maps, naming and storage policy, Python/R/mixed/LaTeX profiles, template provenance, conflict review, applied-move evidence, or rollback. Existing projects are read-only until the user authorizes exact action IDs bound to a plan digest. Preserve uncommitted and untracked work, symlink
.claude/skills/light0305-light-project-structure/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 130% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 74% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 7% | 0% |
Own the visible project tree and its migration evidence. Do not mistake a tidy directory for reproducible research.
Read references/project-lifecycle-resource-map.md before an existing-repository migration. It defines artifacts, policy, access levels, provenance, and cross-skill ownership. Use references/structure-profiles.json for small profile minima and templates/project-policy.template.json for explicit project/file policy. Use scripts/structure_governance_gate.py before delivery to validate profile choice, existing-project read-only safety, template residuals, secret scan, environment doctor, authorization binding, applied-manifest binding, and rollback evidence.
git rm --cached, initialize DVC, rewriteconfiguration, or move a symlink automatically.
--force as consent. The lifecycle has no force bypass..light/ content. memory-pm alone creates or edits passport,project card, decision log, version history, terminology, and handoff files.
UNKNOWN. A path such as data/raw does not prove size,sensitivity, immutability, recomputability, or Git policy.
light.findings.v1; add noSTAGE_GATES, ROUTES, stage number, or back-edge.
reproducibility, statistical validity, or paper quality.
unhandled secret-scan hits, or missing required Python/R/environment checks.
| Situation | Mode | |---|---| | Empty target and the user wants a starting tree | scaffold with one explicit profile | | Existing repository, monorepo package, or non-Git directory | intake, then stop at the decision | | User approved exact moves after seeing the plan | create authorization, then apply | | Applied moves need reversal | rollback from the applied manifest |
Do not scaffold a non-empty directory. Do not retrofit a fixed 23-directory tree onto R, paper-only, mixed-language, custom, or monorepo projects.
Collect or preserve as UNKNOWN:
non-Git directory;
collaborators, CI, license, and retention;
submodules, symlinks, large files, and sensitive path signals.
Choose the smallest profile after inspecting observed technology signatures and the user's declared deliverables:
python-researchr-researchmixed-researchpaper-onlyexisting-customProfiles are extensible minima, not compliance verdicts. The selected profile is not evidence about the project. intake records observed file/config signals separately from policy-declared artifact types, recommends a profile, and fails the governance gate when a different profile has no concrete profile_selection_reason.
Copy the policy template outside the source root, fill known project facts, and add file rules only where there is evidence. Legitimate tracked artifacts include small public fixtures, reviewed golden files, DVC pointers, final paper figures, release artifacts, or audit evidence when project policy requires them. Large/sensitive source data, models, and results usually need DVC/object storage, but require a decision rather than a directory-name verdict.
Run:
textpython scripts/scaffold.py intake <root> --out <evidence-dir> \ --profile mixed-research --policy <project-policy.json>
The command writes evidence to --out and verifies that the source snapshot and Git status did not change.
intake also emits technology signatures, the environment doctor, template residual scan, secret scan, and governance report named in the resource map. Tool checks derive from observed or explicitly declared artifact types, not from the chosen profile alone. If the project requires Python, R, Quarto, DVC, LaTeX, or other local tools, record those requirements in the policy. Use the standalone doctor command only when you need an extra ad-hoc check:
textpython scripts/structure_governance_gate.py --doctor python r
Read the intake artifacts named in the resource map. Check:
UNKNOWN owner, producer, recomputability, sensitivity, classification, target, and policy basis;
evidence from policy.project.artifact_types; the selected profile matches the recommendation or has a concrete user override reason;
../, absolute, drive-letter, UNC, or otherwise root-escaping action pathsare blocked in the dry-run plan and governance gate, not deferred to apply;
whole Git root as its project;
.light/ is preserved and has no move action;raw;doctor are present when relevant; .env ignore is not a secret-scan result.
Present:
git rm --cached, configuration rewrite, and DVC initialization;
Then stop. Ask which action IDs the user authorizes. Do not prewrite their answer.
Run the governance gate on the delivery bundle before presenting a structure as ready:
textpython scripts/structure_governance_gate.py \ --input templates/project-structure-governance.example.json
The bundled example is intentionally fail-closed: it attempts scaffold on an existing R project, leaves template placeholders, reports secret values, misses R, uses force, moves .light/, duplicates action IDs, applies delete, moves a symlink, and risks overwrite.
After the user chooses, create an authorization document:
json{ "schema": "light.project-structure.v2.authorization", "authorization_id": "<user-created stable authorization id>", "plan_sha256": "<exact migration-plan plan_sha256>", "approved_action_ids": ["move-0001"], "authorized_by": "<user-supplied identifier>", "authorized_at": "<YYYY-MM-DD>" }
Do not include blocked or unknown actions. authorization_id and authorized_by must be concrete user-supplied values, not template text; authorized_at cannot be in the future. A changed plan requires fresh authorization. The authorization cannot resolve an overwrite or bypass a symlink block.
textpython scripts/scaffold.py apply \ --plan <migration-plan.json> \ --authorization <authorization.json> \ --manifest-out <applied-manifest.json> \ --as-of <YYYY-MM-DD> python scripts/scaffold.py rollback \ --manifest <applied-manifest.json> \ --rollback-out <rollback-manifest.json>
apply re-verifies source hashes and absolute containment, creates missing target parents, refuses existing targets, moves only ordinary files, records before/after SHA-256, and writes an applied manifest that binds the exact plan file and authorization file by locator plus file SHA-256. A path that escaped the selected root should already have been marked blocked during planning; if one reaches apply anyway, apply still fails closed. rollback verifies target hashes and refuses to overwrite a reappeared source; it uses the applied manifest for safe restoration and does not require the original plan/auth files to still be present.
After rollback:
.light/ content remain byte-identical;Use only on an empty target:
textpython scripts/scaffold.py scaffold <target> --profile r-research --name <name>
The command records profile and generator hashes in .project-structure-provenance.json. It is one-time generation, not safe template updating. For managed template evolution, evaluate Copier or Cruft and review local modifications and conflicts; do not claim drift detection is a merge guarantee.
memory-pm to run pm.py init when .light/ memory is needed; do not doits work here.
data-engineering.experiment-coding.file-reading understand supplied repositories/materials; this skillalone owns moves.
orchestrator consume a delivery if useful; do not create a gate.Run the script self-test:
textpython scripts/scaffold.py --selftest python scripts/structure_governance_gate.py --selftest
It exercises source-read-only intake, a tracked fixture policy, generated environment/template/secret/governance reports, an untracked draft, .light/ preservation, authorization binding, applied-manifest plan/auth file binding, real move/hash evidence, rollback, reapply, non-Git mode, monorepo subroot handling, profile scaffold idempotence, and a best-effort Windows symlink branch.
Before delivery, verify:
file by locator and file SHA-256.
.light/ content survived move and rollback.reason are present; observed/declared signatures support the profile, and R/Python requirements are checked when claimed.
structure_governance_gate.py passes for the actual delivery bundle.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→pass | 11,179 | 5,029 | -55% | 1 | 1 | 0% | 1,493 | 3,429 | +130% | 0 | 0 | — |
case-10 | fail→pass | 14,419 | 7,641 | -47% | 1 | 1 | 0% | 2,194 | 3,823 | +74% | 0 | 0 | — |
case-13 | pass→pass | 14,371 | 6,291 | -56% | 1 | 1 | 0% | 2,332 | 3,671 | +57% | 0 | 0 | — |
case-14 | pass→pass | 15,381 | 6,462 | -58% | 1 | 1 | 0% | 2,091 | 3,664 | +75% | 0 | 0 | — |
case-15 | fail→pass | 11,342 | 4,375 | -61% | 1 | 1 | 0% | 1,687 | 3,310 | +96% | 0 | 0 | — |
case-01 | fail→fail | 20,723 | 12,434 | -40% | 1 | 1 | 0% | 3,659 | 4,119 | +13% | 0 | 0 | — |
case-02 | fail→fail | 21,082 | 8,830 | -58% | 1 | 1 | 0% | 2,919 | 3,009 | +3% | 0 | 0 | — |
case-03 | fail→fail | 20,405 | 8,443 | -59% | 1 | 1 | 0% | 3,353 | 3,306 | -1% | 0 | 0 | — |
case-04 | fail→pass | 9,687 | 9,927 | +2% | 1 | 1 | 0% | 1,507 | 3,574 | +137% | 0 | 0 | — |
case-11 | fail→pass | 18,706 | 2,238 | -88% | 1 | 1 | 0% | 2,769 | 2,954 | +7% | 0 | 0 | — |
case-05 | fail→pass | 16,668 | 6,596 | -60% | 1 | 1 | 0% | 1,070 | 3,843 | +259% | 0 | 0 | — |
case-06 | pass→pass | 13,304 | 5,824 | -56% | 1 | 1 | 0% | 1,818 | 3,541 | +95% | 0 | 0 | — |
case-07 | fail→pass | 17,962 | 8,187 | -54% | 1 | 1 | 0% | 3,129 | 3,942 | +26% | 0 | 0 | — |
case-08 | fail→pass | 12,428 | 3,913 | -69% | 1 | 1 | 0% | 1,956 | 3,290 | +68% | 0 | 0 | — |
case-09 | fail→pass | 9,079 | 3,490 | -62% | 1 | 1 | 0% | 1,363 | 3,224 | +137% | 0 | 0 | — |
case-16 | fail→pass | 15,537 | 4,824 | -69% | 1 | 1 | 0% | 2,487 | 3,389 | +36% | 0 | 0 | — |
case-17 | fail→pass | 13,150 | 4,207 | -68% | 1 | 1 | 0% | 2,065 | 3,267 | +58% | 0 | 0 | — |
case-18 | fail→pass | 11,227 | 9,060 | -19% | 1 | 1 | 0% | 1,808 | 4,284 | +137% | 0 | 0 | — |
case-19 | fail→pass | 12,071 | 5,311 | -56% | 1 | 1 | 0% | 1,854 | 3,430 | +85% | 0 | 0 | — |
case-20 | fail→pass | 13,743 | 3,661 | -73% | 1 | 1 | 0% | 2,213 | 3,262 | +47% | 0 | 0 | — |
case-21 | fail→pass | 19,686 | 10,634 | -46% | 1 | 1 | 0% | 3,202 | 4,286 | +34% | 0 | 0 | — |
case-22 | fail→fail | 22,898 | 19,391 | -15% | 1 | 1 | 0% | 4,437 | 5,200 | +17% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +68 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.