@laitszkin/apollo-toolkit 3.10.0 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/generate-spec/SKILL.md +17 -15
- package/generate-spec/agents/openai.yaml +1 -1
- package/generate-spec/references/TEMPLATE_SPEC.md +103 -84
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/init-project-html/SKILL.md +117 -125
- package/init-project-html/agents/openai.yaml +18 -9
- package/init-project-html/lib/atlas/assets/architecture.css +161 -0
- package/init-project-html/lib/atlas/assets/viewer.client.js +136 -0
- package/init-project-html/lib/atlas/cli.js +1023 -0
- package/init-project-html/lib/atlas/layout.js +330 -0
- package/init-project-html/lib/atlas/render.js +583 -0
- package/init-project-html/lib/atlas/schema.js +347 -0
- package/init-project-html/lib/atlas/state.js +402 -0
- package/init-project-html/references/TEMPLATE_SPEC.md +140 -83
- package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +160 -1058
- package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +136 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/atlas.index.yaml +34 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +172 -0
- package/init-project-html/sample-demo/resources/project-architecture/atlas/features/invite-code-registration.yaml +160 -0
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/index.html +67 -52
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +64 -163
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +102 -196
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +82 -163
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +88 -150
- package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +83 -138
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +61 -51
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +84 -159
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +81 -143
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +98 -188
- package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +83 -138
- package/init-project-html/sample-demo/resources/project-architecture/index.html +256 -335
- package/init-project-html/scripts/architecture.js +65 -247
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
- package/package.json +6 -2
- package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
- package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
- package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
- package/spec-to-project-html/SKILL.md +74 -67
- package/spec-to-project-html/agents/openai.yaml +14 -8
- package/spec-to-project-html/references/TEMPLATE_SPEC.md +98 -83
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
|
@@ -1,181 +1,173 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: init-project-html
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
4
|
+
Declare the project HTML architecture atlas through `apltk architecture` CLI verbs instead of hand-writing SVG/HTML. Two acceptance criteria gate completion: (1) the macro diagram clearly shows feature × sub-module relationships — data flow, call/return interaction logic, error handling, rollback — all expressed as `--kind call|return|data-row|failure` edges; (2) each sub-module's internal diagram clearly shows function-level interactions inside it — function-to-function flow via `dataflow add --fn <declared-fn>`, variable state transitions via `--reads`/`--writes` referencing declared variables, and the resulting local data flow. The tool owns layout, CSS, and pan/zoom for both diagrams; `validate` rejects any step that references an undeclared function or variable. With subagents, each owns one feature and declares every intra-feature interaction itself; the main agent only declares cross-feature edges. Anchor every declaration to repo evidence.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Init Project HTML
|
|
8
8
|
|
|
9
9
|
## Dependencies
|
|
10
10
|
|
|
11
|
-
- Required: none (the
|
|
12
|
-
- Conditional: `spec-to-project-html` when the same atlas needs spec-driven refresh — that skill
|
|
13
|
-
- Optional: `align-project-documents` when `docs/features` already names capabilities.
|
|
14
|
-
-
|
|
15
|
-
- Fallback: codebase too large for one pass → document scanned roots, explicit omissions, phased plan. **MUST NOT** pretend untread paths were verified.
|
|
11
|
+
- Required: none (the CLI ships its own layout engine, CSS, and pan/zoom client; `apltk architecture` is installed with this toolkit).
|
|
12
|
+
- Conditional: `spec-to-project-html` when the same atlas needs spec-driven refresh — that skill uses the same CLI with `--spec`.
|
|
13
|
+
- Optional: `align-project-documents` when `docs/features` already names the user-visible capabilities.
|
|
14
|
+
- Fallback: codebase too large for one pass → use the subagent strategy below, document scanned roots and explicit omissions in `meta.summary`. **MUST NOT** declare components for code paths that were never read.
|
|
16
15
|
|
|
17
16
|
## Non-negotiables
|
|
18
17
|
|
|
19
|
-
### Rule 1 —
|
|
18
|
+
### Rule 1 — Use the CLI; never hand-author atlas HTML
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
- Layer A: **feature ↔ feature** user-visible journeys.
|
|
23
|
-
- Layer B: **sub-module ↔ sub-module** concrete calls / returns / data-row hand-offs that realise Layer A.
|
|
24
|
-
- **MUST** draw each feature as an `m-cluster` (dashed frame); sub-modules are clickable nodes inside their cluster.
|
|
25
|
-
- **MUST** include at least one node-pair carrying **≥2 edges** (e.g. service → db with SELECT / INSERT / UPDATE) to prove multi-edge support.
|
|
26
|
-
- **MUST** include at least one **producer ↔ consumer** loop (call/return pair, or cyclic data-row).
|
|
27
|
-
- **MUST** use **`m-edge--cross`** dashed-heavy edges for cross-feature data-row hand-offs whenever the system has them.
|
|
28
|
-
- **MUST** include `<nav class="atlas-submodule-index">` linking every sub-module page in the atlas.
|
|
20
|
+
The atlas state lives in `resources/project-architecture/atlas/` (`atlas.index.yaml` + per-feature YAMLs). Every change goes through `apltk architecture <verb> ...`. After any mutation, the CLI re-renders `resources/project-architecture/**/*.html` with the correct layout, CSS, pan/zoom, and ARIA — agents **MUST NOT** edit those HTML files by hand or invent additional ones.
|
|
29
21
|
|
|
30
|
-
### Rule 2 — Sub-module pages describe
|
|
22
|
+
### Rule 2 — Sub-module pages describe only themselves; the internal-dataflow diagram is zoomable and structurally typed
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
What the CLI emits on each sub-module page is fixed:
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
- function I/O table (`function add --feature X --submodule Y --name fn --in ... --out ... --side ... --purpose ...`),
|
|
27
|
+
- variables-with-business-purpose table (`variable add --name v --type T --scope call|tx|persist|instance|loop --purpose ...`),
|
|
28
|
+
- internal dataflow diagram — ordered steps the renderer lays out as a numbered top-to-bottom flow inside a pan/zoom viewport with +/−/Fit controls, exactly like the macro SVG. Each step is `dataflow add --step "..." [--fn <declared-fn>] [--reads "v1,v2"] [--writes "v3,v4"]`. The renderer surfaces `--fn` as a pill at the top of the step box, `--reads` as a green chip on the bottom-left, and `--writes` as an orange chip on the bottom-right — so a single SVG simultaneously shows the function-to-function flow inside the sub-module AND the variable state transitions across the run,
|
|
29
|
+
- local errors (`error add --name ErrX --when ... --means ...`).
|
|
38
30
|
|
|
39
|
-
|
|
31
|
+
Schema rules the CLI enforces on every `dataflow add` (so the diagram never lies):
|
|
40
32
|
|
|
41
|
-
|
|
33
|
+
- `--fn <name>` must match a function declared **in the same sub-module** via `function add`. If it does not, `validate` fails — declare the function first.
|
|
34
|
+
- Every name in `--reads` / `--writes` must match a variable declared **in the same sub-module** via `variable add`. If it does not, `validate` fails — declare the variable first.
|
|
35
|
+
- `--fn` / `--reads` / `--writes` are optional but additive: omitting them is allowed for purely descriptive steps, but for any non-trivial sub-module the function-and-variable structure **MUST** be filled in so the diagram conveys the function-to-function flow and the variable state transitions.
|
|
42
36
|
|
|
43
|
-
|
|
37
|
+
Cross-boundary narratives ("I call X", "Y calls me") **MUST** be expressed as edges (`edge add --from X/sub --to Y/sub --kind call|return|data-row|failure --label ...`), never as sub-module page prose. The CLI enforces this by design — there is no verb to add cross-boundary text to a sub-module page.
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
- **Without subagents:** process features **one at a time** — read feature A end-to-end, **immediately** emit `features/A/` (overview + every sub-module page) and incrementally add A's cluster, nodes, and known edges to the macro. Mark edges pointing at unread features with `data-edge-target-pending="<future-slug>"`. **Drop A's function-level details from working memory**, then read feature B. After every feature is written, resolve all pending placeholders in the macro. **Never** read everything before writing.
|
|
39
|
+
### Rule 3 — Read order: never let the codebase wipe the context window; subagents own their own feature
|
|
47
40
|
|
|
48
|
-
|
|
41
|
+
Real production codebases dwarf the main agent's context. Reading the whole repo before declaring pushes early details out by the end, making macro edges and sub-module declarations contradict each other. The split below also draws a hard responsibility line between the worker and the orchestrator. **MUST** follow one of:
|
|
49
42
|
|
|
50
|
-
|
|
43
|
+
- **With subagents (preferred):** first enumerate the **feature-module list** (slug + entry + boundary resources only). Then dispatch **one (write-capable) subagent per feature**. Each subagent:
|
|
44
|
+
- deep-reads its own feature,
|
|
45
|
+
- declares **everything intra-feature** itself via `apltk architecture ... --feature <slug>` (sub-modules; per sub-module functions / variables / internal dataflow / errors; **every intra-feature edge** — function calls between sub-modules, error edges, rollback / compensation edges; variable state transitions are captured as ordered `dataflow add` steps on each sub-module),
|
|
46
|
+
- returns ONLY a structured summary of (i) the sub-module list and (ii) the **outbound boundaries** the main agent needs to wire (calls / data-rows / failure edges to other features' sub-modules, including direction and the consuming/producing endpoints).
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
The main agent never re-reads source for that feature. It collects every subagent's outbound-boundary summary and declares **only the cross-feature edges** (and any cross-feature actors / meta) itself, then runs `apltk architecture validate`.
|
|
49
|
+
- **Without subagents:** process features **one at a time** — read feature A end-to-end, declare its sub-modules, functions, variables, internal dataflow, errors, and intra-feature edges via the CLI, then move on. For cross-feature edges that point at not-yet-declared features, declare the placeholder feature with `feature add --slug <future> --title <future>` first, then add the edge; subsequent passes set the real title/story. Drop A's function-level details from working memory before reading feature B.
|
|
53
50
|
|
|
54
|
-
**
|
|
51
|
+
Both paths share one invariant: at any moment the agent doing the deep read only holds *that feature's details + cross-feature boundary notes*. The main agent's working set, in subagent mode, is **boundaries only**. Run `apltk architecture validate` after the last feature to catch dangling edges, unknown endpoints, or missing required fields.
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
2. `<section class="atlas-summary">` — prose explaining why feature modules and sub-modules sit in one diagram; cite a real producer+consumer / multi-edge case.
|
|
58
|
-
3. `<section class="atlas-legend">` — explains the four edge types: solid arrow = **call**, thin dashed = **return**, warm-tone heavy dashed = **data-row**, plus a note that multiple edges between the same node pair are allowed.
|
|
59
|
-
4. `<section class="flow-section flow-section--macro">` with **one** `<figure class="flow-chart flow-chart--macro flow-chart--svg">` honouring every MUST in Rule 1, plus a mirrored `<ol class="flow-edge-manifest flow-edge-manifest--macro">` (one row per edge, with `data-edge-id` + `data-edge-kind`).
|
|
60
|
-
5. `<nav class="atlas-submodule-index">` — links to every sub-module page across all features.
|
|
61
|
-
6. `<nav class="atlas-features">` (optional) — middle-tier nav to each feature index.
|
|
53
|
+
### Rule 4 — Evidence over invention
|
|
62
54
|
|
|
63
|
-
**
|
|
64
|
-
|
|
65
|
-
1. `<nav class="breadcrumb">` (`../../index.html` → macro).
|
|
66
|
-
2. `<header>` — user-visible capability name.
|
|
67
|
-
3. `<section class="feature-story">` — 1–3 paragraphs of user story; close with one sentence + link back to the macro.
|
|
68
|
-
4. `<section class="submodule-nav">` — table of every sub-module page (link + one-line own responsibility).
|
|
69
|
-
5. Optional `<section class="feature-trace">` for spec-ID traceability.
|
|
70
|
-
|
|
71
|
-
**Forbidden on feature index**: `flow-chart--submodules`, `flow-chart--end-to-end`, `flow-edge-manifest`, or any other cross-submodule structure — those belong on the macro.
|
|
72
|
-
|
|
73
|
-
**C) Sub-module `features/<feature-slug>/<sub-module-slug>.html`** (self-only; matches Rule 2):
|
|
74
|
-
|
|
75
|
-
1. `<nav class="breadcrumb">`: `../../index.html` · `./index.html` · current sub-module.
|
|
76
|
-
2. `<header>` — sub-module name + **own** responsibility (one paragraph; no "who I talk to").
|
|
77
|
-
3. `<section class="sub-io">` — columns `function | signature (in / out) | side effects | purpose`; side-effect chips `pure` / `io` / `write` / `tx` / `lock` / `network` / …
|
|
78
|
-
4. `<section class="sub-vars">` — columns `variable | type | lifecycle / scope | business purpose`; cover **every** business-branch-affecting identifier; scope chip values listed in Rule 2; business purpose in business language (no bland "stores some value").
|
|
79
|
-
5. `<section class="sub-dataflow">` — numbered steps; optional small `<svg class="sub-dataflow__svg">` (nodes = internal variables/functions only; height ≤ 240, width ≤ 720).
|
|
80
|
-
6. `<section class="sub-errors">` — errors raised/returned (condition + meaning).
|
|
81
|
-
7. footer: one-sentence links back to `../../index.html` and `./index.html`.
|
|
82
|
-
|
|
83
|
-
If a sub-module truly holds no business-branch-affecting variables (rare; usually pure pass-through), `sub-vars` MUST still appear as a single-row table that says so with a one-line justification.
|
|
84
|
-
|
|
85
|
-
### Rule 5 — Naming, IDs, and shared assets
|
|
86
|
-
|
|
87
|
-
- **`feature-slug`**: kebab-case, matching the **user-language capability** (e.g. `invite-code-registration`).
|
|
88
|
-
- **`sub-module-slug`**: kebab-case, identifying the implementation boundary (e.g. `web-register-ui`, `public-api`, `registration-service`, `postgresql`).
|
|
89
|
-
- **`data-feature-id` / `data-submodule-id`**: optional node attributes; **MUST** match directory/file names.
|
|
90
|
-
- **`data-edge-id`**: stable id per macro edge (mirrored in the manifest row).
|
|
91
|
-
- **`data-edge-kind`**: one of `call` | `return` | `data-row` | `failure`.
|
|
92
|
-
- **Shared CSS**: on first run, copy `references/architecture.css` to `resources/project-architecture/assets/architecture.css`. Root `index.html` → `href="assets/architecture.css"`; everything under `features/<feature-slug>/` → `href="../../assets/architecture.css"`.
|
|
93
|
-
|
|
94
|
-
### Rule 6 — Accessibility and styling minima
|
|
95
|
-
|
|
96
|
-
- The macro SVG `<figure>` **MUST** carry an `aria-label` plus the mirrored `<ol class="flow-edge-manifest">` so screen-reader users get the full edge list without chasing pixels.
|
|
97
|
-
- Cluster and node links **MUST** wrap their `<g>` in `<a>` and provide readable `<text>` (browsers expose `<text>` as the accessible name).
|
|
98
|
-
- Sub-module `sub-io` and `sub-vars` tables **MUST** use semantic `<thead>` / `<tbody>`.
|
|
99
|
-
- Colour MUST NOT be the sole semantic carrier: edge differences encode via line style (solid / dashed / heavy-dashed) AND colour.
|
|
100
|
-
- Every diagram is static SVG — respect `prefers-reduced-motion` by not adding animation.
|
|
101
|
-
- Quality bar: high contrast, print-friendly, restrained palette; avoid the "AI-default purple gradient" and Inter look-alike. Pair a recognisable display face (e.g. `Fraunces`) with `Plus Jakarta Sans`. Edges use `currentColor` so light/dark adapt; pages stay readable across widths via SVG `viewBox`.
|
|
102
|
-
|
|
103
|
-
### Rule 7 — Other binding rules
|
|
104
|
-
|
|
105
|
-
- **MUST** read the entire production codebase along language boundaries; record skipped roots and the reason in `atlas-summary`.
|
|
106
|
-
- **MUST** anchor every user-visible capability to a concrete entry; **never** invent modules or integrations.
|
|
107
|
-
- **MUST** migrate legacy single-file `features/<slug>.html` or feature-level cross-submodule flowcharts to the new layering on first touch.
|
|
108
|
-
|
|
109
|
-
> Reference cheat sheets (DOM examples, the macro SVG class-hook table, vocabulary glossary) live in `references/TEMPLATE_SPEC.md`. That file is reference material only — every binding rule already lives here.
|
|
55
|
+
- **MUST** anchor every declared feature, sub-module, function, variable, dataflow step, and edge to a concrete path / symbol / SQL / config; record scanned roots and any deliberate omissions in `meta.summary` via `apltk architecture meta set --summary "..."`.
|
|
56
|
+
- **MUST NOT** invent modules, integrations, or sub-modules just because the diagram "looks balanced". Empty rows are valid; lies are not.
|
|
110
57
|
|
|
111
58
|
## Standards (summary)
|
|
112
59
|
|
|
113
|
-
- **Evidence**: every
|
|
114
|
-
- **Execution**: feature-module list (shallow) → branch by environment (subagent fan-out or sequential read-
|
|
115
|
-
- **Quality**: macro SVG carries
|
|
116
|
-
- **Output**: `resources/project-architecture/`
|
|
60
|
+
- **Evidence**: every CLI declaration traces to a path/symbol/SQL/config; uncertain areas surface as `TBD` strings or are omitted with a recorded reason.
|
|
61
|
+
- **Execution**: feature-module list (shallow) → branch by environment (subagent fan-out or sequential read-declare) → `apltk architecture validate` → handover report.
|
|
62
|
+
- **Quality**: macro SVG carries every cross-feature data-row edge that exists in the system; sub-module declarations are self-only; pan/zoom + Fit work in the rendered HTML; `apltk architecture validate` returns OK.
|
|
63
|
+
- **Output**: `resources/project-architecture/atlas/` (YAML state) + `resources/project-architecture/**/*.html` (renderer output) — both managed by the CLI.
|
|
64
|
+
|
|
65
|
+
## Acceptance criteria
|
|
66
|
+
|
|
67
|
+
The atlas is only complete when both of the following are demonstrably true on the rendered HTML (open `resources/project-architecture/index.html` and one representative sub-module page to verify):
|
|
68
|
+
|
|
69
|
+
1. **Macro diagram clearly shows the relationships between features and sub-modules**, including:
|
|
70
|
+
- **Data flow** — every cross-feature DB row, queue topic, or cache key hand-off is a `--kind data-row` edge between the producing and consuming sub-modules (not free-form prose).
|
|
71
|
+
- **Interaction logic** — synchronous request/response paths are paired `--kind call` (outbound) and `--kind return` (response) edges with a label that names the call site or response shape.
|
|
72
|
+
- **Error handling and rollback** — every failure / compensation / retry path that crosses a sub-module boundary is a `--kind failure` edge with a label that names what is being rolled back or compensated.
|
|
73
|
+
- No interaction is captured *only* in sub-module page prose — if it crosses a sub-module boundary it MUST appear as an edge so the macro SVG carries it.
|
|
74
|
+
2. **Each sub-module's internal diagram clearly shows the function-level interactions inside the sub-module**, including:
|
|
75
|
+
- **Function-to-function flow** — every step that does non-trivial work carries `--fn <declared-fn>`. The sequence of pills along the steps reveals which function is active at each point in the flow.
|
|
76
|
+
- **Variable state transitions during the run** — every variable that is read or mutated by a step is declared via `variable add`, and that step lists it in `--reads` (the value flows in) or `--writes` (the value is created/updated). Reading the steps top-to-bottom traces each variable's life cycle.
|
|
77
|
+
- **Local data flow** — the ordered step boxes (with reads/writes chips) read as a directed flowchart, ending at the sub-module boundary (returning a value, persisting a row, emitting an event).
|
|
78
|
+
|
|
79
|
+
`apltk architecture validate` MUST return OK before reporting completion — it enforces both criteria's structural pieces (unknown sub-modules on edges, unknown functions/variables referenced by dataflow steps).
|
|
80
|
+
|
|
81
|
+
## How to use `apltk architecture`
|
|
82
|
+
|
|
83
|
+
Each verb is a single mutation; the CLI auto-renders after every change. Pass `--no-render` when batching mutations. Global flags: `--project <root>`, `--spec <spec_dir>` (writes to overlay; see `spec-to-project-html`), `--no-render`, `--no-open`.
|
|
84
|
+
|
|
85
|
+
| Verb | Use it to… |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| `apltk architecture meta set --title ... --summary ...` | Set the macro title + atlas summary (read order, scanned roots, deliberate omissions). |
|
|
88
|
+
| `apltk architecture actor add --id end-user --label "End user"` | Add a top-level actor (optional; appears in macro context). |
|
|
89
|
+
| `apltk architecture feature add --slug <kebab> --title "..." --story "..." [--depends-on a,b]` | Declare a feature module (user-visible capability). |
|
|
90
|
+
| `apltk architecture submodule add --feature <slug> --slug <kebab> --kind ui\|api\|service\|db\|pure-fn\|queue\|external --role "..."` | Declare a sub-module under a feature. |
|
|
91
|
+
| `apltk architecture function add --feature X --submodule Y --name fn --in "T1, T2" --out "R \| ErrX" --side pure\|io\|write\|tx\|lock\|network --purpose "..."` | Add a function I/O row. |
|
|
92
|
+
| `apltk architecture variable add --feature X --submodule Y --name v --type T --scope call\|tx\|persist\|instance\|loop --purpose "..."` | Add a variable-with-business-purpose row. |
|
|
93
|
+
| `apltk architecture dataflow add --feature X --submodule Y --step "..." [--fn <declared-fn>] [--reads "v1,v2"] [--writes "v3,v4"] [--at N]` | Append (or insert at index `N`) an internal dataflow step. `--fn` must match a previously declared `function`; every name in `--reads` / `--writes` must match a previously declared `variable` in the same sub-module — the renderer surfaces them as a function pill + reads/writes chips so the diagram shows function-to-function flow and variable state transitions. |
|
|
94
|
+
| `apltk architecture dataflow reorder --feature X --submodule Y --from i --to j` | Move a step within the same sub-module. |
|
|
95
|
+
| `apltk architecture error add --feature X --submodule Y --name ErrCode --when "..." --means "..."` | Add a local error row. |
|
|
96
|
+
| `apltk architecture edge add --from <feature>[/sub] --to <feature>[/sub] --kind call\|return\|data-row\|failure --label "..." [--id <stable>]` | Add an edge. Intra-feature edges (both endpoints in the same feature with sub-modules) land in the feature YAML; cross-feature edges land in `atlas.index.yaml`. |
|
|
97
|
+
| `apltk architecture feature\|submodule\|function\|variable\|error\|edge remove ...` | Remove a previously declared component. Removing a feature drops every sub-module and edge that referenced it. |
|
|
98
|
+
| `apltk architecture feature\|submodule set ...` | Update fields (e.g. retitle a feature, change a sub-module's role) without re-adding. |
|
|
99
|
+
| `apltk architecture render` | Force-regenerate HTML from current YAML state (useful after editing YAML directly, though hand-editing is discouraged). |
|
|
100
|
+
| `apltk architecture validate` | Schema + referential integrity check; fails on dangling edges, unknown enums, duplicate slugs. |
|
|
101
|
+
| `apltk architecture undo` | Revert the most recent mutation (single-level snapshot). |
|
|
102
|
+
| `apltk architecture open` | Open the rendered macro `index.html` in a browser. |
|
|
103
|
+
| `apltk architecture diff` | Render the paginated before/after viewer for every active spec under `docs/plans/**/architecture_diff/`. |
|
|
117
104
|
|
|
118
105
|
## Workflow
|
|
119
106
|
|
|
120
107
|
### 1) Whole-repo inventory — list feature modules, not function bodies
|
|
121
108
|
|
|
122
|
-
Scan the shipped source for **user-visible capabilities** (each one = one feature module): entry routes, CLI commands, UI pages, cron jobs, runners, event handlers, CDC streams.
|
|
123
|
-
|
|
124
|
-
- kebab-case `slug` + one-line user story.
|
|
125
|
-
- **Boundary points**: entry symbol/file, outbound resources (DB tables, queue topics, external services, shared cache keys).
|
|
126
|
-
- Candidate cross-feature edges (mark as candidates; do not verify yet).
|
|
109
|
+
Scan the shipped source for **user-visible capabilities** (each one = one feature module): entry routes, CLI commands, UI pages, cron jobs, runners, event handlers, CDC streams. Record only kebab-case slug + one-line user story + boundary points (entry symbol, outbound DB tables / queue topics / external services).
|
|
127
110
|
|
|
128
111
|
- **Pause →** Is the list actually complete? Note skipped roots with reason; no silent skips.
|
|
129
112
|
- **Pause →** Did I dive into function bodies here? Roll back — keep only structural notes.
|
|
130
113
|
|
|
131
114
|
### 2) Branch the deep-read by environment (Rule 3)
|
|
132
115
|
|
|
133
|
-
#### 2A) With subagents (preferred)
|
|
134
|
-
|
|
135
|
-
Dispatch one **read-only** subagent per feature. Require this summary template (no source-code excerpts):
|
|
116
|
+
#### 2A) With subagents (preferred) — workers own their feature; main agent owns the macro seams
|
|
136
117
|
|
|
137
|
-
|
|
138
|
-
> - Sub-module list: one row per `<sub-module-slug>` (kind: ui / api / service / db / pure-fn / queue / external).
|
|
139
|
-
> - Per sub-module: function signatures (in / out / errors), side-effect chip, variables-with-business-purpose, internal flow steps, errors raised.
|
|
140
|
-
> - **Outbound boundaries**: which other features' sub-modules this one calls (call edges); which DB tables / topics / cache keys it touches that **another feature also reads or writes** (data-row / data-topic edges; mark direction).
|
|
118
|
+
Dispatch one **write-capable** subagent per feature, plus the main agent for the macro layer. Hand each subagent: its feature slug, the feature-module list from step 1 (so it knows other features' slugs for outbound edges), and access to `apltk architecture`. Each subagent **declares its own feature end-to-end** and only reports outbound boundaries upward:
|
|
141
119
|
|
|
142
|
-
|
|
120
|
+
> **Feature `<slug>` subagent contract**
|
|
121
|
+
> - Read every sub-module of this feature.
|
|
122
|
+
> - Run `feature add --slug <slug> --title "..." --story "..." --no-render` (or `feature set` if a placeholder already exists).
|
|
123
|
+
> - For every sub-module: `submodule add` with the right `--kind`, then add its `function`, `variable`, `dataflow` (ordered — these steps carry the variable state transitions through the flow), and `error` rows.
|
|
124
|
+
> - For every intra-feature interaction between sub-modules — function calls, returns, error propagation, rollback / compensation — emit `edge add --from <slug>/<a> --to <slug>/<b> --kind call|return|data-row|failure --label "..."`. Failure / rollback flows belong here: model them as additional `--kind failure` edges or as ordered `dataflow add` steps on the affected sub-modules, whichever maps to the real code path.
|
|
125
|
+
> - Run `apltk architecture validate` (scoped to this feature) before returning.
|
|
126
|
+
> - **Return ONLY**: (i) sub-module list (slug + kind + one-line role), (ii) outbound boundaries to *other* features' sub-modules (direction + edge kind + suggested label). No source excerpts, no function bodies.
|
|
143
127
|
|
|
144
|
-
|
|
145
|
-
2. `features/<slug>/index.html` per feature (lightweight: user story + `submodule-nav`).
|
|
146
|
-
3. Per sub-module: self-only page with `sub-io` + `sub-vars` + `sub-dataflow` (small SVG if useful) + `sub-errors`.
|
|
147
|
-
4. Copy `references/architecture.css` to `resources/project-architecture/assets/`.
|
|
128
|
+
Main agent — after every subagent returns — declares **only** macro-level state from the aggregated outbound boundaries:
|
|
148
129
|
|
|
149
|
-
|
|
130
|
+
```bash
|
|
131
|
+
apltk architecture meta set --title "..." --summary "..." --no-render
|
|
132
|
+
# only when an actor is shared across multiple features:
|
|
133
|
+
apltk architecture actor add --id <id> --label "..." --no-render
|
|
134
|
+
# one edge per cross-feature interaction reported by the subagents:
|
|
135
|
+
apltk architecture edge add --from <featA>/<subA> --to <featB>/<subB> --kind call|return|data-row|failure --label "..." --no-render
|
|
136
|
+
apltk architecture render
|
|
137
|
+
apltk architecture validate
|
|
138
|
+
```
|
|
150
139
|
|
|
151
|
-
|
|
140
|
+
The main agent **MUST NOT** re-declare a subagent's intra-feature components, and **MUST NOT** open source files for any feature it delegated.
|
|
152
141
|
|
|
153
|
-
|
|
142
|
+
#### 2B) Without subagents — feature-by-feature read-declare loop
|
|
154
143
|
|
|
155
|
-
|
|
156
|
-
2. **Write to disk immediately**:
|
|
157
|
-
- `features/<slug>/index.html` (lightweight).
|
|
158
|
-
- One page per sub-module (self-only: `sub-io` + `sub-vars` + `sub-dataflow` + `sub-errors`).
|
|
159
|
-
- For `sub-vars`, sweep every identifier (params, local state, struct fields, DB columns, config, counters, `now`) — anything that influences a business branch or external promise **must** appear.
|
|
160
|
-
3. **Patch the macro `index.html` incrementally**: add this feature's cluster + sub-module nodes + intra-feature edges; mark edges pointing at unread features as `data-edge-target-pending="<future-slug>"` and note them in `figcaption`; mirror new edges in `flow-edge-manifest--macro`.
|
|
161
|
-
4. **Drop function-level details from working memory**; keep only lightweight notes (cluster id, pending-edge list); do not re-read this feature's bodies when handling the next one.
|
|
162
|
-
5. Return to step 1 for the next feature.
|
|
144
|
+
Process the list from step 1 one feature at a time (topological hint: read-from data sources and pure helpers first, user-facing entries last). Per feature:
|
|
163
145
|
|
|
164
|
-
|
|
146
|
+
1. **Deep-read** every sub-module of this feature.
|
|
147
|
+
2. **Declare immediately** via the CLI (`feature add`, then `submodule add` × N, then `function`/`variable`/`dataflow`/`error` rows, then intra-feature `edge add`).
|
|
148
|
+
3. **Cross-feature edges**: if the target feature has not been declared yet, declare a placeholder with `feature add --slug <future> --title <future>`, add the edge, then refine the placeholder on a later pass.
|
|
149
|
+
4. **Drop function-level details from working memory** before moving to the next feature.
|
|
165
150
|
|
|
166
|
-
|
|
167
|
-
- Verify `atlas-submodule-index` lists every sub-module page.
|
|
168
|
-
- Confirm `architecture.css` is copied into `assets/`.
|
|
151
|
+
After the last feature:
|
|
169
152
|
|
|
170
|
-
-
|
|
153
|
+
- Refine any placeholder features that were used to carry cross-feature edges.
|
|
154
|
+
- Run `apltk architecture validate` — must return OK.
|
|
171
155
|
|
|
172
156
|
### 3) Handover report
|
|
173
157
|
|
|
174
|
-
Report: feature count, macro edge counts (call/return/
|
|
158
|
+
Report: feature count, sub-module count, macro edge counts (call / return / data-row / failure), uncovered paths + reasons, the read strategy actually used (2A or 2B), and the location of the rendered atlas (`resources/project-architecture/index.html`).
|
|
175
159
|
|
|
176
160
|
## Sample hints
|
|
177
161
|
|
|
178
|
-
- Multiple SQL paths on `service ↔ db` →
|
|
179
|
-
- Retry loops between `service ↔ generator(pure)` → call/return pair in the macro plus a `
|
|
180
|
-
-
|
|
181
|
-
-
|
|
162
|
+
- Multiple SQL paths on `service ↔ db` → call `edge add` once per SQL path so the macro shows them as separate edges.
|
|
163
|
+
- Retry loops between `service ↔ generator(pure)` → call/return pair in the macro plus a `dataflow add` step in the service with `--fn issueCode --writes "code"` describing the retry budget; a follow-up step `--fn issueCode --reads "code" --writes "row"` then captures the persistence attempt.
|
|
164
|
+
- Variable state transitions inside one function (e.g. `code` is computed, persisted, then returned) → emit one `dataflow add` per logical mutation, with `--fn` constant and `--reads` / `--writes` listing every variable that changes shape at that point. The sub-module page chips trace each variable's life cycle top-to-bottom.
|
|
165
|
+
- Cross-feature DB hand-off (A writes, B reads) → declare both sides' `INSERT_*` / `SELECT_*` functions on the `db` sub-module, then `edge add --kind data-row` from producer feature/submodule to consumer feature/submodule.
|
|
166
|
+
- Rollback / compensation across sub-modules → `edge add --kind failure --label "rollback on dup"`; rollback *within* a single sub-module belongs in `dataflow add` (with `--fn` set to whichever function owns the cleanup).
|
|
167
|
+
- Third-party systems → declare as `--kind external` sub-modules; the trust boundary becomes visible because the renderer styles them differently.
|
|
168
|
+
|
|
169
|
+
## References
|
|
170
|
+
|
|
171
|
+
- `lib/atlas/schema.js` — single source of truth for component fields, enums, and validation. `references/TEMPLATE_SPEC.md` mirrors that schema as a quick-reference cheat sheet.
|
|
172
|
+
- `lib/atlas/cli.js` — full verb dispatch (run `apltk architecture --help` for the live usage).
|
|
173
|
+
- `init-project-html/sample-demo/` — end-to-end YAML + rendered HTML for two features.
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "init-project-html"
|
|
3
|
-
short_description: "
|
|
3
|
+
short_description: "Declare the project HTML architecture atlas through `apltk architecture` CLI verbs"
|
|
4
4
|
default_prompt: >-
|
|
5
|
-
Use $init-project-html. Its `SKILL.md` is the authoritative rulebook
|
|
6
|
-
|
|
5
|
+
Use $init-project-html. Its `SKILL.md` is the authoritative rulebook; `references/TEMPLATE_SPEC.md` is a component-schema cheat sheet.
|
|
6
|
+
NEVER hand-author files under `resources/project-architecture/**/*.html`. The atlas state lives in YAML under `resources/project-architecture/atlas/` and every mutation goes through `apltk architecture <verb> ...`; the CLI owns layout, no-overlap, DOM, CSS, ARIA, and pan/zoom — both the macro SVG and each sub-module's internal-dataflow diagram are zoomable.
|
|
7
|
+
Read strategy to avoid context loss AND to enforce a hard responsibility split. STEP 1: enumerate the feature-module list (slug + entry + boundary resources) WITHOUT diving into function bodies.
|
|
7
8
|
STEP 2: branch by environment.
|
|
8
|
-
(2A, preferred) if subagents are available, dispatch ONE
|
|
9
|
-
(2B, no subagents) process features ONE AT A TIME — deep-read feature A, IMMEDIATELY
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
(2A, preferred) if subagents are available, dispatch ONE write-capable subagent per feature. Each subagent deep-reads ITS OWN feature and declares EVERY intra-feature interaction itself via `apltk architecture ... --feature <slug>`: `submodule add` (with the right `--kind`), `function add` / `variable add` / `dataflow add` (ordered — these steps carry the variable state transitions through the flow) / `error add` rows on every sub-module, and **every intra-feature edge** between its sub-modules (function calls, returns, error propagation, rollback / compensation — model failure / rollback paths as `--kind failure` edges and/or as ordered `dataflow add` steps). The subagent returns ONLY (i) sub-module list (slug + kind + one-line role) and (ii) outbound boundaries to other features' sub-modules (direction + edge kind + suggested label). The main agent never re-reads source for a delegated feature and never re-declares its components — it batches ONLY cross-feature `edge add` (and any shared `actor` / `meta`) from the aggregated outbound summaries, then runs `apltk architecture render` and `apltk architecture validate`.
|
|
10
|
+
(2B, no subagents) process features ONE AT A TIME — deep-read feature A, IMMEDIATELY drive the CLI (`feature add`, `submodule add` x N, `function add` / `variable add` / `dataflow add` / `error add` rows, intra-feature `edge add` including failure / rollback edges), drop A's function-level details from working memory, then move to feature B. For cross-feature edges pointing at a not-yet-declared feature, declare a placeholder with `feature add --slug <future> --title <future>` first and refine its title/story on a later pass.
|
|
11
|
+
CLI verbs to declare components (always kebab-case slugs; pass `--no-render` to batch then call `apltk architecture render` once at the end):
|
|
12
|
+
`apltk architecture meta set --title "..." --summary "..."`,
|
|
13
|
+
`apltk architecture actor add --id <kebab> --label "..."`,
|
|
14
|
+
`apltk architecture feature add --slug <kebab> --title "..." --story "..." [--depends-on a,b]`,
|
|
15
|
+
`apltk architecture submodule add --feature X --slug Y --kind ui|api|service|db|pure-fn|queue|external --role "..."`,
|
|
16
|
+
`apltk architecture function add --feature X --submodule Y --name fn --in "T1, T2" --out "R | ErrX" --side pure|io|write|tx|lock|network --purpose "..."`,
|
|
17
|
+
`apltk architecture variable add --feature X --submodule Y --name v --type T --scope call|tx|persist|instance|loop --purpose "..."`,
|
|
18
|
+
`apltk architecture dataflow add --feature X --submodule Y --step "..." [--fn <declared-fn>] [--reads "v1,v2"] [--writes "v3,v4"] [--at N]` (use `--fn` to surface function-to-function flow inside the sub-module; use `--reads` / `--writes` to surface variable state transitions — every name MUST match a `function`/`variable` already declared in the SAME sub-module or `validate` fails),
|
|
19
|
+
`apltk architecture error add --feature X --submodule Y --name ErrCode --when "..." --means "..."`,
|
|
20
|
+
`apltk architecture edge add --from <feature>[/sub] --to <feature>[/sub] --kind call|return|data-row|failure --label "..." [--id <stable>]`.
|
|
21
|
+
Intra-feature edges (both endpoints in the same feature with sub-modules) land in the feature YAML; cross-feature edges land in `atlas.index.yaml`. After the last mutation run `apltk architecture validate` — must return OK; resolve every reported error before reporting completion.
|
|
22
|
+
Each sub-module page describes ONLY itself (`sub-io` function I/O + `sub-vars` variables-with-business-purpose + `sub-dataflow` zoomable internal flow with fn pill + reads/writes chips + `sub-errors` local errors) — express any cross-boundary interaction as an edge, never as sub-module page prose. Two acceptance criteria gate completion: (1) the macro diagram clearly shows feature×sub-module relationships — data flow, call/return interaction logic, error handling, rollback — all as `--kind call|return|data-row|failure` edges (no cross-boundary path expressed only as prose); (2) every non-trivial sub-module's internal diagram clearly shows function-level interactions — `dataflow add --fn <declared-fn>` for function-to-function flow + `--reads` / `--writes` for variable state transitions through the run. Anchor every declaration to a concrete path / symbol / SQL / config; mark TBD when evidence is missing; record scanned roots and deliberate omissions in `meta.summary`. Report which read strategy (2A or 2B) was actually used and the location of the rendered atlas (`resources/project-architecture/index.html`).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* architecture.css — styling for the declarative atlas. The CLI copies
|
|
2
|
+
* this file into <outDir>/assets/. Style hooks (class names) are owned
|
|
3
|
+
* by render.js so agents never need to touch HTML by hand. */
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
--bg: #0f172a;
|
|
8
|
+
--panel: #111827;
|
|
9
|
+
--panel-soft: #1f2937;
|
|
10
|
+
--text: #e5e7eb;
|
|
11
|
+
--muted: #9ca3af;
|
|
12
|
+
--border: #334155;
|
|
13
|
+
--accent: #38bdf8;
|
|
14
|
+
--kind-ui: #38bdf8;
|
|
15
|
+
--kind-api: #818cf8;
|
|
16
|
+
--kind-service: #34d399;
|
|
17
|
+
--kind-db: #fbbf24;
|
|
18
|
+
--kind-pure-fn: #cbd5e1;
|
|
19
|
+
--kind-queue: #a78bfa;
|
|
20
|
+
--kind-external: #fb7185;
|
|
21
|
+
--edge-call: #60a5fa;
|
|
22
|
+
--edge-return: #94a3b8;
|
|
23
|
+
--edge-data-row: #fbbf24;
|
|
24
|
+
--edge-failure: #fb7185;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
* { box-sizing: border-box; }
|
|
28
|
+
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
|
|
29
|
+
|
|
30
|
+
a { color: var(--accent); text-decoration: none; }
|
|
31
|
+
a:hover { text-decoration: underline; }
|
|
32
|
+
|
|
33
|
+
h1, h2 { margin: 0 0 12px; font-weight: 600; letter-spacing: -0.01em; }
|
|
34
|
+
h1 { font-size: 28px; }
|
|
35
|
+
h2 { font-size: 18px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; font-size: 13px; }
|
|
36
|
+
|
|
37
|
+
p { line-height: 1.55; color: var(--text); }
|
|
38
|
+
|
|
39
|
+
/* ---- atlas (macro) ---- */
|
|
40
|
+
.atlas-header { padding: 28px 40px 16px; border-bottom: 1px solid var(--border); background: var(--panel); }
|
|
41
|
+
.atlas-summary { color: var(--muted); max-width: 80ch; margin: 8px 0 0; }
|
|
42
|
+
|
|
43
|
+
.atlas-main { display: grid; grid-template-columns: minmax(0, 3fr) minmax(280px, 1fr); gap: 24px; padding: 24px 40px 48px; }
|
|
44
|
+
|
|
45
|
+
.atlas-canvas { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; position: relative; }
|
|
46
|
+
.atlas-canvas__toolbar { position: absolute; top: 16px; right: 16px; display: flex; gap: 4px; z-index: 2; }
|
|
47
|
+
.atlas-canvas__toolbar button { background: var(--panel-soft); color: var(--text); border: 1px solid var(--border); padding: 4px 12px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
|
48
|
+
.atlas-canvas__toolbar button:hover { border-color: var(--accent); color: var(--accent); }
|
|
49
|
+
|
|
50
|
+
.atlas-canvas__viewport { width: 100%; max-height: 72vh; overflow: hidden; border-radius: 8px; background: #0b1220; }
|
|
51
|
+
.atlas-canvas__viewport.is-grabbing { cursor: grabbing; }
|
|
52
|
+
.atlas-canvas__viewport:not(.is-grabbing) { cursor: grab; }
|
|
53
|
+
|
|
54
|
+
.atlas-svg { width: 100%; height: auto; max-height: 72vh; display: block; user-select: none; touch-action: none; }
|
|
55
|
+
|
|
56
|
+
.atlas-legend { list-style: none; padding: 12px 4px 0; margin: 0; display: flex; gap: 18px; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
|
|
57
|
+
.atlas-legend li { display: inline-flex; align-items: center; gap: 6px; }
|
|
58
|
+
.legend-swatch { display: inline-block; width: 18px; height: 4px; border-radius: 2px; }
|
|
59
|
+
.legend-swatch--call { background: var(--edge-call); }
|
|
60
|
+
.legend-swatch--return { background: var(--edge-return); }
|
|
61
|
+
.legend-swatch--data-row { background: var(--edge-data-row); }
|
|
62
|
+
.legend-swatch--failure { background: var(--edge-failure); }
|
|
63
|
+
|
|
64
|
+
.atlas-index { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; max-height: 80vh; overflow: auto; }
|
|
65
|
+
|
|
66
|
+
.atlas-submodule-index { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
67
|
+
.atlas-submodule-index__item a { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px 8px; padding: 8px 10px; background: var(--panel-soft); border: 1px solid var(--border); border-radius: 8px; color: inherit; }
|
|
68
|
+
.atlas-submodule-index__item a:hover { border-color: var(--accent); }
|
|
69
|
+
.atlas-submodule-index__feature { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; grid-column: 1 / 3; }
|
|
70
|
+
.atlas-submodule-index__sub { font-weight: 600; }
|
|
71
|
+
.atlas-submodule-index__kind { font-size: 11px; padding: 1px 8px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border); color: var(--muted); }
|
|
72
|
+
.atlas-submodule-index__role { margin: 4px 10px 0; font-size: 12px; color: var(--muted); }
|
|
73
|
+
|
|
74
|
+
/* ---- SVG macro ---- */
|
|
75
|
+
.m-cluster__bg { fill: rgba(15, 23, 42, 0.55); stroke: var(--border); stroke-width: 1; }
|
|
76
|
+
.m-cluster__title { font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; fill: var(--text); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
|
|
77
|
+
.m-node { cursor: pointer; }
|
|
78
|
+
.m-node rect { fill: var(--panel-soft); stroke: var(--border); stroke-width: 1; transition: stroke 120ms ease, fill 120ms ease; }
|
|
79
|
+
.m-node:hover rect,
|
|
80
|
+
.m-node:focus rect,
|
|
81
|
+
.m-node:focus-visible rect { stroke: var(--accent); stroke-width: 1.6; fill: rgba(56, 189, 248, 0.08); }
|
|
82
|
+
.m-node:focus { outline: none; }
|
|
83
|
+
.m-node__title { font-size: 13px; font-weight: 600; fill: var(--text); }
|
|
84
|
+
.m-node__kind { font-size: 11px; fill: var(--muted); }
|
|
85
|
+
.m-node__role { font-size: 11px; fill: var(--muted); }
|
|
86
|
+
.m-node:hover .m-node__title,
|
|
87
|
+
.m-node:focus .m-node__title { fill: var(--accent); }
|
|
88
|
+
|
|
89
|
+
.m-node--ui rect { stroke: var(--kind-ui); }
|
|
90
|
+
.m-node--api rect { stroke: var(--kind-api); }
|
|
91
|
+
.m-node--service rect { stroke: var(--kind-service); }
|
|
92
|
+
.m-node--db rect { stroke: var(--kind-db); }
|
|
93
|
+
.m-node--pure-fn rect { stroke: var(--kind-pure-fn); }
|
|
94
|
+
.m-node--queue rect { stroke: var(--kind-queue); }
|
|
95
|
+
.m-node--external rect { stroke: var(--kind-external); }
|
|
96
|
+
|
|
97
|
+
.m-edge path { stroke-width: 1.6; }
|
|
98
|
+
.m-edge--call path { stroke: var(--edge-call); }
|
|
99
|
+
.m-edge--return path { stroke: var(--edge-return); stroke-dasharray: 6 4; }
|
|
100
|
+
.m-edge--data-row path { stroke: var(--edge-data-row); }
|
|
101
|
+
.m-edge--failure path { stroke: var(--edge-failure); }
|
|
102
|
+
|
|
103
|
+
.m-arrow path { fill: currentColor; }
|
|
104
|
+
.m-arrow--call { color: var(--edge-call); }
|
|
105
|
+
.m-arrow--return { color: var(--edge-return); }
|
|
106
|
+
.m-arrow--data-row { color: var(--edge-data-row); }
|
|
107
|
+
.m-arrow--failure { color: var(--edge-failure); }
|
|
108
|
+
|
|
109
|
+
.m-edge__label { fill: var(--muted); font-size: 11px; }
|
|
110
|
+
|
|
111
|
+
/* ---- feature page ---- */
|
|
112
|
+
.feature-header, .submodule-header { padding: 24px 40px 12px; border-bottom: 1px solid var(--border); background: var(--panel); }
|
|
113
|
+
.feature-breadcrumb, .submodule-breadcrumb { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
|
|
114
|
+
.feature-depends { font-size: 13px; color: var(--muted); margin: 8px 0 0; }
|
|
115
|
+
.feature-main, .submodule-main { padding: 24px 40px 48px; display: flex; flex-direction: column; gap: 32px; }
|
|
116
|
+
.feature-story p { max-width: 80ch; }
|
|
117
|
+
|
|
118
|
+
.submodule-nav { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
|
|
119
|
+
.submodule-card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }
|
|
120
|
+
.submodule-card__link { display: flex; align-items: center; justify-content: space-between; color: inherit; font-weight: 600; }
|
|
121
|
+
.submodule-card__kind { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); }
|
|
122
|
+
.submodule-card__role { margin: 8px 0 0; font-size: 13px; color: var(--muted); }
|
|
123
|
+
|
|
124
|
+
.feature-edges__list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
125
|
+
.feature-edges__item { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 2fr); gap: 8px; padding: 8px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; font-size: 13px; }
|
|
126
|
+
.feature-edges__kind { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; align-self: center; }
|
|
127
|
+
.feature-edges__item--call { border-left: 4px solid var(--edge-call); }
|
|
128
|
+
.feature-edges__item--return { border-left: 4px solid var(--edge-return); }
|
|
129
|
+
.feature-edges__item--data-row { border-left: 4px solid var(--edge-data-row); }
|
|
130
|
+
.feature-edges__item--failure { border-left: 4px solid var(--edge-failure); }
|
|
131
|
+
|
|
132
|
+
/* ---- submodule page ---- */
|
|
133
|
+
.submodule-kind { display: inline-block; font-size: 12px; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--border); color: var(--muted); margin-left: 8px; vertical-align: middle; text-transform: uppercase; letter-spacing: 0.06em; }
|
|
134
|
+
.submodule-role { color: var(--muted); margin: 8px 0 0; max-width: 80ch; }
|
|
135
|
+
|
|
136
|
+
.sub-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
137
|
+
.sub-table th, .sub-table td { padding: 8px 12px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
|
|
138
|
+
.sub-table th { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; background: var(--panel); }
|
|
139
|
+
|
|
140
|
+
.sub-section__empty { color: var(--muted); font-style: italic; font-size: 13px; }
|
|
141
|
+
|
|
142
|
+
.sub-dataflow__canvas { position: relative; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; }
|
|
143
|
+
.sub-dataflow__toolbar { position: absolute; top: 16px; right: 16px; display: flex; gap: 4px; z-index: 2; }
|
|
144
|
+
.sub-dataflow__toolbar button { background: var(--panel-soft); color: var(--text); border: 1px solid var(--border); padding: 4px 12px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
|
145
|
+
.sub-dataflow__toolbar button:hover { border-color: var(--accent); color: var(--accent); }
|
|
146
|
+
.sub-dataflow__viewport { width: 100%; max-height: 60vh; overflow: hidden; border-radius: 8px; background: #0b1220; }
|
|
147
|
+
.sub-dataflow__viewport.is-grabbing { cursor: grabbing; }
|
|
148
|
+
.sub-dataflow__viewport:not(.is-grabbing) { cursor: grab; }
|
|
149
|
+
.sub-dataflow__svg { width: 100%; height: auto; max-height: 60vh; display: block; user-select: none; touch-action: none; }
|
|
150
|
+
.sub-dataflow__badge { fill: var(--panel-soft); stroke: var(--accent); stroke-width: 1.4; }
|
|
151
|
+
.sub-dataflow__badge-text { font-family: ui-sans-serif, system-ui, sans-serif; font-size: 13px; font-weight: 600; fill: var(--accent); }
|
|
152
|
+
.sub-dataflow__step .sub-dataflow__box { fill: var(--panel-soft); stroke: var(--border); stroke-width: 1; }
|
|
153
|
+
.sub-dataflow__step:hover .sub-dataflow__box { stroke: var(--accent); }
|
|
154
|
+
.sub-dataflow__text { font-family: ui-sans-serif, system-ui, sans-serif; font-size: 14px; fill: var(--text); }
|
|
155
|
+
.sub-dataflow__arrow { stroke: var(--muted); stroke-width: 1.6; }
|
|
156
|
+
.sub-dataflow__fn-bg { fill: rgba(56, 189, 248, 0.12); stroke: var(--accent); stroke-width: 1; }
|
|
157
|
+
.sub-dataflow__fn-text { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; font-weight: 600; fill: var(--accent); letter-spacing: 0.02em; }
|
|
158
|
+
.sub-dataflow__chip { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; font-weight: 500; }
|
|
159
|
+
.sub-dataflow__chip--reads { fill: var(--kind-service); }
|
|
160
|
+
.sub-dataflow__chip--writes { fill: var(--kind-db); }
|
|
161
|
+
.sub-dataflow__empty { color: var(--muted); font-style: italic; }
|