# Shortly Maintain

> Maintain and curate the Shortly repository — ADRs, FAQs, AGENTS map, just/install tooling, local benches, Dart steward, Skill Steward skills, and GitNexus. Use when the user asks to maintain, curate, steward, or evolve this repo; when adding tools, docs, or benches; after structural changes; when timing hops or running /shortly-maintain.

- Skill: `arenukvern/shortly-maintain` (Agent Skill)
- Install (CLI): `npx skillmds@latest add arenukvern/shortly-maintain`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arenukvern/shortly-maintain/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: arenukvern (https://skillmd.com/u/arenukvern)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arenukvern/shortly-maintain

---


# Shortly maintain

Repo-local curation procedure. Product behavior SSOT is `src/` + tests. This skill owns how agents change the repo ecology, not how they implement URL features.

## Before any durable change

1. Read `docs/NORTH_STAR.mdx`. Classify `north_star_impact`: `none` | `applies` | `clarifies` | `sub_star` | `amends` | `conflicts`.
2. Do not reopen ADRs 0001–0008 unless the user explicitly changes a locked product decision. ADR 0009 is the stewardship-stack decision.
3. Use Skill Steward skills already in `.agents/skills/` for governance and quality-contract work. Do not re-teach those procedures here.
4. If GitNexus is indexed, run impact analysis before editing a symbol. If the index is stale, `npx gitnexus analyze`.

## Documentation & docs.page conventions

All public and internal documentation is published via [docs.page](https://docs.page):

1. **File Extension:** All doc pages in `docs/` must use the `.mdx` extension (e.g. `docs/index.mdx`, `docs/quickstart.mdx`, `docs/decisions/0001-*.mdx`).
2. **Frontmatter:** Every `.mdx` file must begin with valid YAML frontmatter containing `title` and `description`.
3. **Configuration (`docs.json`):**
   - Header menu links are configured under `"links"`.
   - Sidebar hierarchy is configured under `"navigation"`.
4. **Internal Links:** Use clean relative routes (e.g. `[ADR 0001](/decisions/0001-single-shared-pool)`, `[Quickstart](/quickstart)`). Avoid hardcoded `.md` extensions in documentation links.

## Command hub & execution environments

| Job | Command | Notes |
|---|---|---|
| Bootstrap | `./install.sh` | Installs .NET, Dart, `just`, Node, skills, GitNexus |
| Detect | `just status` | Tooling presence check |
| Build (Safe) | `dotnet build -m:1` | Single-process build (safe in sandboxes) |
| Native gate | `just check` | `dotnet test` + Dart `shortly steward validate` |
| Fast validator | `just validate` | `./tools/dart-validate.sh` (ADRs, encoder, key checks) |
| API service | `just run` | Runs `Shortly.Api` on `http://localhost:5080` |
| Time `GET /{code}` | `just bench-redirect` | Isolated redirect timing (not on `just check`) |
| Re-index | `npx gitnexus analyze` | Refreshes code intelligence knowledge graph |

### Agent Sandbox Caveats
In restricted agent environments (e.g. Zed, Claude Code, sandboxed subshells):
- **Build:** Always pass `-m:1` or ensure `DOTNET_CLI_DO_NOT_USE_MSBUILD_SERVER=1` and `MSBUILDDISABLENODEREUSE=1` (handled by `tools/env.sh`). Multi-process MSBuild server nodes will hang attempting inter-process socket communication.
- **Test:** `dotnet test` uses `vstest`/`testhost` loopback TCP socket IPC. If socket binding is blocked (`SocketException: Permission denied`), do not hang waiting. Run `dotnet build -m:1` + `./tools/dart-validate.sh` to prove correctness, and leave full `dotnet test` to host/unsandboxed runs.

Standing how for commands: [docs/DX_FAQ.mdx](../../../docs/DX_FAQ.mdx).

## Benchmarks

Use when the user says a hop feels slow, asks to benchmark, or you change lookup/persist on `GET /{code}`.

1. Split **Shortly hop** (302, no follow) from **destination** (`Location` / `curl -L` / browser).
2. Run `just bench-redirect` (in-process). Against a running API: `-- --base-url http://localhost:5080 --code <code>`; add `--follow` only to time the destination.
3. Read recipes and how to add a bench in [docs/DX_FAQ.mdx](../../../docs/DX_FAQ.mdx). Tool contract: [tools/Shortly.Bench/README.md](../../../tools/Shortly.Bench/README.md).
4. `curl -I` is HEAD and returns 405. Time GET.
5. Do not write one machine's p50 into an ADR as a product SLO. Standing why stays in [docs/DESIGN_FAQ.mdx](../../../docs/DESIGN_FAQ.mdx).
6. New bench: implement in `tools/Shortly.Bench` (or a sibling), wire `tools/bench-*.sh` and `tools/bench-*.ps1`, add a `just` recipe that only calls those scripts, document how in DX_FAQ. Keep `just check` unchanged.

## After a structural change

1. Update the owning ADR or add the next number under `docs/decisions/*.mdx`.
2. Update `docs.json` navigation/links if new pages are introduced.
3. Standing why → `docs/DESIGN_FAQ.mdx`. Standing how → `docs/DX_FAQ.mdx`.
4. Keep `AGENTS.md` a map. Do not paste implementations into it.
5. If install/just recipes changed, change `tools/*.sh` (and `tools/*.ps1`) first; justfile only calls those scripts.
6. Run `just validate` (or `just check`).
7. Delete stale plans once extracted.

## Do not

- Invent product features (tenants, custom domains, cleanup workers, extra auth).
- Make the .NET service depend on Dart, Node, or skills.
- Treat Skill Steward or GitNexus as runtime dependencies of the API.
- Add `steward.yaml` / a harness unless a typed action is actually needed.
- Put local benches on the native gate or treat them as production APM.

