mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
chore: gitignore .claude (local Claude Code tooling, not published)
.claude/ (the tools-registry-context + dev-local skills) is local dev tooling now — untracked from the repo and added to .gitignore. The design docs it manages stay public in docs/context/. Fix the AGENTS/CONTRIBUTING/README references that pointed at .claude/skills.
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: dev-local
|
||||
description: One-command local dev stack for tools-registry. Use when asked to "start the dev server", "run treg locally", "test login locally", "bring the stack up", or before any manual/browser test against localhost.
|
||||
---
|
||||
|
||||
# dev-local — the local treg stack in one command
|
||||
|
||||
`scripts/dev-local.sh` runs the FastAPI server in a tmux session with dev-safe
|
||||
settings, and gives you a sandboxed CLI that never touches `~/.treg/config.json`.
|
||||
|
||||
| Service | Command (managed by the script) | Port |
|
||||
|---|---|---|
|
||||
| treg server | `uv run python -m treg --reload` + `TREG_EMAIL_DEV_MODE=true`, own sqlite `treg-dev.db` | 18790 |
|
||||
|
||||
No infra deps (sqlite). Prerequisites: `tmux`, `uv` (the script runs `uv sync` if `.venv` is missing).
|
||||
|
||||
## Subcommands
|
||||
|
||||
```
|
||||
scripts/dev-local.sh up # start (idempotent) — prints URLs when healthy
|
||||
scripts/dev-local.sh down # stop the session
|
||||
scripts/dev-local.sh status # windows + port check
|
||||
scripts/dev-local.sh logs # last 200 lines of the server window
|
||||
scripts/dev-local.sh restart # respawn the server window
|
||||
scripts/dev-local.sh attach # attach to tmux
|
||||
scripts/dev-local.sh cli <args> # working-tree treg CLI, sandboxed HOME, pre-pointed at localhost
|
||||
scripts/dev-local.sh reset # down + wipe treg-dev.db and the CLI sandbox
|
||||
```
|
||||
|
||||
`cli` is the key trick for login testing: `scripts/dev-local.sh cli login` runs the
|
||||
repo's CLI against localhost with `HOME=scripts/.dev-home`, so the real
|
||||
`~/.treg/config.json` (usually pointing at production) is never overwritten.
|
||||
Email OTP dev mode is on — codes appear in the login page / API response, no mail sender needed.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Port 18790 in use, no session** → something else owns it: `lsof -i :18790`.
|
||||
- **Server window died** → `scripts/dev-local.sh logs` for the traceback, then `restart`.
|
||||
- **Stale dev state / want a fresh DB** → `scripts/dev-local.sh reset` then `up`.
|
||||
@@ -1,55 +0,0 @@
|
||||
# MAINTAINING — keep the tools-registry fragment set (and this skill) current
|
||||
|
||||
The "sub-skill": the protocol for updating `docs/context/` fragments after code changes. Read it when
|
||||
running `/tools-registry-context sync`. (This system was scaffolded by the global `codemap` skill.)
|
||||
|
||||
## Scope boundary (read first)
|
||||
|
||||
This skill documents **only `docs/context/`**. Session **handoffs and plans live elsewhere** (e.g.
|
||||
`.context/`) and are explicitly **not** part of the fragment set — never read them as input, fold them
|
||||
into a fragment, or sweep them into the index. `build-map.py` walks `docs/context/` only, by design.
|
||||
|
||||
## The mental model
|
||||
|
||||
```
|
||||
docs/context/**/*.md ← the fragments (SOURCE OF TRUTH; human-browsable, versioned)
|
||||
frontmatter: title / status / sources: [...] / related: [...]
|
||||
│ scripts/build-map.py reads all frontmatter + fragments.config →
|
||||
▼
|
||||
docs/context/README.md (human index, grouped by category)
|
||||
.claude/skills/tools-registry-context/MAP.md (source file → fragment, for routing + drift)
|
||||
```
|
||||
|
||||
Edit **fragments**, never the generated files (they carry a "GENERATED" banner and are overwritten).
|
||||
|
||||
## Sync workflow
|
||||
|
||||
1. **Scope:** default range `origin/main..HEAD`. Override with an explicit range if needed.
|
||||
2. **Detect drift:** `bash .claude/skills/tools-registry-context/scripts/drift.sh [range]` → (a) changed
|
||||
source → documenting fragment(s); (b) changed source with **no** fragment.
|
||||
3. **For each affected fragment:** read it + `git diff <range> -- <file>`; update prose; re-grep moved
|
||||
cited symbols still exist (grep them); add new files to `sources:`. Citations are **symbols, not
|
||||
line numbers**, so an unrelated insert elsewhere does NOT make this fragment drift — only a genuine
|
||||
behavior/rename change does. (This is why sync stays fast.)
|
||||
4. **For gaps:** fold into an existing fragment (+ `sources:`), or write a new fragment from
|
||||
`fragment.md.tmpl` in the right category folder (~70–130 lines, cited, present-tense).
|
||||
5. **Show before applying.** Get user approval; apply only what's approved.
|
||||
6. **Regenerate:** `python3 .claude/skills/tools-registry-context/scripts/build-map.py` — warns on any
|
||||
fragment missing frontmatter (exit 1). Fix before committing.
|
||||
7. **Commit with the code.** `docs(context):` scope; follow the repo's commit conventions.
|
||||
|
||||
## Fragment conventions (must hold for the tooling)
|
||||
|
||||
- **Frontmatter required** on every fragment: `title`, `status`
|
||||
(shipped | reference | foundational | living | archived | backlog), `sources:` (repo-relative; `[]`
|
||||
for narrative/reference), `related:` (other fragment paths).
|
||||
- **Categories = subfolders** under `docs/context/`, ordered/labeled in `fragments.config`.
|
||||
- **One subsystem per fragment.** Split anything past ~150 lines.
|
||||
|
||||
## Evolving this skill / config
|
||||
|
||||
- New category → add `{dir,label}` to `fragments.config` `categories` (controls index order + heading).
|
||||
- New source area → add a pathspec to `source_globs` (and extension to `source_exts`) in the config.
|
||||
- Pull upstream script improvements → re-run `codemap` in `refresh` mode (re-copies `build-map.py` /
|
||||
`drift.sh` from the global skill without touching your fragments or config).
|
||||
- Keep `SKILL.md` thin (a router). Detail belongs here or in fragments.
|
||||
@@ -1,69 +0,0 @@
|
||||
# tools-registry context MAP
|
||||
|
||||
<!-- GENERATED by scripts/build-map.py — do not edit by hand; edit fragment frontmatter instead -->
|
||||
|
||||
Reverse index: **source file → the fragment(s) that document it.** Used by the
|
||||
`tools-registry-context` skill to load the right fragment when you touch a file and to detect drift.
|
||||
Regenerate via `scripts/build-map.py`.
|
||||
|
||||
## Source file → fragment(s)
|
||||
|
||||
| Source file | Documented in |
|
||||
|---|---|
|
||||
| `README.md` | foundation/charter.md |
|
||||
| `external:meetings/2026-06-30-jason-tools-registry.md` | foundation/charter.md, reference/glossary.md |
|
||||
| `render.yaml` | ops/deploy.md |
|
||||
| `src/treg/__main__.py` | ops/deploy.md |
|
||||
| `src/treg/api.py` | architecture/multi-tenancy.md, architecture/proxy-model.md, architecture/super-admin.md, interface/api.md, interface/dashboard.md, interface/landing-sandbox.md |
|
||||
| `src/treg/audit.py` | architecture/data-model.md, ops/deploy.md |
|
||||
| `src/treg/cli.py` | interface/cli.md, interface/onboarding.md, interface/shell.md |
|
||||
| `src/treg/config.py` | architecture/super-admin.md, ops/deploy.md |
|
||||
| `src/treg/convert.py` | interface/cli.md |
|
||||
| `src/treg/crypto.py` | architecture/auth-secrets.md |
|
||||
| `src/treg/db.py` | architecture/data-model.md, architecture/multi-tenancy.md, ops/deploy.md |
|
||||
| `src/treg/demo.py` | interface/onboarding.md |
|
||||
| `src/treg/egress.py` | architecture/local-run.md |
|
||||
| `src/treg/email.py` | interface/api.md, ops/deploy.md |
|
||||
| `src/treg/fsjail.py` | architecture/local-run.md |
|
||||
| `src/treg/health.py` | architecture/auth-secrets.md |
|
||||
| `src/treg/injectors.py` | architecture/auth-secrets.md |
|
||||
| `src/treg/localrun.py` | architecture/local-run.md |
|
||||
| `src/treg/models.py` | architecture/data-model.md, architecture/multi-tenancy.md |
|
||||
| `src/treg/oauth.py` | architecture/auth-secrets.md |
|
||||
| `src/treg/providers.py` | interface/env-import.md |
|
||||
| `src/treg/proxy.py` | architecture/proxy-model.md |
|
||||
| `src/treg/ratestore.py` | architecture/data-model.md, interface/api.md |
|
||||
| `src/treg/runner.py` | interface/api.md |
|
||||
| `src/treg/sandbox.py` | interface/landing-sandbox.md |
|
||||
| `src/treg/session.py` | interface/dashboard.md |
|
||||
| `src/treg/shell.py` | interface/shell.md |
|
||||
| `src/treg/skills.py` | interface/env-import.md |
|
||||
| `src/treg/web/index.html` | interface/dashboard.md, interface/landing-sandbox.md, interface/onboarding.md |
|
||||
| `src/treg/web/install.sh` | interface/landing-sandbox.md |
|
||||
| `src/treg/web/skill.md` | interface/skill.md |
|
||||
| `src/treg/web/tour/index.html` | interface/dashboard.md |
|
||||
| `src/treg/web/tour/tour.js` | interface/dashboard.md |
|
||||
| `src/treg/web/tutorial.html` | interface/dashboard.md |
|
||||
| `src/treg/web/tutorial.js` | interface/dashboard.md |
|
||||
|
||||
## Fragment → sources
|
||||
|
||||
| Fragment | Sources |
|
||||
|---|---|
|
||||
| `architecture/auth-secrets.md` | `injectors.py`, `crypto.py`, `oauth.py`, `health.py` |
|
||||
| `architecture/data-model.md` | `models.py`, `db.py`, `audit.py`, `ratestore.py` |
|
||||
| `architecture/local-run.md` | `localrun.py`, `egress.py`, `fsjail.py` |
|
||||
| `architecture/multi-tenancy.md` | `models.py`, `api.py`, `db.py` |
|
||||
| `architecture/proxy-model.md` | `proxy.py`, `api.py` |
|
||||
| `architecture/super-admin.md` | `api.py`, `config.py` |
|
||||
| `foundation/charter.md` | `2026-06-30-jason-tools-registry.md`, `README.md` |
|
||||
| `interface/api.md` | `api.py`, `email.py`, `runner.py`, `ratestore.py` |
|
||||
| `interface/cli.md` | `cli.py`, `convert.py` |
|
||||
| `interface/dashboard.md` | `index.html`, `tutorial.js`, `tutorial.html`, `tour.js`, `index.html`, `api.py`, `session.py` |
|
||||
| `interface/env-import.md` | `providers.py`, `skills.py` |
|
||||
| `interface/landing-sandbox.md` | `sandbox.py`, `api.py`, `index.html`, `install.sh` |
|
||||
| `interface/onboarding.md` | `demo.py`, `cli.py`, `index.html` |
|
||||
| `interface/shell.md` | `shell.py`, `cli.py` |
|
||||
| `interface/skill.md` | `skill.md` |
|
||||
| `ops/deploy.md` | `__main__.py`, `config.py`, `db.py`, `email.py`, `audit.py`, `render.yaml` |
|
||||
| `reference/glossary.md` | `2026-06-30-jason-tools-registry.md` |
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
name: tools-registry-context
|
||||
description: tools-registry context + doc upkeep. Use to warm up a fresh session (orient on the architecture + recent commits) or when working on tools-registry — changing code, rules, content, data, or process (proxy · auth/secrets · API · CLI · the registry skill) — loads the relevant fragment(s) from docs/context so you act with accurate, cited context. Accepts an optional focus query (e.g. `/tools-registry-context <area>`). Also runs `/tools-registry-context sync` to update the doc fragments after changes (show → approve → apply). Mention it whenever a push to the main branch is near.
|
||||
argument-hint: "[sync | <focus query>]"
|
||||
---
|
||||
|
||||
# tools-registry-context — load the right design fragment, keep docs honest
|
||||
|
||||
tools-registry's design docs are **fragments** under `docs/context/` (one per subsystem), each declaring the
|
||||
source files it covers in frontmatter. [`MAP.md`](MAP.md) (next to this file) is the generated reverse
|
||||
index: **source file → the fragment that documents it.** This skill has two modes.
|
||||
|
||||
## Mode A — LOAD context (default). Adapt to *when* you're called:
|
||||
|
||||
**Cold start (a fresh session, little/no prior context) → warm up.** Read
|
||||
[`docs/context/README.md`](../../../docs/context/README.md) (the index), then the fragments that matter
|
||||
(the `foundation`-style overview fragments plus whichever subsystems the query or repo state points at).
|
||||
Run `git log --oneline -15` and `git status` to catch recent commits + uncommitted work. Then give a
|
||||
short orientation — what tools-registry is, the subsystems in play, what changed recently — and say you're ready.
|
||||
|
||||
**Mid-chat (a task/topic is already in play) → stay targeted.** Map the artifacts/topic at hand via
|
||||
[`MAP.md`](MAP.md)'s "Source file → fragment(s)" table, read **just** those fragment(s), and proceed.
|
||||
Don't re-warm the whole tree.
|
||||
|
||||
**A focus query (`/tools-registry-context <query>`) always wins** — use it to pick the fragment(s) and
|
||||
focus the warm-up on that area, in either case.
|
||||
|
||||
Always: read the data model / behavior / RCAs / symbol anchors before changing anything; load only
|
||||
what's relevant (never dump the whole tree); if an artifact you touch has **no** fragment, note it as a
|
||||
gap for Mode B.
|
||||
|
||||
## Mode B — SYNC docs (`/tools-registry-context sync`, or before a push)
|
||||
|
||||
Before a push to the main branch, **remind the user** to run this; proceed only on their yes. Then
|
||||
follow [`MAINTAINING.md`](MAINTAINING.md) — the short version:
|
||||
|
||||
1. **Detect drift:** `bash .claude/skills/tools-registry-context/scripts/drift.sh` (defaults to
|
||||
`origin/main..HEAD`). It prints, per changed source, which fragment(s) document it — plus gaps.
|
||||
2. **Draft updates:** for each affected fragment, read it + the diff; update prose to match changed
|
||||
behavior and verify cited **symbols** still exist (no line-number chasing — symbols don't drift).
|
||||
New subsystem with no fragment → draft a new fragment from `fragment.md.tmpl`.
|
||||
3. **Show, then apply:** present proposed changes and get approval **before** writing.
|
||||
4. **Regenerate:** `python3 .claude/skills/tools-registry-context/scripts/build-map.py` (rewrites README + MAP).
|
||||
5. **Commit together:** doc updates ride with the code in the same commit/push.
|
||||
|
||||
## Invariants
|
||||
|
||||
- **Docs are the source of truth; this skill is a lens.** Fragments live in `docs/context/`; never
|
||||
duplicate them into the skill. The skill holds only the generated `MAP.md` + scripts + config.
|
||||
- **Frontmatter drives everything.** A fragment's `sources:` feeds the index, the MAP, and drift. When a
|
||||
fragment starts covering a new file, add it to `sources:` and rerun `build-map.py`.
|
||||
- **Cite stable symbols, not line numbers.** Anchor every claim to a grep-able symbol; bare line
|
||||
numbers drift on every edit and slow sync. Describe what shipped, not intent.
|
||||
- **No automation behind the user's back.** Sync is reminder → approve → apply. There is no git hook.
|
||||
- **Handoffs and plans are NOT documentation.** They live outside `docs/context/` (e.g. `.context/`) and
|
||||
are out of scope — never read, fold in, or scan them as fragment input.
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"project": "tools-registry",
|
||||
"docs_dir": "docs/context",
|
||||
"categories": [
|
||||
{
|
||||
"dir": "foundation",
|
||||
"label": "Foundation"
|
||||
},
|
||||
{
|
||||
"dir": "architecture",
|
||||
"label": "Architecture (proxy, auth, data model)"
|
||||
},
|
||||
{
|
||||
"dir": "interface",
|
||||
"label": "Interfaces (API \u00b7 CLI \u00b7 skill)"
|
||||
},
|
||||
{
|
||||
"dir": "ops",
|
||||
"label": "Ops (deploy, scale)"
|
||||
},
|
||||
{
|
||||
"dir": "reference",
|
||||
"label": "Reference"
|
||||
}
|
||||
],
|
||||
"source_globs": [
|
||||
"src",
|
||||
"skill"
|
||||
],
|
||||
"source_exts": [
|
||||
"py",
|
||||
"ts",
|
||||
"js",
|
||||
"sh",
|
||||
"json",
|
||||
"yaml"
|
||||
]
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
build-map.py — single source of truth for a codemap fragment set (project-agnostic).
|
||||
|
||||
Reads `fragments.config` (next to this script's parent skill dir) and the YAML-ish frontmatter of
|
||||
every fragment under <docs_dir>, then regenerates:
|
||||
1. <docs_dir>/README.md — the human index, grouped by category
|
||||
2. <skill_dir>/MAP.md — source file -> fragment(s) routing/drift map
|
||||
|
||||
Behavior is entirely config-driven, so this file is copied verbatim into every project. No third-party
|
||||
deps (hand-rolled frontmatter parser over the small subset we author). Run after editing a fragment:
|
||||
|
||||
python3 .claude/skills/<proj>-context/scripts/build-map.py
|
||||
|
||||
Idempotent. Prints a summary + any fragment missing frontmatter (exit 1 on missing).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT = Path(__file__).resolve()
|
||||
SKILL_DIR = SCRIPT.parents[1] # <scope-root>/.claude/skills/<proj>-context
|
||||
REPO = SCRIPT.parents[4] # scope root = the dir containing .claude/ (NOT necessarily git root)
|
||||
CONFIG = SKILL_DIR / "fragments.config"
|
||||
|
||||
MARK = "<!-- GENERATED by scripts/build-map.py — do not edit by hand; edit fragment frontmatter instead -->"
|
||||
|
||||
|
||||
def load_config() -> dict:
|
||||
cfg = json.loads(CONFIG.read_text(encoding="utf-8")) if CONFIG.exists() else {}
|
||||
cfg.setdefault("docs_dir", "docs/context")
|
||||
cfg.setdefault("categories", []) # ordered [{"dir":..,"label":..}]
|
||||
return cfg
|
||||
|
||||
|
||||
def parse_frontmatter(text: str) -> dict | None:
|
||||
if not text.startswith("---"):
|
||||
return None
|
||||
end = text.find("\n---", 3)
|
||||
if end == -1:
|
||||
return None
|
||||
fm: dict = {}
|
||||
key = None
|
||||
for raw in text[3:end].strip("\n").splitlines():
|
||||
line = raw.rstrip()
|
||||
if not line.strip():
|
||||
continue
|
||||
if line.startswith(" - ") or line.startswith("- "):
|
||||
if key:
|
||||
fm.setdefault(key, [])
|
||||
if isinstance(fm[key], list):
|
||||
fm[key].append(line.split("- ", 1)[1].strip())
|
||||
continue
|
||||
if ":" in line:
|
||||
k, _, v = line.partition(":")
|
||||
key = k.strip()
|
||||
v = v.strip()
|
||||
if v in ("", "[]"):
|
||||
fm[key] = []
|
||||
elif v.startswith("[") and v.endswith("]"):
|
||||
fm[key] = [x.strip() for x in v[1:-1].split(",") if x.strip()]
|
||||
else:
|
||||
fm[key] = v
|
||||
return fm
|
||||
|
||||
|
||||
def collect(docs: Path) -> list[dict]:
|
||||
frags = []
|
||||
for md in sorted(docs.rglob("*.md")):
|
||||
rel = md.relative_to(docs)
|
||||
if rel.name == "README.md":
|
||||
continue
|
||||
fm = parse_frontmatter(md.read_text(encoding="utf-8"))
|
||||
frags.append({
|
||||
"path": str(rel),
|
||||
"category": rel.parts[0] if len(rel.parts) > 1 else "",
|
||||
"title": (fm or {}).get("title") or md.stem,
|
||||
"status": (fm or {}).get("status", "?"),
|
||||
"sources": (fm or {}).get("sources", []) or [],
|
||||
"related": (fm or {}).get("related", []) or [],
|
||||
"has_fm": fm is not None,
|
||||
})
|
||||
return frags
|
||||
|
||||
|
||||
def category_order(cfg: dict, frags: list[dict]) -> list[tuple[str, str]]:
|
||||
"""Configured categories first (in order), then any extra dirs found, then root-level ('')."""
|
||||
order = [(c["dir"], c.get("label", c["dir"])) for c in cfg["categories"]]
|
||||
known = {d for d, _ in order}
|
||||
extras = sorted({f["category"] for f in frags if f["category"] and f["category"] not in known})
|
||||
order += [(d, d) for d in extras]
|
||||
if any(f["category"] == "" for f in frags):
|
||||
order.append(("", "Other"))
|
||||
return order
|
||||
|
||||
|
||||
def render_readme(cfg: dict, frags: list[dict]) -> str:
|
||||
proj = cfg.get("project", "this project")
|
||||
skill = SKILL_DIR.name # actual skill dir (e.g. arcterm-context) — not the display name
|
||||
out = [f"# {proj} — design fragments", "", MARK, "",
|
||||
"Small, focused fragments that mirror the codebase. Each declares the source files it",
|
||||
"covers (frontmatter `sources:`). Regenerate this index with",
|
||||
f"`python3 .claude/skills/{skill}/scripts/build-map.py`.", ""]
|
||||
by_cat: dict[str, list[dict]] = {}
|
||||
for f in frags:
|
||||
by_cat.setdefault(f["category"], []).append(f)
|
||||
for cat, label in category_order(cfg, frags):
|
||||
items = by_cat.get(cat, [])
|
||||
if not items:
|
||||
continue
|
||||
out += [f"## {label}", "", "| Fragment | Status | Covers |", "|---|---|---|"]
|
||||
for f in sorted(items, key=lambda x: x["path"]):
|
||||
covers = ", ".join(Path(s).name for s in f["sources"][:4]) or "—"
|
||||
if len(f["sources"]) > 4:
|
||||
covers += ", …"
|
||||
out.append(f"| [{f['title']}]({f['path']}) | {f['status']} | {covers} |")
|
||||
out.append("")
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
def render_map(cfg: dict, frags: list[dict]) -> str:
|
||||
proj = cfg.get("project", "project")
|
||||
skill = SKILL_DIR.name
|
||||
rev: dict[str, list[str]] = {}
|
||||
for f in frags:
|
||||
for s in f["sources"]:
|
||||
rev.setdefault(s, []).append(f["path"])
|
||||
out = [f"# {proj} context MAP", "", MARK, "",
|
||||
"Reverse index: **source file → the fragment(s) that document it.** Used by the",
|
||||
f"`{skill}` skill to load the right fragment when you touch a file and to detect drift.",
|
||||
"Regenerate via `scripts/build-map.py`.", "",
|
||||
"## Source file → fragment(s)", "", "| Source file | Documented in |", "|---|---|"]
|
||||
for src in sorted(rev):
|
||||
out.append(f"| `{src}` | {', '.join(sorted(set(rev[src])))} |")
|
||||
out += ["", "## Fragment → sources", "", "| Fragment | Sources |", "|---|---|"]
|
||||
for f in sorted(frags, key=lambda x: x["path"]):
|
||||
srcs = ", ".join(f"`{Path(s).name}`" for s in f["sources"]) or "_(no source files — narrative/reference)_"
|
||||
out.append(f"| `{f['path']}` | {srcs} |")
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
cfg = load_config()
|
||||
docs = REPO / cfg["docs_dir"]
|
||||
if not docs.exists():
|
||||
print(f"docs dir not found: {docs}", file=sys.stderr)
|
||||
return 2
|
||||
frags = collect(docs)
|
||||
(docs / "README.md").write_text(render_readme(cfg, frags), encoding="utf-8")
|
||||
(SKILL_DIR / "MAP.md").write_text(render_map(cfg, frags), encoding="utf-8")
|
||||
missing = [f["path"] for f in frags if not f["has_fm"]]
|
||||
n_src = len({s for f in frags for s in f["sources"]})
|
||||
print(f"✓ {len(frags)} fragments · {n_src} mapped source files")
|
||||
print(f" wrote {(docs / 'README.md').relative_to(REPO)}")
|
||||
print(f" wrote {(SKILL_DIR / 'MAP.md').relative_to(REPO)}")
|
||||
if missing:
|
||||
print("⚠ fragments missing frontmatter:", ", ".join(missing))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# drift.sh [git-range] — map changed source files to the fragment(s) that document them.
|
||||
# Project-agnostic: source pathspecs + extensions come from fragments.config. Reads the generated MAP.md.
|
||||
# Default range: origin/main..HEAD (everything unpushed).
|
||||
set -euo pipefail
|
||||
|
||||
RANGE="${1:-origin/main..HEAD}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
ROOT="$(cd "$SKILL_DIR/../../.." && pwd)"
|
||||
MAP="$SKILL_DIR/MAP.md"
|
||||
CONFIG="$SKILL_DIR/fragments.config"
|
||||
|
||||
[ -f "$MAP" ] || { echo "MAP.md not found — run build-map.py first" >&2; exit 1; }
|
||||
|
||||
# Pull source pathspecs + optional extension filter from the JSON config (python3 is a dependency).
|
||||
globs=$(python3 -c "import json;print(' '.join(json.load(open('$CONFIG')).get('source_globs',[])))" 2>/dev/null || true)
|
||||
extre=$(python3 -c "import json;e=json.load(open('$CONFIG')).get('source_exts',[]);print('\\.('+'|'.join(e)+')\$' if e else '')" 2>/dev/null || true)
|
||||
|
||||
cd "$ROOT"
|
||||
changed=$(git diff --name-only "$RANGE" -- $globs 2>/dev/null || true)
|
||||
[ -n "$extre" ] && changed=$(printf '%s\n' "$changed" | grep -E "$extre" || true)
|
||||
|
||||
if [ -z "$changed" ]; then
|
||||
echo "No documented-source changes in $RANGE."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Changed sources in $RANGE → fragments to review:"
|
||||
gap=()
|
||||
while IFS= read -r f; do
|
||||
[ -z "$f" ] && continue
|
||||
line=$(grep -F "\`$f\`" "$MAP" | grep ' | ' | head -1 || true)
|
||||
if [ -n "$line" ]; then
|
||||
docs=$(printf '%s' "$line" | sed -E 's/^\| `[^`]+` \| (.*) \|$/\1/')
|
||||
printf ' %-48s → %s\n' "$f" "$docs"
|
||||
else
|
||||
gap+=("$f")
|
||||
fi
|
||||
done <<< "$changed"
|
||||
|
||||
if [ ${#gap[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
echo "⚠ changed sources with NO fragment (possible doc gap — fold in or write a new fragment):"
|
||||
printf ' %s\n' "${gap[@]}"
|
||||
fi
|
||||
+1
-1
@@ -9,6 +9,6 @@ __pycache__/
|
||||
.secrets/
|
||||
.pytest_cache/
|
||||
dist/
|
||||
.claude/mode
|
||||
/.playwright-cli
|
||||
scripts/.dev-home/
|
||||
.claude/
|
||||
|
||||
@@ -5,8 +5,8 @@ This file orients an AI agent (Claude Code, Codex, Cursor, …) working in this
|
||||
## Read first
|
||||
|
||||
- **Design docs are the source of truth.** `docs/context/` holds one fragment per subsystem, each citing
|
||||
the source files it covers. Before changing code, load the fragment for that area. The
|
||||
`tools-registry-context` skill (`.claude/skills/`) maps a source file → its fragment.
|
||||
the source files it covers in its frontmatter (`sources:`). Before changing code, load the fragment for
|
||||
that area; `docs/context/README.md` is the generated index (source file → fragment).
|
||||
- **The charter:** tools-registry is a registry that turns a team's skills into shareable, callable tools;
|
||||
the core mechanic is a proxy that injects credentials server-side so a consumer never holds the secret.
|
||||
See `README.md`.
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ No `.env` needed for dev — every setting has a working default (ephemeral encr
|
||||
sqlite). The `TREG_*` knobs for persistence / a real deployment are documented in the README's
|
||||
**Configuration** section (and `docs/context/ops/deploy.md`).
|
||||
|
||||
A one-command local stack is in `scripts/dev-local.sh` (also the `dev-local` skill under `.claude/skills`).
|
||||
A one-command local stack is in `scripts/dev-local.sh` (`up` / `logs` / `cli` / `reset`).
|
||||
|
||||
## Project layout
|
||||
|
||||
|
||||
@@ -290,9 +290,7 @@ tools-registry/
|
||||
├── docs/
|
||||
│ ├── context/ # design fragments (codemap system) + generated index
|
||||
│ └── ONBOARDING.md # first-time bootstrap
|
||||
├── .claude/skills/tools-registry-context/ # doc-maintenance skill (/tools-registry-context)
|
||||
├── USAGE.md # full treg CLI reference
|
||||
├── CLAUDE.md # project instructions
|
||||
└── pyproject.toml
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user