@laitszkin/apollo-toolkit 3.11.3 → 3.11.5
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/AGENTS.md +1 -0
- package/CHANGELOG.md +30 -0
- package/README.md +5 -1
- 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/commit-and-push/README.md +0 -2
- package/commit-and-push/SKILL.md +5 -5
- package/commit-and-push/agents/openai.yaml +1 -1
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/init-project-html/lib/atlas/assets/architecture.css +15 -0
- package/init-project-html/lib/atlas/layout.js +225 -55
- package/init-project-html/lib/atlas/render.js +20 -8
- 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 +1 -1
- 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/review-change-set/README.md +3 -3
- package/review-change-set/SKILL.md +36 -24
- package/review-change-set/agents/openai.yaml +2 -2
- package/review-spec-related-changes/README.md +3 -2
- package/review-spec-related-changes/SKILL.md +12 -7
- package/review-spec-related-changes/agents/openai.yaml +1 -1
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
- package/update-project-html/README.md +38 -0
- package/update-project-html/SKILL.md +125 -0
- package/update-project-html/agents/openai.yaml +11 -0
- package/version-release/README.md +0 -2
- package/version-release/SKILL.md +3 -3
- package/version-release/agents/openai.yaml +1 -1
package/AGENTS.md
CHANGED
|
@@ -62,6 +62,7 @@ This repository enables users to install and run a curated set of reusable agent
|
|
|
62
62
|
- Users can add focused observability to opaque workflows through targeted logs, metrics, traces, and tests.
|
|
63
63
|
- Users can iteratively improve repository code quality through behavior-neutral naming, simplification, module-boundary, logging, and test-coverage passes.
|
|
64
64
|
- Users can iteratively improve repository performance through evidence-backed module scans, safe hot-path optimization, benchmark guardrails, batching, caching, allocation, concurrency, and repeated full-codebase stage gates.
|
|
65
|
+
- Users can refresh the project HTML architecture atlas to reflect the latest committed or staged code changes by dispatching one subagent per affected feature and updating the base atlas via `apltk architecture` (no spec overlay).
|
|
65
66
|
- Users can select risk-driven test levels and define unit drift checks through a shared testing strategy skill.
|
|
66
67
|
- Users can build against Jupiter's official Solana swap, token, price, lending, trigger, recurring, and portfolio APIs with an evidence-based development guide.
|
|
67
68
|
- Users can render and embed math formulas with KaTeX using official documentation-backed guidance and reusable rendering scripts.
|
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,36 @@ All notable changes to this repository are documented in this file.
|
|
|
10
10
|
|
|
11
11
|
### Fixed
|
|
12
12
|
|
|
13
|
+
## [v3.11.5] - 2026-05-12
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- New skill `update-project-html`: refreshes the base project HTML architecture atlas (`resources/project-architecture/`) to reflect the latest code changes by reading the existing atlas, resolving the diff scope (`git diff --stat` + staged by default, or against a user-named ref), filtering to code-affecting hunks, and dispatching one write-capable subagent per affected feature to update declarations through `apltk architecture` (no `--spec`); the main agent waits until every subagent finishes before declaring cross-feature edges, then runs `apltk architecture render` and `apltk architecture validate`.
|
|
18
|
+
- README: notes for `update-project-html`, the `commit-and-push` / `version-release` decoupling, the `review-change-set` decoupling + subagent guidance, and the `review-spec-related-changes` parallel secondary-subagent pattern. AGENTS.md: new business-flow bullet for `update-project-html`.
|
|
19
|
+
- Tests (`test/skill-workflows.test.js`): assertions for the four behavior changes above (decoupling and subagent recommendations).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- `commit-and-push` and `version-release` no longer chain `discover-edge-cases` or `discover-security-issues` automatically. The `review-change-set` gate stays mandatory for code-affecting scope, and other conditional gates (e.g. `archive-specs`) remain unchanged. Invoke security or edge-case skills explicitly when their scenario applies.
|
|
24
|
+
- `review-change-set` no longer chains `discover-security-issues` and now recommends dispatching one read-only subagent per coherent scope cluster for multi-file diffs; the main agent aggregates structured architecture + simplification findings without re-reading delegated files. Tiny diffs are still reviewed inline.
|
|
25
|
+
- `review-spec-related-changes` keeps its three secondary dependencies (`review-change-set`, `discover-edge-cases`, `discover-security-issues`) but now prefers running each one in its own read-only subagent in parallel, and may also fan out independent business-goal requirement clusters to read-only subagents.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
## [v3.11.4] - 2026-05-12
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Macro atlas: `measureEdgeLabel` wraps long edge labels (including CJK) with honest width/height for elkjs so orthogonal routes reserve space proportional to label size; `renderMacroSvg` paints wrapped labels as stacked `<tspan>` lines on one anchor.
|
|
34
|
+
- Macro atlas: isolated feature clusters (no intra-feature edges and not an endpoint of a root-level cross-feature edge) use elk **rectpacking** with aspect-ratio hint for a grid-like pack instead of a tall vertical column of sub-modules.
|
|
35
|
+
- Tests: CJK submodule sizing, edge-label wrapping, rectpacking vs layered cluster selection, compact rectpack geometry, `m-edge--cross` markup, and cross-edge CSS dim/hover rules.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- Macro layout (`layout.js`): CJK-aware text width and visual-width wrapping for sub-module **role** lines; raised `SUB_WIDTH_MAX` / `SUB_HEIGHT_MAX` and `MAX_ROLE_LINES`; sub-module boxes prefer fewer wrapped lines when content allows.
|
|
40
|
+
- Root ELK graph: `elk.aspectRatio` 16:9, tighter node/layer spacing and padding, `BALANCED` node placement, `EDGE_LENGTH` post-compaction; cluster padding and internal spacing reduced.
|
|
41
|
+
- Cross-feature edges: root-level edges render with `m-edge--cross`; default lower opacity/thinner stroke, full strength on hover/focus so intra-feature flow reads first.
|
|
42
|
+
|
|
13
43
|
## [v3.11.3] - 2026-05-11
|
|
14
44
|
|
|
15
45
|
### Added
|
package/README.md
CHANGED
|
@@ -56,6 +56,7 @@ A curated skill catalog for Codex, OpenClaw, Trae, Agents, and Claude Code with
|
|
|
56
56
|
- systematic-debug
|
|
57
57
|
- test-case-strategy
|
|
58
58
|
- text-to-short-video
|
|
59
|
+
- update-project-html
|
|
59
60
|
- version-release
|
|
60
61
|
- video-production
|
|
61
62
|
- weekly-financial-event-report
|
|
@@ -210,7 +211,10 @@ Compatibility note:
|
|
|
210
211
|
- `recover-missing-plan` is a local skill used by `enhance-existing-features` and `ship-github-issue-fix` when a referenced `docs/plans/...` spec set is missing or archived.
|
|
211
212
|
- `maintain-skill-catalog` can conditionally use `find-skills`, but its install source is not verified in this repository, so it is intentionally omitted from the table.
|
|
212
213
|
- `read-github-issue` uses GitHub CLI (`gh`) directly for remote issue discovery and inspection, so it does not add any extra skill dependency.
|
|
213
|
-
- `review-spec-related-changes` is a local skill that depends on `review-change-set`, `discover-edge-cases`, and `discover-security-issues` for secondary code-practice checks after business-goal completion is reviewed against the governing specs.
|
|
214
|
+
- `review-spec-related-changes` is a local skill that depends on `review-change-set`, `discover-edge-cases`, and `discover-security-issues` for secondary code-practice checks after business-goal completion is reviewed against the governing specs; it prefers running each secondary skill in its own read-only subagent in parallel.
|
|
215
|
+
- `update-project-html` is a local skill that depends on `init-project-html` for semantic rules and on the `apltk architecture` CLI to refresh the base atlas after code changes; for spec overlay diagrams use `spec-to-project-html` instead.
|
|
216
|
+
- `commit-and-push` and `version-release` no longer chain `discover-edge-cases` or `discover-security-issues`; invoke those skills explicitly when the review surface needs them.
|
|
217
|
+
- `review-change-set` no longer chains `discover-security-issues`; for multi-file diffs it prefers dispatching one read-only subagent per scope cluster.
|
|
214
218
|
|
|
215
219
|
## Release publishing
|
|
216
220
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -31,6 +31,4 @@ When the diff includes code changes, `review-change-set` is still a conditional
|
|
|
31
31
|
|
|
32
32
|
Apply the same rule to every other conditional gate: if its scenario is met during classification, it becomes blocking before commit rather than a best-effort follow-up.
|
|
33
33
|
|
|
34
|
-
That includes risk-driven review gates such as `discover-edge-cases` and `discover-security-issues` whenever the change surface makes them applicable.
|
|
35
|
-
|
|
36
34
|
For release workflows, use `version-release`.
|
package/commit-and-push/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: commit-and-push
|
|
3
3
|
description: >-
|
|
4
|
-
Commit and push only (no semver): inspect staged vs unstaged, classify scopes, run mandated
|
|
4
|
+
Commit and push only (no semver): inspect staged vs unstaged, classify scopes, run the mandated `review-change-set` for code-affecting scope, then **`submission-readiness-check`** BEFORE the final commit honoring `CHANGELOG.md` Unreleased + `archive-specs` redirections, preserve intentional staging splits, forbid UI git stubs, VERIFY remote hashes post-push. **`version-release` elsewhere**.
|
|
5
5
|
Use for “please commit”, “submit”, “push branch” lacking explicit semver/tag language **STOP** tagging here… BAD skip readiness red… GOOD staged subset untouched unrelated dirty files changelog mirrors diff… hashes `git rev-parse HEAD` versus upstream… archive specs before commit flagged…
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
## Dependencies
|
|
11
11
|
|
|
12
12
|
- Required: **`submission-readiness-check`** immediately before the **final** commit.
|
|
13
|
-
- Conditional: **`archive-specs`** when readiness (or completed specs) requires doc conversion or categorized `docs/` alignment; **`review-change-set`** for every **code-affecting** scope
|
|
13
|
+
- Conditional: **`archive-specs`** when readiness (or completed specs) requires doc conversion or categorized `docs/` alignment; **`review-change-set`** for every **code-affecting** scope.
|
|
14
14
|
- Optional: none.
|
|
15
15
|
- Fallback: Any **required** dependency unavailable ⇒ **MUST** stop and report—**MUST NOT** “light” commit.
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ description: >-
|
|
|
18
18
|
|
|
19
19
|
- **MUST** use real `git` mutations (`git add`, `git commit`, `git push`, `git stash`, etc.); **MUST NOT** treat UI tokens (`::git-commit`, IDE buttons) as proof of history.
|
|
20
20
|
- **MUST** run **`submission-readiness-check`** before final commit; unresolved readiness (e.g. stale/missing `CHANGELOG.md` **Unreleased**, doc drift) **blocks** commit.
|
|
21
|
-
- Code-affecting: **`review-change-set` MANDATORY**; unresolved confirmed findings **block**.
|
|
21
|
+
- Code-affecting: **`review-change-set` MANDATORY**; unresolved confirmed findings **block**.
|
|
22
22
|
- **`archive-specs`**: when readiness says convert/archive or `docs/` mismatch—**MUST** run **before** final commit, not as a vague follow-up.
|
|
23
23
|
- **MUST** reconcile **staged vs unstaged** with user intent—**MUST NOT** broaden scope by auto-staging unrelated files when user staged a subset.
|
|
24
24
|
- **`CHANGELOG.md` `Unreleased`**: for code-affecting or user-visible docs, **MUST** reflect this change before commit; reopen diff after edits to match commit scope.
|
|
@@ -27,7 +27,7 @@ description: >-
|
|
|
27
27
|
- **MUST NOT** run version bump, tag, or GitHub release (**use `version-release`**).
|
|
28
28
|
- Clean worktree requests: **MUST** inspect `HEAD`, upstream, last commit—**MUST NOT** fabricate “pushed” when already satisfied or impossible.
|
|
29
29
|
|
|
30
|
-
**Repository regression checks (verbatim requirements):** Treat root `CHANGELOG.md` `Unreleased` coverage as mandatory for code-affecting or user-visible changes. Re-open the final `CHANGELOG.md` diff after readiness updates. **`review-change-set` is required for code-affecting changes**; Run `review-change-set` for every code-affecting change before continuing; treat unresolved review findings as blocking. Any conditional gate whose trigger is confirmed by this classification becomes mandatory before commit. Treat every scenario-matched gate as blocking before commit.
|
|
30
|
+
**Repository regression checks (verbatim requirements):** Treat root `CHANGELOG.md` `Unreleased` coverage as mandatory for code-affecting or user-visible changes. Re-open the final `CHANGELOG.md` diff after readiness updates. **`review-change-set` is required for code-affecting changes**; Run `review-change-set` for every code-affecting change before continuing; treat unresolved review findings as blocking. Any conditional gate whose trigger is confirmed by this classification becomes mandatory before commit. Treat every scenario-matched gate as blocking before commit.
|
|
31
31
|
|
|
32
32
|
## Standards (summary)
|
|
33
33
|
|
|
@@ -54,7 +54,7 @@ description: >-
|
|
|
54
54
|
3. **Branch target** — Honor user branch; if switch needed, protect unrelated changes; cherry-pick/replay off wrong branch safely; worktree cases: identify authoritative target **before** replay.
|
|
55
55
|
- **Pause →** Am I about to merge noise because diff > issue scope—should I stop and narrow first?
|
|
56
56
|
|
|
57
|
-
4. **Code-affecting gates** — `review-change-set` always;
|
|
57
|
+
4. **Code-affecting gates** — `review-change-set` always; fix or document blockers; re-test material logic.
|
|
58
58
|
|
|
59
59
|
5. **Readiness** — Run **`submission-readiness-check`**; if it routes to **`archive-specs`**, run that **now**; fix `Unreleased` bullets; recheck changelog vs staged intent.
|
|
60
60
|
- **Pause →** Could I commit while readiness still red—**why not**?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Commit and Push"
|
|
3
3
|
short_description: "Submit local changes with commit and push only"
|
|
4
|
-
default_prompt: "Use $commit-and-push to inspect the current git state and classify the diff. Treat every conditional gate whose scenario is met as blocking before any commit: if the change set includes code changes, run $review-change-set; if
|
|
4
|
+
default_prompt: "Use $commit-and-push to inspect the current git state and classify the diff. Treat every conditional gate whose scenario is met as blocking before any commit: if the change set includes code changes, run $review-change-set; if completed specs should be converted or docs need normalization, ensure $archive-specs runs through $submission-readiness-check; if changelog synchronization is needed, complete it before continuing. Then run any additional required code-quality skills, hand the repository to $submission-readiness-check so it can synchronize completed plan archives, project docs, AGENTS.md/CLAUDE.md, and CHANGELOG.md before any commit, confirm root CHANGELOG.md Unreleased reflects the actual pending change set, preserve user staging intent, create a concise Conventional Commit, and push to the intended branch without any versioning or release steps."
|
|
Binary file
|
|
Binary file
|
|
@@ -433,8 +433,23 @@ p { line-height: 1.6; color: var(--vellum-soft); }
|
|
|
433
433
|
font-family: var(--font-mono);
|
|
434
434
|
font-size: 11px;
|
|
435
435
|
letter-spacing: 0.02em;
|
|
436
|
+
paint-order: stroke fill;
|
|
437
|
+
stroke: var(--ink);
|
|
438
|
+
stroke-width: 3.5;
|
|
439
|
+
stroke-linejoin: round;
|
|
440
|
+
pointer-events: none;
|
|
436
441
|
}
|
|
437
442
|
|
|
443
|
+
/* Cross-feature edges are routed across the entire atlas and tend to
|
|
444
|
+
be the loudest lines on screen. Dim them so intra-feature flow
|
|
445
|
+
reads first; restore full strength on hover/focus. */
|
|
446
|
+
.m-edge--cross path { opacity: 0.5; stroke-width: 1.1; }
|
|
447
|
+
.m-edge--cross .m-edge__label { opacity: 0.7; }
|
|
448
|
+
.m-edge--cross:hover path,
|
|
449
|
+
.m-edge--cross:focus-within path { opacity: 1; stroke-width: 1.8; }
|
|
450
|
+
.m-edge--cross:hover .m-edge__label,
|
|
451
|
+
.m-edge--cross:focus-within .m-edge__label { opacity: 1; }
|
|
452
|
+
|
|
438
453
|
/* =================================================================
|
|
439
454
|
feature page
|
|
440
455
|
================================================================= */
|
|
@@ -17,11 +17,15 @@ const ELK = require('elkjs');
|
|
|
17
17
|
const SUB_WIDTH = 240;
|
|
18
18
|
const SUB_HEIGHT = 92;
|
|
19
19
|
|
|
20
|
-
// Box-sizing knobs (intrinsic SVG coordinates).
|
|
20
|
+
// Box-sizing knobs (intrinsic SVG coordinates). The width/height caps
|
|
21
|
+
// are intentionally generous so CJK roles — which paint at ~1em per
|
|
22
|
+
// character instead of ~0.55em — can grow into a readable rectangle
|
|
23
|
+
// without spilling outside the box (the original ~360×220 cap was
|
|
24
|
+
// only honest for Latin text).
|
|
21
25
|
const SUB_WIDTH_MIN = 220;
|
|
22
|
-
const SUB_WIDTH_MAX =
|
|
26
|
+
const SUB_WIDTH_MAX = 520;
|
|
23
27
|
const SUB_HEIGHT_MIN = 92;
|
|
24
|
-
const SUB_HEIGHT_MAX =
|
|
28
|
+
const SUB_HEIGHT_MAX = 360;
|
|
25
29
|
const SUB_SIDE_PAD = 16;
|
|
26
30
|
const SUB_TOP_PAD = 14;
|
|
27
31
|
const SUB_BOTTOM_PAD = 14;
|
|
@@ -30,12 +34,22 @@ const KIND_LINE = 16; // kind chip line
|
|
|
30
34
|
const ROLE_LINE = 16; // each role line
|
|
31
35
|
const KIND_GAP = 4;
|
|
32
36
|
const ROLE_GAP = 8;
|
|
33
|
-
const MAX_ROLE_LINES =
|
|
37
|
+
const MAX_ROLE_LINES = 6;
|
|
34
38
|
|
|
35
|
-
const CLUSTER_PAD_TOP =
|
|
36
|
-
const CLUSTER_PAD_SIDE =
|
|
37
|
-
const CLUSTER_PAD_BOTTOM =
|
|
38
|
-
|
|
39
|
+
const CLUSTER_PAD_TOP = 44;
|
|
40
|
+
const CLUSTER_PAD_SIDE = 16;
|
|
41
|
+
const CLUSTER_PAD_BOTTOM = 18;
|
|
42
|
+
|
|
43
|
+
// Font sizes mirror architecture.css so the layout math agrees with
|
|
44
|
+
// what the SVG actually paints.
|
|
45
|
+
const SLUG_FONT_PX = 15;
|
|
46
|
+
const KIND_FONT_PX = 10;
|
|
47
|
+
const ROLE_FONT_PX = 11.5;
|
|
48
|
+
const EDGE_LABEL_FONT_PX = 11;
|
|
49
|
+
const EDGE_LABEL_LINE_PX = 14;
|
|
50
|
+
const EDGE_LABEL_LINE_WIDTH_MAX = 220;
|
|
51
|
+
const EDGE_LABEL_PAD_X = 18;
|
|
52
|
+
const EDGE_LABEL_PAD_Y = 8;
|
|
39
53
|
|
|
40
54
|
const KIND_LABELS = {
|
|
41
55
|
ui: 'UI',
|
|
@@ -47,30 +61,128 @@ const KIND_LABELS = {
|
|
|
47
61
|
external: 'external',
|
|
48
62
|
};
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
// East-Asian Wide / Full-width detection. The ranges follow the
|
|
65
|
+
// canonical "wide" / "fullwidth" code blocks (Unicode TR11) — we use
|
|
66
|
+
// them to switch between a ~0.55em-per-char Latin metric and a
|
|
67
|
+
// ~1.0em-per-char CJK metric so layout matches paint.
|
|
68
|
+
function isWideChar(ch) {
|
|
69
|
+
const code = ch.codePointAt(0);
|
|
70
|
+
return (
|
|
71
|
+
(code >= 0x1100 && code <= 0x115F) ||
|
|
72
|
+
(code >= 0x2E80 && code <= 0x9FFF) ||
|
|
73
|
+
(code >= 0xA000 && code <= 0xA4CF) ||
|
|
74
|
+
(code >= 0xAC00 && code <= 0xD7A3) ||
|
|
75
|
+
(code >= 0xF900 && code <= 0xFAFF) ||
|
|
76
|
+
(code >= 0xFE30 && code <= 0xFE4F) ||
|
|
77
|
+
(code >= 0xFF00 && code <= 0xFF60) ||
|
|
78
|
+
(code >= 0xFFE0 && code <= 0xFFE6) ||
|
|
79
|
+
(code >= 0x20000 && code <= 0x2FFFD)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function charWidthFactor(ch) {
|
|
84
|
+
if (isWideChar(ch)) return 1.0;
|
|
85
|
+
if (ch === ' ') return 0.30;
|
|
86
|
+
if (/[A-Za-z0-9]/.test(ch)) return 0.55;
|
|
87
|
+
return 0.50;
|
|
53
88
|
}
|
|
54
89
|
|
|
55
|
-
// Approximate render width of a string in the target font. The 0.6
|
|
56
|
-
// factor is a deliberate over-estimate for our sans-serif stack so
|
|
57
|
-
// the chosen width almost always leaves a little breathing room.
|
|
58
90
|
function approxTextWidth(text, fontPx) {
|
|
59
|
-
|
|
91
|
+
if (!text) return 0;
|
|
92
|
+
let w = 0;
|
|
93
|
+
for (const ch of String(text)) w += fontPx * charWidthFactor(ch);
|
|
94
|
+
return w;
|
|
60
95
|
}
|
|
61
96
|
|
|
62
|
-
|
|
97
|
+
// Greedy wrap by *visual* width. CJK characters break between any
|
|
98
|
+
// two characters; ASCII words stay whole; whitespace is a soft break.
|
|
99
|
+
function wrapByVisualWidth(text, maxWidthPx, fontPx) {
|
|
63
100
|
if (!text) return [];
|
|
64
|
-
const
|
|
101
|
+
const str = String(text);
|
|
65
102
|
const lines = [];
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
103
|
+
let line = '';
|
|
104
|
+
let lineW = 0;
|
|
105
|
+
|
|
106
|
+
function flush() {
|
|
107
|
+
if (line.length > 0) lines.push(line.replace(/\s+$/, ''));
|
|
108
|
+
line = '';
|
|
109
|
+
lineW = 0;
|
|
71
110
|
}
|
|
72
|
-
|
|
73
|
-
|
|
111
|
+
|
|
112
|
+
let i = 0;
|
|
113
|
+
while (i < str.length) {
|
|
114
|
+
const cp = str.codePointAt(i);
|
|
115
|
+
const ch = String.fromCodePoint(cp);
|
|
116
|
+
const advance = ch.length;
|
|
117
|
+
|
|
118
|
+
if (ch === '\n') {
|
|
119
|
+
flush();
|
|
120
|
+
i += advance;
|
|
121
|
+
} else if (isWideChar(ch)) {
|
|
122
|
+
const w = fontPx * 1.0;
|
|
123
|
+
if (line && lineW + w > maxWidthPx) flush();
|
|
124
|
+
line += ch;
|
|
125
|
+
lineW += w;
|
|
126
|
+
i += advance;
|
|
127
|
+
} else if (/\s/.test(ch)) {
|
|
128
|
+
const w = fontPx * 0.30;
|
|
129
|
+
if (line) {
|
|
130
|
+
if (lineW + w > maxWidthPx) flush();
|
|
131
|
+
else { line += ch; lineW += w; }
|
|
132
|
+
}
|
|
133
|
+
i += advance;
|
|
134
|
+
} else {
|
|
135
|
+
let word = '';
|
|
136
|
+
let wordW = 0;
|
|
137
|
+
while (i < str.length) {
|
|
138
|
+
const cp2 = str.codePointAt(i);
|
|
139
|
+
const ch2 = String.fromCodePoint(cp2);
|
|
140
|
+
if (isWideChar(ch2) || /\s/.test(ch2)) break;
|
|
141
|
+
word += ch2;
|
|
142
|
+
wordW += fontPx * charWidthFactor(ch2);
|
|
143
|
+
i += ch2.length;
|
|
144
|
+
}
|
|
145
|
+
if (line && lineW + wordW > maxWidthPx) flush();
|
|
146
|
+
line += word;
|
|
147
|
+
lineW += wordW;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
flush();
|
|
151
|
+
return lines.filter((l) => l.length > 0);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Short labels (feature title, sub-module slug) — single-line width
|
|
155
|
+
// only. Capped so very long ASCII slugs do not blow up the cluster
|
|
156
|
+
// header band; CJK titles still get an honest visual width.
|
|
157
|
+
function estimateLabelWidth(text) {
|
|
158
|
+
if (!text) return 0;
|
|
159
|
+
return Math.min(320, Math.max(40, Math.ceil(approxTextWidth(text, 13)) + 16));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Edge labels — wrap into a tall enough rectangle so elkjs reserves
|
|
163
|
+
// proportional edge length (longer text ⇒ longer arrow). The wrapped
|
|
164
|
+
// text is stored with '\n' separators so render.js can paint each
|
|
165
|
+
// line as its own <tspan> centered on the same anchor.
|
|
166
|
+
function measureEdgeLabel(text) {
|
|
167
|
+
if (!text) return { text: '', lines: [], width: 0, height: 0 };
|
|
168
|
+
const raw = String(text);
|
|
169
|
+
const singleW = approxTextWidth(raw, EDGE_LABEL_FONT_PX);
|
|
170
|
+
if (singleW <= EDGE_LABEL_LINE_WIDTH_MAX) {
|
|
171
|
+
return {
|
|
172
|
+
text: raw,
|
|
173
|
+
lines: [raw],
|
|
174
|
+
width: Math.max(40, Math.ceil(singleW) + EDGE_LABEL_PAD_X),
|
|
175
|
+
height: EDGE_LABEL_LINE_PX + EDGE_LABEL_PAD_Y,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const lines = wrapByVisualWidth(raw, EDGE_LABEL_LINE_WIDTH_MAX, EDGE_LABEL_FONT_PX);
|
|
179
|
+
const widestLine = lines.reduce((m, l) => Math.max(m, approxTextWidth(l, EDGE_LABEL_FONT_PX)), 0);
|
|
180
|
+
return {
|
|
181
|
+
text: lines.join('\n'),
|
|
182
|
+
lines,
|
|
183
|
+
width: Math.ceil(widestLine) + EDGE_LABEL_PAD_X,
|
|
184
|
+
height: lines.length * EDGE_LABEL_LINE_PX + EDGE_LABEL_PAD_Y,
|
|
185
|
+
};
|
|
74
186
|
}
|
|
75
187
|
|
|
76
188
|
// measureSubmodule picks a width + height that fit the slug, the kind
|
|
@@ -83,26 +195,33 @@ function measureSubmodule(sub) {
|
|
|
83
195
|
const kindLabel = KIND_LABELS[sub && sub.kind] || (sub && sub.kind) || 'service';
|
|
84
196
|
const role = (sub && sub.role) || '';
|
|
85
197
|
|
|
86
|
-
const slugW = approxTextWidth(slug,
|
|
87
|
-
|
|
198
|
+
const slugW = approxTextWidth(slug, SLUG_FONT_PX);
|
|
199
|
+
// Kind chip is upper-cased + letter-spaced in CSS (0.22em); add ~30% slack.
|
|
200
|
+
const kindW = approxTextWidth(kindLabel.toUpperCase(), KIND_FONT_PX) * 1.3;
|
|
88
201
|
const baseInner = Math.max(slugW, kindW);
|
|
89
202
|
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
|
|
203
|
+
// Auto-expand the box to fit the role with as few lines as
|
|
204
|
+
// possible: prefer 1 line if it fits inside SUB_WIDTH_MAX, else 2,
|
|
205
|
+
// else 3 — and only wrap further when even 3 lines would exceed
|
|
206
|
+
// the cap. This is what "boxes auto-expand to their content" means
|
|
207
|
+
// for CJK roles whose glyphs are ~2× wider than Latin.
|
|
208
|
+
const roleVisualW = approxTextWidth(role, ROLE_FONT_PX);
|
|
209
|
+
const maxInner = SUB_WIDTH_MAX - SUB_SIDE_PAD * 2;
|
|
93
210
|
let chosenInner;
|
|
94
211
|
if (!role) {
|
|
95
212
|
chosenInner = baseInner;
|
|
96
213
|
} else {
|
|
97
|
-
|
|
98
|
-
|
|
214
|
+
let target;
|
|
215
|
+
if (roleVisualW <= maxInner) target = roleVisualW;
|
|
216
|
+
else if (Math.ceil(roleVisualW / 2) <= maxInner) target = Math.ceil(roleVisualW / 2);
|
|
217
|
+
else target = Math.ceil(roleVisualW / 3);
|
|
218
|
+
chosenInner = Math.max(baseInner, Math.max(180, target));
|
|
99
219
|
}
|
|
100
220
|
const width = Math.max(SUB_WIDTH_MIN, Math.min(SUB_WIDTH_MAX, Math.ceil(chosenInner + SUB_SIDE_PAD * 2)));
|
|
101
221
|
|
|
102
222
|
// With the chosen width fixed, wrap the role for real and count lines.
|
|
103
223
|
const innerW = width - SUB_SIDE_PAD * 2;
|
|
104
|
-
|
|
105
|
-
let roleLines = role ? wrapToLines(role, charsPerLine) : [];
|
|
224
|
+
let roleLines = role ? wrapByVisualWidth(role, innerW, ROLE_FONT_PX) : [];
|
|
106
225
|
if (roleLines.length > MAX_ROLE_LINES) {
|
|
107
226
|
roleLines = roleLines.slice(0, MAX_ROLE_LINES);
|
|
108
227
|
const last = roleLines[MAX_ROLE_LINES - 1];
|
|
@@ -129,7 +248,53 @@ function endpointId(endpoint, ownerFeature) {
|
|
|
129
248
|
return null;
|
|
130
249
|
}
|
|
131
250
|
|
|
251
|
+
function clusterLayoutOptions(feature, isCrossEdgeEndpoint) {
|
|
252
|
+
// If the feature declares intra-feature flow edges OR is an
|
|
253
|
+
// endpoint of any root-level cross-feature edge, the cluster must
|
|
254
|
+
// use a hierarchy-friendly directional algorithm (layered) so elk
|
|
255
|
+
// can route edges into/out of its children. Mixing rectpacking
|
|
256
|
+
// with layered hierarchy edges raises UnsupportedGraphException.
|
|
257
|
+
//
|
|
258
|
+
// Otherwise (truly isolated leaf cluster) pack sub-modules into a
|
|
259
|
+
// roughly square grid so a 10-sub-module feature does not become a
|
|
260
|
+
// tall column that wastes the rest of the viewport.
|
|
261
|
+
const hasInternalEdges = Array.isArray(feature.edges) && feature.edges.length > 0;
|
|
262
|
+
const common = {
|
|
263
|
+
'elk.padding': `[top=${CLUSTER_PAD_TOP},left=${CLUSTER_PAD_SIDE},bottom=${CLUSTER_PAD_BOTTOM},right=${CLUSTER_PAD_SIDE}]`,
|
|
264
|
+
'elk.spacing.nodeNode': '16',
|
|
265
|
+
'elk.nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]',
|
|
266
|
+
};
|
|
267
|
+
if (hasInternalEdges || isCrossEdgeEndpoint) {
|
|
268
|
+
return {
|
|
269
|
+
...common,
|
|
270
|
+
'elk.algorithm': 'layered',
|
|
271
|
+
'elk.direction': 'DOWN',
|
|
272
|
+
'elk.layered.spacing.nodeNodeBetweenLayers': '28',
|
|
273
|
+
'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
...common,
|
|
278
|
+
'elk.algorithm': 'rectpacking',
|
|
279
|
+
'elk.aspectRatio': '1.4',
|
|
280
|
+
'elk.rectpacking.optimizationGoal': 'MAX_SCALE_DRIVEN',
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function collectCrossEdgeFeatures(state) {
|
|
285
|
+
const set = new Set();
|
|
286
|
+
function note(endpoint) {
|
|
287
|
+
if (endpoint && typeof endpoint === 'object' && endpoint.feature) set.add(endpoint.feature);
|
|
288
|
+
}
|
|
289
|
+
for (const edge of state.edges || []) {
|
|
290
|
+
note(edge.from);
|
|
291
|
+
note(edge.to);
|
|
292
|
+
}
|
|
293
|
+
return set;
|
|
294
|
+
}
|
|
295
|
+
|
|
132
296
|
function buildGraph(state) {
|
|
297
|
+
const crossEndpoints = collectCrossEdgeFeatures(state);
|
|
133
298
|
const children = (state.features || []).map((feature) => ({
|
|
134
299
|
id: `feature::${feature.slug}`,
|
|
135
300
|
labels: [{
|
|
@@ -138,14 +303,7 @@ function buildGraph(state) {
|
|
|
138
303
|
width: estimateLabelWidth(feature.title || feature.slug),
|
|
139
304
|
height: 24,
|
|
140
305
|
}],
|
|
141
|
-
layoutOptions:
|
|
142
|
-
'elk.padding': `[top=${CLUSTER_PAD_TOP},left=${CLUSTER_PAD_SIDE},bottom=${CLUSTER_PAD_BOTTOM},right=${CLUSTER_PAD_SIDE}]`,
|
|
143
|
-
'elk.spacing.nodeNode': '24',
|
|
144
|
-
'elk.algorithm': 'layered',
|
|
145
|
-
'elk.direction': 'DOWN',
|
|
146
|
-
'elk.layered.spacing.nodeNodeBetweenLayers': '36',
|
|
147
|
-
'elk.nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]',
|
|
148
|
-
},
|
|
306
|
+
layoutOptions: clusterLayoutOptions(feature, crossEndpoints.has(feature.slug)),
|
|
149
307
|
children: (feature.submodules || []).map((sub) => {
|
|
150
308
|
const box = measureSubmodule(sub);
|
|
151
309
|
return {
|
|
@@ -168,17 +326,18 @@ function buildGraph(state) {
|
|
|
168
326
|
|
|
169
327
|
function pushEdge(list, raw, sourceId, targetId) {
|
|
170
328
|
if (!sourceId || !targetId) return;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
labels
|
|
176
|
-
id: `${
|
|
177
|
-
text:
|
|
178
|
-
width:
|
|
179
|
-
height:
|
|
180
|
-
}]
|
|
181
|
-
}
|
|
329
|
+
const id = raw.id || `e-${nextEdgeId++}`;
|
|
330
|
+
let labels = [];
|
|
331
|
+
if (raw.label) {
|
|
332
|
+
const m = measureEdgeLabel(raw.label);
|
|
333
|
+
labels = [{
|
|
334
|
+
id: `${id}::label`,
|
|
335
|
+
text: m.text,
|
|
336
|
+
width: m.width,
|
|
337
|
+
height: m.height,
|
|
338
|
+
}];
|
|
339
|
+
}
|
|
340
|
+
list.push({ id, sources: [sourceId], targets: [targetId], labels });
|
|
182
341
|
}
|
|
183
342
|
|
|
184
343
|
for (const feature of state.features || []) {
|
|
@@ -203,12 +362,20 @@ function buildGraph(state) {
|
|
|
203
362
|
'elk.algorithm': 'layered',
|
|
204
363
|
'elk.direction': 'RIGHT',
|
|
205
364
|
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
'elk.
|
|
365
|
+
// 16:9 hint so elk stops sprawling along one axis and leaving
|
|
366
|
+
// the other half of the viewport empty.
|
|
367
|
+
'elk.aspectRatio': '1.778',
|
|
368
|
+
'elk.spacing.nodeNode': '32',
|
|
369
|
+
'elk.layered.spacing.nodeNodeBetweenLayers': '60',
|
|
370
|
+
'elk.padding': '[top=20,left=20,bottom=20,right=20]',
|
|
209
371
|
'elk.edgeRouting': 'ORTHOGONAL',
|
|
210
372
|
'elk.edgeLabels.inline': 'false',
|
|
211
373
|
'elk.edgeLabels.placement': 'CENTER',
|
|
374
|
+
// Tighter post-layout placement: BALANCED keeps related nodes
|
|
375
|
+
// adjacent, EDGE_LENGTH compaction pulls disconnected
|
|
376
|
+
// sub-graphs in toward each other so unused columns collapse.
|
|
377
|
+
'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',
|
|
378
|
+
'elk.layered.compaction.postCompaction.strategy': 'EDGE_LENGTH',
|
|
212
379
|
},
|
|
213
380
|
children,
|
|
214
381
|
edges: rootEdges,
|
|
@@ -327,4 +494,7 @@ module.exports = {
|
|
|
327
494
|
assertNoOverlap,
|
|
328
495
|
buildGraph,
|
|
329
496
|
measureSubmodule,
|
|
497
|
+
measureEdgeLabel,
|
|
498
|
+
approxTextWidth,
|
|
499
|
+
wrapByVisualWidth,
|
|
330
500
|
};
|
|
@@ -81,13 +81,13 @@ function edgeKindFor(stateEdge) {
|
|
|
81
81
|
function findEdgeMeta(state, edgeId) {
|
|
82
82
|
for (const feature of state.features || []) {
|
|
83
83
|
for (const e of feature.edges || []) {
|
|
84
|
-
if (e.id === edgeId) return e;
|
|
84
|
+
if (e.id === edgeId) return { edge: e, scope: 'feature' };
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
for (const e of state.edges || []) {
|
|
88
|
-
if (e.id === edgeId) return e;
|
|
88
|
+
if (e.id === edgeId) return { edge: e, scope: 'root' };
|
|
89
89
|
}
|
|
90
|
-
return null;
|
|
90
|
+
return { edge: null, scope: 'feature' };
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
function renderMacroSvg(layout, state) {
|
|
@@ -144,17 +144,29 @@ function renderMacroSvg(layout, state) {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
for (const edge of layout.edges) {
|
|
147
|
-
const meta = findEdgeMeta(state, edge.id);
|
|
147
|
+
const { edge: meta, scope } = findEdgeMeta(state, edge.id);
|
|
148
148
|
const kind = edgeKindFor(meta);
|
|
149
149
|
const d = renderEdgePath(edge);
|
|
150
150
|
if (!d) continue;
|
|
151
|
-
|
|
151
|
+
const scopeClass = scope === 'root' ? ' m-edge--cross' : '';
|
|
152
|
+
parts.push(` <g class="m-edge m-edge--${kind}${scopeClass}" data-edge="${htmlEscape(edge.id)}">`);
|
|
152
153
|
parts.push(` <path d="${d}" fill="none" marker-end="url(#arrow-${kind})" />`);
|
|
153
154
|
for (const label of edge.labels || []) {
|
|
154
155
|
if (!label.text) continue;
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
156
|
+
const lines = String(label.text).split('\n');
|
|
157
|
+
const cx = label.x + (label.width || 0) / 2;
|
|
158
|
+
const lineH = 14; // matches EDGE_LABEL_LINE_PX in layout.js
|
|
159
|
+
const blockH = lines.length * lineH;
|
|
160
|
+
const firstBaseline = label.y + ((label.height || 0) - blockH) / 2 + (lineH - 3);
|
|
161
|
+
parts.push(` <text class="m-edge__label" x="${cx.toFixed(2)}" y="${firstBaseline.toFixed(2)}" text-anchor="middle">`);
|
|
162
|
+
lines.forEach((line, idx) => {
|
|
163
|
+
if (idx === 0) {
|
|
164
|
+
parts.push(` <tspan x="${cx.toFixed(2)}">${htmlEscape(line)}</tspan>`);
|
|
165
|
+
} else {
|
|
166
|
+
parts.push(` <tspan x="${cx.toFixed(2)}" dy="${lineH}">${htmlEscape(line)}</tspan>`);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
parts.push(' </text>');
|
|
158
170
|
}
|
|
159
171
|
parts.push(' </g>');
|
|
160
172
|
}
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -10,7 +10,7 @@ This skill:
|
|
|
10
10
|
2. Rejects authorship bias, including confidence in code written earlier in the same conversation.
|
|
11
11
|
3. Looks for architecture-level abstraction opportunities.
|
|
12
12
|
4. Looks for code that can be simplified without changing behavior.
|
|
13
|
-
5.
|
|
13
|
+
5. For multi-file or multi-module diffs, dispatches one read-only subagent per coherent scope cluster and aggregates structured findings on the main agent.
|
|
14
14
|
|
|
15
15
|
## When to use
|
|
16
16
|
|
|
@@ -27,7 +27,7 @@ Use this skill when the task asks you to:
|
|
|
27
27
|
- Treat recent edits as untrusted until evidence proves otherwise.
|
|
28
28
|
- Prefer fewer, stronger findings over broad speculative advice.
|
|
29
29
|
- Focus on architecture and simplification, not cosmetic style feedback.
|
|
30
|
-
-
|
|
30
|
+
- For wide diffs, prefer parallel read-only subagents over loading every file into one context.
|
|
31
31
|
|
|
32
32
|
## Example
|
|
33
33
|
|
|
@@ -44,7 +44,7 @@ Expected behavior:
|
|
|
44
44
|
- changed files are read before conclusions,
|
|
45
45
|
- findings cite exact evidence,
|
|
46
46
|
- architecture issues are prioritized over style comments,
|
|
47
|
-
-
|
|
47
|
+
- multi-module diffs are reviewed by parallel read-only subagents and aggregated into one report.
|
|
48
48
|
|
|
49
49
|
## References
|
|
50
50
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review-change-set
|
|
3
3
|
description: >-
|
|
4
|
-
Unbiased **git diff** review: architecture (boundaries, duplication, ownership) then simplification (real deletes/flattening, not churn)—discard conversation bias.
|
|
4
|
+
Unbiased **git diff** review: architecture (boundaries, duplication, ownership) then simplification (real deletes/flattening, not churn)—discard conversation bias. For diffs spanning multiple files/modules, **prefer dispatching one read-only subagent per scope cluster** (each owns its files end-to-end), then aggregate confirmed findings on the main agent without re-reading delegated files.
|
|
5
5
|
Use for pre-commit/pre-PR review, refactor/abstraction second opinion, “review my branch” **STOP** greenfield feature design from scratch—use planning skills… BAD style-only nits… GOOD evidence + named abstraction target…
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -10,9 +10,9 @@ description: >-
|
|
|
10
10
|
## Dependencies
|
|
11
11
|
|
|
12
12
|
- Required: none.
|
|
13
|
-
- Conditional:
|
|
13
|
+
- Conditional: none.
|
|
14
14
|
- Optional: none.
|
|
15
|
-
- Fallback: If
|
|
15
|
+
- Fallback: If a downstream consumer (e.g. `commit-and-push`) needs additional safety checks (security, edge cases), invoke those skills explicitly there — this skill no longer chains them automatically.
|
|
16
16
|
|
|
17
17
|
## Non-negotiables
|
|
18
18
|
|
|
@@ -21,14 +21,15 @@ description: >-
|
|
|
21
21
|
- Prefer **architecture** and **maintainability** over style-only.
|
|
22
22
|
- Abstraction only when it cuts duplication, clarifies ownership, or stabilizes boundaries.
|
|
23
23
|
- Simplification only when behavior-preserving and genuinely simpler—**MUST NOT** shuffle complexity.
|
|
24
|
-
- **
|
|
24
|
+
- For non-trivial diffs (multiple files, multiple modules, or large per-file changes), **SHOULD** dispatch **read-only subagents** — one per coherent scope cluster (e.g. one feature/package, one layer, or one logical concern). Each subagent reads its assigned files end-to-end and returns ONLY structured findings (architecture + simplification with `path:line` evidence). The main agent **MUST NOT** re-read delegated files; it aggregates confirmed findings, deduplicates cross-cluster overlaps, and writes the final report. Tiny one-file diffs may be reviewed inline without subagents.
|
|
25
|
+
- **MUST NOT** fabricate findings the diff does not actually contain; subagent reports stay confined to architecture and simplification.
|
|
25
26
|
|
|
26
27
|
## Standards (summary)
|
|
27
28
|
|
|
28
|
-
- **Evidence**: Full diff + minimum context reads to understand behavior.
|
|
29
|
-
- **Execution**: Git state → baseline → architecture → simplification →
|
|
30
|
-
- **Quality**: Actionable, outsider perspective;
|
|
31
|
-
- **Output**: Scope, architecture findings, simplification findings,
|
|
29
|
+
- **Evidence**: Full diff + minimum context reads to understand behavior; subagent reports cite `path:line` per finding.
|
|
30
|
+
- **Execution**: Git state → baseline → (subagent fan-out for multi-cluster diffs OR inline read for tiny diffs) → architecture → simplification → aggregate → report.
|
|
31
|
+
- **Quality**: Actionable, outsider perspective; subagent fan-out keeps each context window small; no duplicated findings across clusters.
|
|
32
|
+
- **Output**: Scope, architecture findings, simplification findings, residual uncertainty.
|
|
32
33
|
|
|
33
34
|
## Workflow
|
|
34
35
|
|
|
@@ -40,45 +41,56 @@ description: >-
|
|
|
40
41
|
- No diff → `No active git change set to review` and stop.
|
|
41
42
|
- **Pause →** Am I about to review **only** unstaged while staged also ships?
|
|
42
43
|
|
|
43
|
-
### 2)
|
|
44
|
+
### 2) Plan the read pattern
|
|
44
45
|
|
|
45
|
-
-
|
|
46
|
+
- **Tiny diff** (one file or a handful of small hunks in one module) → read inline; skip subagents.
|
|
47
|
+
- **Multi-file or multi-module diff** → cluster the changed files into coherent scopes (one feature/package, one layer, one logical concern). Dispatch **one read-only subagent per cluster**. Hand each subagent: the cluster file list, its slice of `git diff`/`git diff --cached`, and the structured-report contract below. The main agent **MUST NOT** read the delegated files itself.
|
|
48
|
+
|
|
49
|
+
> **Cluster `<scope>` subagent contract**
|
|
50
|
+
> - Read every file in this cluster E2E plus the minimum callers/callees/config needed to interpret behavior.
|
|
51
|
+
> - Discard authorship bias; behavior comes from code/tests/config, not chat memory.
|
|
52
|
+
> - Return ONLY a structured findings block:
|
|
53
|
+
> - `Architecture`: list of `{ title, evidence (path:line), abstraction target, why current shape is weaker }`.
|
|
54
|
+
> - `Simplification`: list of `{ title, evidence (path:line), candidate change, behavior-preserving benefit }`.
|
|
55
|
+
> - `Outbound concerns`: any boundary issue that touches another cluster (so the orchestrator can deduplicate).
|
|
56
|
+
> - No source dumps, no opinions about tasks outside this cluster, no security/edge-case fabrication.
|
|
57
|
+
|
|
58
|
+
- **Pause →** Did I cluster correctly so that one subagent owns each coherent boundary, or am I about to split a duplicated helper across two subagents and miss the dedup signal?
|
|
59
|
+
|
|
60
|
+
### 3) Baseline (inline path) or aggregate (subagent path)
|
|
61
|
+
|
|
62
|
+
- Inline: read every changed file E2E; pull in minimal callers/callees/config to interpret moves and interfaces.
|
|
63
|
+
- Subagent: wait for **every** cluster subagent to return. Aggregate their findings, then deduplicate any architecture finding two clusters reported via their `Outbound concerns` block.
|
|
46
64
|
- Behavior from **code, tests, config, execution**—not from chat memory.
|
|
47
65
|
- **Pause →** Can I quote **one concrete behavior** change this diff introduces—not intent?
|
|
48
66
|
|
|
49
|
-
###
|
|
67
|
+
### 4) Architecture first
|
|
50
68
|
|
|
51
69
|
Flag only if evidence-backed: duplicated workflows, cross-layer leakage, wrong helper ownership, repeated condition trees, unstable interfaces.
|
|
52
70
|
Each finding **MUST** name abstraction target **and** why current shape is weaker.
|
|
53
71
|
- **Pause →** Is this “different style” or a real **boundary** problem?
|
|
54
72
|
|
|
55
|
-
###
|
|
73
|
+
### 5) Simplification second
|
|
56
74
|
|
|
57
75
|
Redundant branches/wrappers, deep nesting, duplicated validation, oversize functions, dead compat—**only** if it truly reduces complexity.
|
|
58
76
|
- **Pause →** Would this refactor just **move** lines between files?
|
|
59
77
|
|
|
60
|
-
### 5) Security cross-check
|
|
61
|
-
|
|
62
|
-
- Run **`discover-security-issues`** on the **same** code-affecting scope.
|
|
63
|
-
- Merge **confirmed** findings that affect safety of this structure; omit unconfirmed noise.
|
|
64
|
-
- **Pause →** Did I cite **their** severity + repro—or paraphrase fear?
|
|
65
|
-
|
|
66
78
|
### 6) Report
|
|
67
79
|
|
|
68
|
-
1. **Scope** — staged/unstaged; extra context paths read.
|
|
80
|
+
1. **Scope** — staged/unstaged; extra context paths read; cluster list when subagents were used.
|
|
69
81
|
2. **Architecture** — title, evidence (`path:line`), candidate, why weaker.
|
|
70
82
|
3. **Simplification** — title, evidence, candidate, benefit.
|
|
71
|
-
4. **
|
|
72
|
-
5. **Residual uncertainty** — hypotheses / follow-up checks.
|
|
83
|
+
4. **Residual uncertainty** — hypotheses / follow-up checks.
|
|
73
84
|
|
|
74
|
-
If nothing actionable: `No actionable abstraction or simplification finding identified
|
|
85
|
+
If nothing actionable: `No actionable abstraction or simplification finding identified`.
|
|
75
86
|
|
|
76
87
|
## Sample hints
|
|
77
88
|
|
|
78
89
|
- **Staged only**: User ran `git add -p` → findings tagged **staged** vs **unstaged** separately.
|
|
79
90
|
- **Rename-heavy**: Read old→new path mapping before calling “duplication.”
|
|
80
|
-
- **Tiny diff**: One-file guard clause → architecture section may be empty;
|
|
91
|
+
- **Tiny diff**: One-file guard clause → architecture section may be empty; reviewed inline without subagents.
|
|
92
|
+
- **Wide refactor across packages**: cluster by package; one read-only subagent per package; dedupe duplicated-helper findings on the main agent.
|
|
81
93
|
|
|
82
94
|
## References
|
|
83
95
|
|
|
84
|
-
-
|
|
96
|
+
- Downstream consumers (e.g. `commit-and-push`, `version-release`, `review-spec-related-changes`) decide independently when to add security or edge-case passes; this skill no longer wires them.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Review Change Set"
|
|
3
|
-
short_description: "Independent diff review for architecture
|
|
4
|
-
default_prompt: "Use $review-change-set to read the active git change set end-to-end, discard any bias toward code written earlier in the conversation, review it like an independent reviewer for architecture-level abstraction and simplification opportunities,
|
|
3
|
+
short_description: "Independent diff review for architecture and simplification opportunities"
|
|
4
|
+
default_prompt: "Use $review-change-set to read the active git change set end-to-end, discard any bias toward code written earlier in the conversation, and review it like an independent reviewer for architecture-level abstraction and simplification opportunities. For multi-file or multi-module diffs, prefer dispatching one read-only subagent per coherent scope cluster (each owns its files end-to-end and returns structured architecture + simplification findings with path:line evidence); the main agent aggregates and deduplicates without re-reading delegated files."
|
|
@@ -9,7 +9,7 @@ This skill:
|
|
|
9
9
|
1. Resolves the governing `docs/plans/...` spec scope from user input or recent repository changes.
|
|
10
10
|
2. Checks whether each business goal and acceptance criterion is actually implemented.
|
|
11
11
|
3. Treats unmet business goals as the most severe review findings.
|
|
12
|
-
4. Runs secondary code-practice review through `review-change-set`, `discover-edge-cases`, and `discover-security-issues` for code-affecting scopes.
|
|
12
|
+
4. Runs secondary code-practice review through `review-change-set`, `discover-edge-cases`, and `discover-security-issues` for code-affecting scopes — preferably as parallel read-only subagents (one per skill) that report back to the main agent.
|
|
13
13
|
5. Reports business-goal gaps separately from edge-case, security, and maintainability findings.
|
|
14
14
|
|
|
15
15
|
## When to use
|
|
@@ -27,6 +27,7 @@ Use this skill when the task asks you to:
|
|
|
27
27
|
- Missing required behavior is more severe than ordinary code-practice issues.
|
|
28
28
|
- Secondary edge-case, security, and code-review findings remain clearly separated.
|
|
29
29
|
- Findings must cite concrete spec and code evidence.
|
|
30
|
+
- For multi-skill reviews, prefer parallel read-only subagents (one per secondary skill) over chaining the skills sequentially on the main agent.
|
|
30
31
|
|
|
31
32
|
## Example
|
|
32
33
|
|
|
@@ -41,7 +42,7 @@ Expected behavior:
|
|
|
41
42
|
|
|
42
43
|
- the named spec set is read before judging the code,
|
|
43
44
|
- business-goal gaps are listed first and treated as highest severity,
|
|
44
|
-
- secondary review skills are invoked for the same implementation scope,
|
|
45
|
+
- secondary review skills are invoked for the same implementation scope, preferably as one read-only subagent per skill running in parallel,
|
|
45
46
|
- the final report separates spec-compliance findings from edge-case, security, and code-review findings.
|
|
46
47
|
|
|
47
48
|
## References
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review-spec-related-changes
|
|
3
3
|
description: >-
|
|
4
|
-
Read-only spec compliance
|
|
5
|
-
Use for
|
|
6
|
-
Do not mutate
|
|
4
|
+
Read-only spec compliance vs governing docs/plans: score every business requirement Met/Partial/Not-met from code/tests/commands—checked `tasks.md` boxes never count; ambiguity between two plan roots halts execution; on code-bearing diffs run **`review-change-set`**, **`discover-edge-cases`**, **`discover-security-issues`** on the same scope afterward — **prefer one read-only subagent per secondary skill in parallel** so the main agent aggregates without re-reading. Independent requirement clusters may also be scored by parallel read-only subagents.
|
|
5
|
+
Use for “does this PR satisfy coordination.md + spec.md R2?” or a user-pinned `{change}` folder.
|
|
6
|
+
Do not mutate repos, bury missing goals, skip the tertiary bundle on code-bearing diffs, or rest on intent without evidence; FORBIDDEN to lead with refactor comments while R1 is failing. GOOD: pair every Not-met cite with a `spec.md` ref + concrete path:test gap.
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Review Spec Related Changes
|
|
@@ -23,14 +23,17 @@ description: >-
|
|
|
23
23
|
- **MUST** classify each business goal / acceptance item as `Met`, `Partially met`, `Not met`, or `Deferred/N/A` **only** using verifiable evidence (code, tests, commands, traces)—checked boxes in `tasks.md` are **not** proof by themselves.
|
|
24
24
|
- **MUST** treat **unmet or partially met required business goals** as **highest severity**. **MUST NOT** let edge-case, security, or style findings **outrank** those gaps in the reported order or implied priority.
|
|
25
25
|
- **MUST** finish the business-goal verdict **before** invoking secondary skills; **MUST** still run `review-change-set`, `discover-edge-cases`, and `discover-security-issues` on the **same** implementation scope when code is involved (after step 1 verdict is written).
|
|
26
|
+
- **SHOULD** parallelize the secondary reviews when code is involved by dispatching **one read-only subagent per secondary skill** (one for `review-change-set`, one for `discover-edge-cases`, one for `discover-security-issues`). Each subagent receives the same diff scope, follows that skill’s own SKILL.md, and returns ONLY its structured findings; the main agent aggregates them in the fixed report order without re-running the underlying analysis. Single-file or trivial diffs may be reviewed inline without subagents.
|
|
27
|
+
- For business-goal scoring itself, **MAY** parallelize by dispatching one read-only subagent per **independent requirement cluster** (requirements that share no owned paths and no shared spec section), each returning Met/Partial/Not-met with cited evidence. The main agent owns final ordering, severity, and any cross-requirement reconciliation. Tightly coupled requirements stay on the main agent.
|
|
26
28
|
- **MUST NOT** rest conclusions on author intent, branch names, or chat memory unless **repository evidence** agrees.
|
|
29
|
+
- **MUST NOT** let subagents mutate repositories, archive specs, or commit — every dispatched subagent runs in **read-only** mode.
|
|
27
30
|
- Prefer **fewer confirmed findings** over broad speculation; unproven items belong under **Residual uncertainty**, not as faux defects.
|
|
28
31
|
|
|
29
32
|
## Standards (summary)
|
|
30
33
|
|
|
31
34
|
- **Evidence**: Full read of governing docs + minimal code/diff context + spec-named verification commands when safe to run.
|
|
32
|
-
- **Execution**: Scope resolution → business compliance →
|
|
33
|
-
- **Quality**: Business-first severity; secondary findings separated unless they also block an acceptance criterion.
|
|
35
|
+
- **Execution**: Scope resolution → business compliance (optionally fanned out by independent requirement cluster) → parallel secondary reviews via per-skill read-only subagents → aggregated ordered report.
|
|
36
|
+
- **Quality**: Business-first severity; secondary findings separated unless they also block an acceptance criterion; subagent reports stay strictly within their assigned skill’s scope.
|
|
34
37
|
- **Output**: Ordered list: business gaps → edge cases → security → code review → passing summary → residual uncertainty.
|
|
35
38
|
|
|
36
39
|
## Scope resolution
|
|
@@ -53,17 +56,19 @@ description: >-
|
|
|
53
56
|
- **Pause →** Which items are **mandatory** acceptance vs explicitly **out of scope** or deferred?
|
|
54
57
|
- **Pause →** What observable failure would make me change a `Met` to `Not met` for the top risk requirement?
|
|
55
58
|
|
|
56
|
-
2. **Implementation evidence** — Read the relevant diff/staged/commits/files. Trace the minimum code path to validate claims. Run spec-named checks when available and safe.
|
|
59
|
+
2. **Implementation evidence** — Read the relevant diff/staged/commits/files. Trace the minimum code path to validate claims. Run spec-named checks when available and safe. When the spec contains **independent requirement clusters** (disjoint owned paths, disjoint spec sections), **MAY** dispatch one read-only subagent per cluster to score Met/Partial/Not-met with cited evidence; the main agent reconciles cross-requirement effects and owns the final verdict ordering. Tightly coupled requirements stay on the main agent.
|
|
57
60
|
- **Pause →** What is the **smallest** code path I have not yet read that could still falsify a `Met`?
|
|
58
61
|
- **Pause →** Am I about to score `Met` from **intent** or from **tests/commands** I actually ran or inspected?
|
|
62
|
+
- **Pause →** If I clustered, is every cluster genuinely disjoint, or am I about to lose a cross-requirement contradiction by running them in isolation?
|
|
59
63
|
|
|
60
64
|
3. **Business-goal verdict first** — Emit every `Not met` / `Partially met` **before** secondary findings, with **exact** spec cites and code/test evidence. While required goals stay failed, **MUST NOT** frame archival, release, or “done” narratives that imply compliance.
|
|
61
65
|
- **Pause →** If I sorted findings by “interesting” instead of business impact, which line would unfairly rise above a missing goal?
|
|
62
66
|
- **Pause →** For each `Partially met`, what single **missing proof** (test, wire-up, error path) am I naming explicitly?
|
|
63
67
|
|
|
64
|
-
4. **Secondary reviews (code-affecting)** — On the same scope: `review-change-set` (architecture/simplification), `discover-edge-cases` (reproducible edge/observability risks), `discover-security-issues` (reproducible security).
|
|
68
|
+
4. **Secondary reviews (code-affecting)** — On the same scope: `review-change-set` (architecture/simplification), `discover-edge-cases` (reproducible edge/observability risks), `discover-security-issues` (reproducible security). **Prefer dispatching one read-only subagent per skill in parallel** so each runs in its own context with the full SKILL.md it owns; hand each subagent the same diff scope and the structured-report contract from that skill. The main agent waits for every subagent to return, then keeps outputs labeled so they do not read as business-goal substitutions. Trivial single-file diffs may run inline without subagents. The main agent **MUST NOT** re-run a secondary skill it already delegated, and subagents **MUST NOT** mutate the repository.
|
|
65
69
|
- **Pause →** Does this secondary finding **force** a business re-score—if yes, did I revise step 3 before publishing?
|
|
66
70
|
- **Pause →** Is the diff scope identical to what I used for business mapping (no silent file creep)?
|
|
71
|
+
- **Pause →** Did every dispatched secondary subagent return — or am I about to publish from partial summaries?
|
|
67
72
|
|
|
68
73
|
5. **Final report (fixed order)** — (1) Business-goal failures (always top severity for required gaps). (2) Edge-case. (3) Security. (4) Code-review / maintainability. (5) Passing evidence for goals confirmed `Met`. (6) Residual uncertainty (skipped commands, unmapped spec text, unverifiable externals). If nothing actionable: state that explicitly **and** still cite docs and evidence reviewed.
|
|
69
74
|
- **Pause →** What commands or spec paragraphs remain **unverified**—are they all listed under residual uncertainty?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Review Spec Related Changes"
|
|
3
3
|
short_description: "Review spec-backed changes for business-goal completion and secondary code-practice risks"
|
|
4
|
-
default_prompt: "Use $review-spec-related-changes to resolve the recent or user-specified spec documents, verify each business goal and acceptance criterion against the related implementation evidence, treat unmet business goals as the most severe findings,
|
|
4
|
+
default_prompt: "Use $review-spec-related-changes to resolve the recent or user-specified spec documents, verify each business goal and acceptance criterion against the related implementation evidence, and treat unmet business goals as the most severe findings. When code is involved, prefer dispatching one read-only subagent per secondary skill in parallel — one for $review-change-set, one for $discover-edge-cases, one for $discover-security-issues — each running against the same diff scope and returning structured findings; the main agent waits for all secondary subagents, then aggregates them into the fixed report order without re-running any of those skills. Independent requirement clusters with disjoint owned paths may also be scored by parallel read-only business-goal subagents; tightly coupled requirements stay on the main agent. Subagents always run in read-only mode."
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# update-project-html
|
|
2
|
+
|
|
3
|
+
`update-project-html` refreshes the project HTML architecture atlas (`resources/project-architecture/`) so it reflects the latest code changes.
|
|
4
|
+
|
|
5
|
+
## What this skill does
|
|
6
|
+
|
|
7
|
+
1. Reads the current atlas (`atlas.index.yaml` + per-feature YAML).
|
|
8
|
+
2. Resolves the diff scope (`git diff --stat` + `git diff --cached --stat` by default, or `git diff --stat <base>..HEAD` when the user names a ref).
|
|
9
|
+
3. Filters to code-affecting hunks and maps each changed file to an existing or new feature.
|
|
10
|
+
4. Dispatches one write-capable subagent per affected feature to deep-read only its own changed files and apply every intra-feature mutation through `apltk architecture` (no `--spec`).
|
|
11
|
+
5. Waits until every subagent finishes, then declares cross-feature edges, runs `apltk architecture render`, and validates.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
Use this skill when the task asks you to:
|
|
16
|
+
|
|
17
|
+
- update or refresh the existing project architecture diagram after code changes,
|
|
18
|
+
- bring `resources/project-architecture/` back in sync with the current branch or a specific commit range,
|
|
19
|
+
- reflect a recent PR or batch of commits in the canonical atlas before merging or releasing.
|
|
20
|
+
|
|
21
|
+
If no atlas exists yet, use `init-project-html` to bootstrap one. For planned but unshipped work scoped to a `docs/plans/...` spec, use `spec-to-project-html` to write under `<spec_dir>/architecture_diff/` instead of the base atlas.
|
|
22
|
+
|
|
23
|
+
## Core principles
|
|
24
|
+
|
|
25
|
+
- The CLI owns atlas state and renderer output; agents never hand-edit `resources/project-architecture/**/*.html`.
|
|
26
|
+
- Every mutation traces to a specific file + diff hunk; absent code never produces atlas entries.
|
|
27
|
+
- Subagent fan-out is the only safe read pattern: one feature per subagent, no shared source loading.
|
|
28
|
+
- Cross-feature wiring happens **after** every subagent finishes — never from partial summaries.
|
|
29
|
+
|
|
30
|
+
## References
|
|
31
|
+
|
|
32
|
+
- [`SKILL.md`](./SKILL.md) — full workflow and execution rules.
|
|
33
|
+
- [`../init-project-html/SKILL.md`](../init-project-html/SKILL.md) — semantic rulebook.
|
|
34
|
+
- [`../spec-to-project-html/SKILL.md`](../spec-to-project-html/SKILL.md) — spec overlay flow.
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
MIT
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update-project-html
|
|
3
|
+
description: >-
|
|
4
|
+
Refresh the base project HTML architecture atlas to reflect the latest code changes: read the existing atlas, resolve diff scope (`git diff --stat` + staged by default, or `git diff --stat <base>..HEAD` when a ref is named), filter to code-affecting hunks, and update affected feature/sub-module declarations through `apltk architecture` (no `--spec` — base atlas, not spec overlays). **Subagents only:** dispatch ONE write-capable subagent per affected feature; each deep-reads only its own changed files, applies every intra-feature delta (function/variable/dataflow/error/intra-feature edge add|set|remove|reorder), and returns ONLY (i) sub-module change summary and (ii) outbound boundary deltas. The main agent waits until every subagent finishes before declaring cross-feature edges, then `apltk architecture render` + `validate`. Exact CLI: `apltk architecture --help`. Anchor every change to the actual diff. For unshipped spec work use `spec-to-project-html`; first-time bootstrap use `init-project-html`.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Update Project HTML
|
|
8
|
+
|
|
9
|
+
## Dependencies
|
|
10
|
+
|
|
11
|
+
- Required: **`init-project-html`** — its `SKILL.md` is the semantic rulebook (acceptance criteria, two-layer rule, `edge.kind` enum, function/variable referencing rules); **`apltk architecture --help`** is the verb/flag source of truth.
|
|
12
|
+
- Conditional: **`spec-to-project-html`** when the user actually wants an overlay scoped to a `docs/plans/...` spec rather than the base atlas — that skill uses `--spec`.
|
|
13
|
+
- Optional: **`align-project-documents`** when feature names in the atlas no longer match the `docs/features` set after the diff.
|
|
14
|
+
- Fallback: changed code references components that are absent from the atlas → declare new sub-modules / functions / variables before referencing them; if a single feature’s diff is too large for one subagent context, split that feature’s subagent by sub-module folder. **MUST NOT** invent components for code paths that were never read.
|
|
15
|
+
|
|
16
|
+
## Non-negotiables
|
|
17
|
+
|
|
18
|
+
- **MUST** mutate atlas state only through the CLI (`apltk architecture …`). The renderer owns `resources/project-architecture/**/*.html` — agents **MUST NOT** hand-edit those files.
|
|
19
|
+
- **MUST** target the **base atlas** (no `--spec` flag). This skill is for code that has *already shipped* (or is about to be committed) and therefore belongs in the canonical diagram. For planned/unmerged work scoped to a spec, redirect to **`spec-to-project-html`**. For repos with no atlas yet, redirect to **`init-project-html`**.
|
|
20
|
+
- **MUST** decide the diff scope **before** reading any source files: working tree (`git diff --stat`) + staged (`git diff --cached --stat`) by default; an explicit ref/range when the user names one (e.g. `git diff --stat $(git merge-base HEAD origin/main)..HEAD` for a PR refresh). Print the literal command(s) you ran in the report so the run is reproducible.
|
|
21
|
+
- **MUST** filter to **code-affecting** hunks — exclude pure docs/markdown/asset edits, generated files, lockfiles, and formatting-only diffs that do not change runtime behavior. Record skipped buckets in the report so reviewers can audit the filter.
|
|
22
|
+
- **MUST** preserve the existing atlas structure for parts the diff did not touch — never delete features, sub-modules, or edges just because the current diff is silent about them. Only mutate what the diff actually changed (rename, move, remove, add, behavior change).
|
|
23
|
+
- **MUST** use the **subagent fan-out** pattern from `init-project-html` Rule 3:
|
|
24
|
+
1. Enumerate **affected features** from the filtered diff (path → feature mapping using existing atlas YAML + folder layout). No function-body deep reads at this stage.
|
|
25
|
+
2. Dispatch **one write-capable subagent per affected feature**. Each deep-reads only its own changed files (use `git diff` for exact deltas plus the post-change source for context), applies every intra-feature mutation via `apltk architecture` (`function`, `variable`, `dataflow`, `error`, intra-feature `edge` add|set|remove|reorder), and returns ONLY (i) sub-module change summary and (ii) outbound boundary deltas (cross-feature edges to add/change/remove with endpoints + suggested kind/label).
|
|
26
|
+
3. **HARD GATE:** the main agent **MUST** wait until **every** dispatched subagent has finished (success or explicit failure report) before declaring any cross-feature `edge`, shared `meta` that stitches multiple features, or `actor` that exists only for cross-feature context.
|
|
27
|
+
- **MUST** run `apltk architecture render` (when subagents batched with `--no-render`) and `apltk architecture validate` after the cross-feature wiring; resolve every reported error before reporting completion.
|
|
28
|
+
- **MUST NOT** re-read source for a delegated feature in the main agent and **MUST NOT** re-declare intra-feature components a subagent already owns.
|
|
29
|
+
- **MUST NOT** generate spec overlay artifacts (`<spec_dir>/architecture_diff/atlas/`) — that is **`spec-to-project-html`**’s job.
|
|
30
|
+
|
|
31
|
+
## Standards (summary)
|
|
32
|
+
|
|
33
|
+
- **Evidence**: every CLI mutation traces to a specific file + diff hunk; record the chosen diff scope and skipped buckets in `meta.summary` via the CLI.
|
|
34
|
+
- **Execution**: read base atlas → resolve diff scope → filter to code-affecting hunks → map paths to features → subagent fan-out → wait for all → cross-feature edges → `render` → `validate` → handover.
|
|
35
|
+
- **Quality**: macro SVG still reflects every cross-feature data-row that exists in the *new* code; sub-module declarations stay self-only; `apltk architecture validate` returns OK.
|
|
36
|
+
- **Output**: updated `resources/project-architecture/atlas/**/*.yaml` + re-rendered `resources/project-architecture/**/*.html` + a report listing affected features, mutation counts, skipped diff buckets, and the `validate` outcome.
|
|
37
|
+
|
|
38
|
+
## Acceptance criteria
|
|
39
|
+
|
|
40
|
+
The atlas update is only complete when **all** of the following hold:
|
|
41
|
+
|
|
42
|
+
1. Every code-affecting hunk in the chosen diff scope is reflected in either an intra-feature mutation (function/variable/dataflow/error/edge) or a cross-feature edge — or is explicitly listed under "no diagram impact" in the handover report with a one-line reason.
|
|
43
|
+
2. `apltk architecture validate` returns OK.
|
|
44
|
+
3. Macro acceptance criteria from `init-project-html` still hold: cross-boundary interaction expressed as `call`/`return`/`data-row`/`failure` edges (never sub-module page prose); each touched sub-module’s internal diagram has function-to-function flow plus declared variable reads/writes for non-trivial steps.
|
|
45
|
+
4. The handover report cites: chosen diff scope (literal commands), affected feature list, per-feature mutation counts, skipped diff buckets (with reasons), and confirmation that **all subagents completed before cross-feature wiring**.
|
|
46
|
+
|
|
47
|
+
## How to use `apltk architecture`
|
|
48
|
+
|
|
49
|
+
**Authoritative command tree:** run **`apltk architecture --help`** (same output as `apltk architecture help`). Same families as `init-project-html`:
|
|
50
|
+
|
|
51
|
+
- `feature` / `submodule` — structural mutations (use **`set`** for label/role updates, **`remove`** when code deleted the entry point, **`add`** when the diff introduced a new module).
|
|
52
|
+
- `function` / `variable` / `dataflow` / `error` — per-sub-module rows. Declare new symbols **before** referencing them in `dataflow`. Use the row-level `remove` (see `--help`) to delete obsolete rows the diff dropped.
|
|
53
|
+
- `edge` — intra- or cross-feature seams. Prefer stable **`--id`** when re-applying the same edge after a mutation cycle. `kind` ∈ `call` | `return` | `data-row` | `failure`.
|
|
54
|
+
- `meta` / `actor` — only when the diff actually changed the macro narrative (e.g. summary now needs to record the diff scope or new omissions).
|
|
55
|
+
- `render` (when you batched with `--no-render`) → `validate` → done.
|
|
56
|
+
|
|
57
|
+
This skill **never** uses `--spec`. If the user wants overlay diagrams for a planning doc, redirect to **`spec-to-project-html`**.
|
|
58
|
+
|
|
59
|
+
## Workflow
|
|
60
|
+
|
|
61
|
+
**Chain-of-thought:** Answer **`Pause →`** before moving on. Validator red **MUST** block "done."
|
|
62
|
+
|
|
63
|
+
### 1) Read the current atlas (no source code yet)
|
|
64
|
+
|
|
65
|
+
- Open `resources/project-architecture/index.html` to confirm the atlas exists and renders. If it does not, redirect to **`init-project-html`** — this skill is for refreshes, not bootstraps.
|
|
66
|
+
- List `resources/project-architecture/atlas/atlas.index.yaml` and the per-feature YAMLs to learn the current feature set, sub-modules, and edge ids.
|
|
67
|
+
- **Pause →** Do I actually have a base atlas to update? If not — stop and route to **`init-project-html`**.
|
|
68
|
+
|
|
69
|
+
### 2) Resolve diff scope
|
|
70
|
+
|
|
71
|
+
- Default: **uncommitted** (`git diff --stat`) + **staged** (`git diff --cached --stat`); show both. If the user pointed at a ref/range/commit, use that instead (`git diff --stat <base>..HEAD`, `git diff --stat HEAD~N`, `git show --stat <sha>`, etc.).
|
|
72
|
+
- Print the chosen diff scope as the literal command(s) you ran so the report is reproducible.
|
|
73
|
+
- **Pause →** Is this the diff the user actually meant — or am I about to refresh the atlas against the wrong baseline?
|
|
74
|
+
|
|
75
|
+
### 3) Filter to code-affecting changes
|
|
76
|
+
|
|
77
|
+
- Drop pure docs/markdown/assets/lockfiles/generated/format-only diffs. Keep source files in language directories the project actually treats as code (open the project layout if uncertain).
|
|
78
|
+
- Group remaining files into **affected features** using the per-feature YAML’s declared paths plus folder/package heuristics. Record the path → feature mapping.
|
|
79
|
+
- **Pause →** Did I drop a hunk that actually changes runtime behavior (e.g. a config file the runtime reads)? Re-include if so.
|
|
80
|
+
- **Pause →** Are there changed files I cannot map to any existing feature — do they create a new feature, or do they extend an existing one? Decide explicitly before delegating.
|
|
81
|
+
|
|
82
|
+
### 4) Subagent fan-out — workers own features; orchestrator owns cross-feature seams **after** all workers finish
|
|
83
|
+
|
|
84
|
+
Dispatch one **write-capable** subagent per affected feature. Hand each subagent: its feature slug, the list of changed files in that feature, the diff scope command(s), the existing feature-module list (so it knows other features’ slugs for outbound edges), and **`apltk architecture --help`** as the flag reference.
|
|
85
|
+
|
|
86
|
+
> **Feature `<slug>` subagent contract**
|
|
87
|
+
> - Read the existing per-feature YAML and every changed file in this feature E2E (with `git diff` for the exact delta plus the post-change source for context).
|
|
88
|
+
> - For every behavior change in this feature, apply the matching CLI mutation: structural (`feature` / `submodule`), rows (`function`, `variable`, `dataflow`, `error`), and intra-feature **`edge`** add/set/remove/reorder.
|
|
89
|
+
> - Declare new functions / variables **before** referencing them from `dataflow`.
|
|
90
|
+
> - Run **`apltk architecture validate`** before returning.
|
|
91
|
+
> - **Return ONLY**: (i) sub-module change list (slug + change kind + one-line reason) and (ii) outbound boundary deltas (cross-feature edges to add/change/remove with endpoints + suggested kind/label). No source dumps.
|
|
92
|
+
|
|
93
|
+
**Orchestrator — after every subagent has completed:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# only when meta.summary needs to record the diff scope or new omissions
|
|
97
|
+
apltk architecture meta set --summary "..." --no-render
|
|
98
|
+
# one edge mutation per cross-feature interaction reported by the subagents
|
|
99
|
+
apltk architecture edge add --from <featA>/<subA> --to <featB>/<subB> --kind call|return|data-row|failure --label "..." --no-render
|
|
100
|
+
apltk architecture edge remove --id <stable_id> --no-render
|
|
101
|
+
apltk architecture render
|
|
102
|
+
apltk architecture validate
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The main agent **MUST NOT** re-declare a subagent’s intra-feature components, and **MUST NOT** open source files for any feature it delegated.
|
|
106
|
+
- **Pause →** Did every subagent return — or am I about to wire cross-feature edges from partial summaries?
|
|
107
|
+
|
|
108
|
+
### 5) Handover report
|
|
109
|
+
|
|
110
|
+
Report: chosen diff scope (literal commands), affected features (count), per-feature mutation summary, cross-feature edge deltas (added / removed / changed), skipped diff buckets (with reasons), `validate` outcome, and the location of the rendered atlas (`resources/project-architecture/index.html`).
|
|
111
|
+
|
|
112
|
+
## Sample hints
|
|
113
|
+
|
|
114
|
+
- **Renamed function**: subagent removes the old `function` row, adds the new one, and updates every `dataflow` step that referenced it — do **not** silently leave the old row.
|
|
115
|
+
- **Deleted sub-module**: subagent uses `submodule remove` (see `--help`) and reports the outbound edges to drop; the orchestrator removes the cross-feature edges by stable `--id` after the gate.
|
|
116
|
+
- **New cross-feature data-row**: only one subagent will see the producing side and another only the consumer side — both subagents flag it as an outbound boundary; the orchestrator declares the single `data-row` edge **after** the gate.
|
|
117
|
+
- **Pure formatting diff**: skip entirely; record under "no diagram impact" in the report so future runs do not re-litigate the file.
|
|
118
|
+
- **PR refresh against `main`**: when the user asks to refresh the atlas to reflect "everything on this branch", use `git diff --stat $(git merge-base HEAD origin/main)..HEAD` and state the resolved base SHA in the report.
|
|
119
|
+
|
|
120
|
+
## References
|
|
121
|
+
|
|
122
|
+
- **`init-project-html/SKILL.md`** — semantic rulebook, two-layer rule, acceptance criteria, full subagent contract.
|
|
123
|
+
- **`init-project-html/references/TEMPLATE_SPEC.md`** — schema cheat sheet (fields/enums).
|
|
124
|
+
- **`spec-to-project-html/SKILL.md`** — overlay flow when work is still in spec form.
|
|
125
|
+
- **`apltk architecture --help`** — live CLI reference; trust this over any prose.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "update-project-html"
|
|
3
|
+
short_description: "Refresh the project HTML architecture atlas to reflect the latest code changes via `apltk architecture`"
|
|
4
|
+
default_prompt: >-
|
|
5
|
+
Use $update-project-html. Semantic rules + acceptance criteria live in $init-project-html SKILL.md; **exact verb/subverb/flag spelling MUST come from `apltk architecture --help`** — never memorize commands from prose.
|
|
6
|
+
NEVER hand-edit `resources/project-architecture/**/*.html`. State is YAML under `resources/project-architecture/atlas/`; every mutation goes through the CLI; the renderer owns layout, CSS, ARIA, pan/zoom on macro + sub-module dataflow SVGs.
|
|
7
|
+
STEP 1 — open the current atlas index + per-feature YAMLs (no source reads yet); if no atlas exists, redirect to $init-project-html. STEP 2 — resolve the diff scope explicitly: working tree + staged (`git diff --stat` + `git diff --cached --stat`) by default, or `git diff --stat <base>..HEAD` when the user names a ref. Print the chosen command(s) before delegating. STEP 3 — filter to code-affecting hunks and group them into affected features using existing per-feature YAML + folder layout; record path → feature mapping.
|
|
8
|
+
**Subagents only:** dispatch ONE write-capable subagent per AFFECTED feature; each deep-reads only its own changed files and declares EVERY intra-feature mutation (`feature`/`submodule`/`function`/`variable`/`dataflow`/`error`/intra-feature `edge` add|set|remove|reorder) via `apltk architecture` (NO `--spec` — this is the base atlas). Each returns ONLY (i) sub-module change list and (ii) outbound boundary deltas for OTHER features.
|
|
9
|
+
**HARD GATE:** main agent MUST wait until EVERY subagent finishes before declaring ANY cross-feature `edge`, shared `meta` that stitches multiple features, or `actor` that exists only for cross-feature context. Then `apltk architecture render` (if subagents used `--no-render`) and `apltk architecture validate`.
|
|
10
|
+
Sub-module pages stay self-only — cross-boundary behavior is ALWAYS `edge` with kind call|return|data-row|failure. Internal `dataflow` steps may reference a declared function plus reads/writes of declared variables on the SAME sub-module or validate fails.
|
|
11
|
+
Anchor every mutation to the actual diff; preserve existing atlas structure for parts the diff did not touch; for spec-driven overlays use $spec-to-project-html instead and for first-time bootstrap use $init-project-html. Report completion only after validate is OK; cite chosen diff scope, per-feature mutation counts, skipped diff buckets, and the location of the rendered atlas.
|
|
@@ -34,8 +34,6 @@ When the release includes code changes, `review-change-set` is still a condition
|
|
|
34
34
|
|
|
35
35
|
Apply the same rule to every other conditional gate: if its scenario is met during release classification, it becomes blocking before version bumping, tagging, or release publication.
|
|
36
36
|
|
|
37
|
-
That includes risk-driven review gates such as `discover-edge-cases` and `discover-security-issues` whenever the release surface makes them applicable.
|
|
38
|
-
|
|
39
37
|
Do not report release completion after only bumping versions or pushing a commit: the matching tag and GitHub release are part of done criteria unless the user explicitly says to skip publication.
|
|
40
38
|
|
|
41
39
|
If the user only wants commit + push, use `commit-and-push`.
|
package/version-release/SKILL.md
CHANGED
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
## Dependencies
|
|
11
11
|
|
|
12
12
|
- Required: **`commit-and-push`** (shared inspect/classify/readiness/commit/push mechanics); **`submission-readiness-check`** **before** version files, tags, or publication mutate.
|
|
13
|
-
- Conditional: **`archive-specs`** when specs/docs need alignment; **`review-change-set`**
|
|
13
|
+
- Conditional: **`archive-specs`** when specs/docs need alignment; **`review-change-set`** on **code-affecting** release scope **before** version churn—blocking while findings open.
|
|
14
14
|
- Optional: none.
|
|
15
15
|
- Fallback: Missing required skill ⇒ stop and report.
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ description: >-
|
|
|
26
26
|
- **MUST** verify **remote** has commit + tag before calling release **done**; **MUST NOT** trust UI git shortcuts.
|
|
27
27
|
- **Done** = version files + changelog section + **pushed** commit + **remote** tag + **published** GitHub release (unless user explicitly skips publication—then say so).
|
|
28
28
|
|
|
29
|
-
**Repository regression checks:** Before creating release metadata, inspect existing local and remote tags plus any existing GitHub Release for the target version so duplicates are caught early. Do not continue until you can state the current version, the intended next version, and the exact tag name that will be created. **`review-change-set` is required for code-affecting releases**—run `review-change-set` for the same release scope before continuing; treat unresolved review findings as blocking. Any conditional gate whose trigger is confirmed by this classification becomes mandatory before version bumping, tagging, or release publication. Treat every scenario-matched gate as blocking before versioning or release publication.
|
|
29
|
+
**Repository regression checks:** Before creating release metadata, inspect existing local and remote tags plus any existing GitHub Release for the target version so duplicates are caught early. Do not continue until you can state the current version, the intended next version, and the exact tag name that will be created. **`review-change-set` is required for code-affecting releases**—run `review-change-set` for the same release scope before continuing; treat unresolved review findings as blocking. Any conditional gate whose trigger is confirmed by this classification becomes mandatory before version bumping, tagging, or release publication. Treat every scenario-matched gate as blocking before versioning or release publication. Never stop after the release commit or tag alone; creating the matching GitHub release is part of done criteria unless the user explicitly says to skip release publication.
|
|
30
30
|
|
|
31
31
|
## Standards (summary)
|
|
32
32
|
|
|
@@ -58,7 +58,7 @@ description: >-
|
|
|
58
58
|
|
|
59
59
|
### 3) Gates before version churn
|
|
60
60
|
|
|
61
|
-
- Classify scope; code-affecting ⇒ `review-change-set
|
|
61
|
+
- Classify scope; code-affecting ⇒ `review-change-set`; **`submission-readiness-check`** (+ **`archive-specs`** when indicated). All blocking items closed.
|
|
62
62
|
- **Pause →** Am I versioning while `Unreleased`/readiness still wrong?
|
|
63
63
|
|
|
64
64
|
### 4) Decide version & tag
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Version Release"
|
|
3
3
|
short_description: "Prepare a versioned release with bump, changelog, tag, GitHub release, and push"
|
|
4
|
-
default_prompt: "Use $version-release only for explicit release/version/tag requests, including direct semver wording like patch/minor/major update or requests to trigger release-published automation: inspect the current repository state, read the current version plus existing tag/release state, and inspect root CHANGELOG.md Unreleased content. Treat every conditional gate whose scenario is met as blocking before any version bump, tag, or release step: if the release includes code changes, run $review-change-set; if
|
|
4
|
+
default_prompt: "Use $version-release only for explicit release/version/tag requests, including direct semver wording like patch/minor/major update or requests to trigger release-published automation: inspect the current repository state, read the current version plus existing tag/release state, and inspect root CHANGELOG.md Unreleased content. Treat every conditional gate whose scenario is met as blocking before any version bump, tag, or release step: if the release includes code changes, run $review-change-set; if completed specs should be converted or docs need normalization, ensure $archive-specs runs through $submission-readiness-check; if changelog synchronization is needed, complete it before continuing. Then run any additional required code-quality skills, hand the repository to $submission-readiness-check so completed plan archives, project docs, AGENTS.md/CLAUDE.md, and changelog readiness are settled before any version bump or tag, confirm CHANGELOG.md Unreleased is release-ready, update version files, cut the release directly from CHANGELOG.md Unreleased, create the release commit and matching tag, push commits and tags, and publish the matching GitHub release before reporting success."
|