mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-16 15:15:35 +02:00
fix(storybook): reconcile capability associations and map omissions (#16154)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - The feature map describes user capabilities and verification recipes. > - Storybook holds isolated examples of those capabilities. > - Missing catalog links can hide existing examples. > - Some stories also expose shipped capabilities absent from the map. > - This pull request adds verified source associations and three paired map entries. > - Readers can find existing examples without changing their homes or URLs. ## Linked Issues or Issue Description Refs #16052, #16049 and #16046. **What existing behavior does this improve?** Storybook capability lookup and the feature/agent access maps. **Current behavior** Seventy capabilities have no example link. Some matching stories already exist. Primary-agent preferences and company decision/fast-response services appear only under broad neighboring capabilities. **Proposed behavior** Add source-supported links across 34 suites. Keep shared foundations in place while cross-listing them. Add primary-agent, decision-model and fast-response capabilities to both upstream maps. Retain explicit simulation and partial-example limits. **Reason and benefit** The catalog distinguishes missing associations from missing examples. The upstream map describes three existing product capabilities more precisely. **Breaking changes** None to product behavior, story exports, folders, sidebar titles or URLs. A shared foundation can declare a reasoned `home: "foundations"` override while referencing related capabilities. ## What Changed - Add 55 references across 34 suites. Replace primary-agent suites' reporting-line association with their own capability. - Add three source-reviewed capabilities and their API/actor boundaries to paired maps. - Preserve the shared Foundations home when cross-listing developer design examples. Add a validation regression test. - Record which exports demonstrate each association and what remains simulated or unverified. - Regenerate the catalog and capability data. Preserve all original 223 authored suites and 2,210 story IDs. Retain the two skill-removal stories added by current master, for 2,212 authored stories in total. - Reduce empty example lookups from 70 of 171 capabilities to 59 of 174. Links do not establish complete capability coverage. ## Verification - Passed: 27 catalog/generator/map tests, catalog validation, map structural checks, token gates and skill validation. - Passed: source inventory comparison preserves all authored files, titles, meta IDs and story IDs. - Passed: repository typecheck/build and Storybook build. Final built index has 2,248 entries and preserves all previous entries, including the two skills stories added by current master. - The broad local repository test run was interrupted before completion to resolve a new master conflict. A complete local suite pass is not claimed; fresh CI passed on the reconciled branch. - Browser: Design links to preserved Foundations stories; company-service sections link settings/history/journey suites; decision SetupToHistory passed 12 interaction steps; primary-agent ReplacePrimary passed four steps. No console errors in selected checks. - Greptile: 5/5 on final commit `805a8af62abe589907e7cc6ca1b415ce1e0cc3c0`, with no findings or unresolved threads. - Final-revision CI passed all 57 checks/statuses, including all eight browser shards, server and Runner tests, typecheck and build. The unchanged Cloud-auth mocked-response race seen on a superseded revision did not recur on the final commit. No test expectations were changed. - New agent-access evidence is source-only. Live provider and agent-credential verification is not established. ## Risks - Suite-level associations can represent only selected states. Notes retain those limits and existing review classifications. - In-memory connection drafts do not prove reload persistence. Resume-failure UI does not prove successful continuation. No-op budget controls do not prove relief or resumption. - Three map capabilities document existing behavior. No permission, API, provider or production component changes. ## Model Used OpenAI Codex, GPT-6 family, with reasoning, code execution and source inspection. The exact runtime model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
aded4197e5
commit
5e8e992df2
13 files changed
+574
-211
No files matched your search
@@ -54,6 +54,10 @@ export function scanStories(root = defaultRoot) {
|
||||
});
|
||||
}
|
||||
|
||||
function storyHome(entry) {
|
||||
return entry.home ?? entry.capabilities[0]?.split("/")[0] ?? (entry.implementation === "guide" ? "overview" : "foundations");
|
||||
}
|
||||
|
||||
export function validateCatalog(root, catalog, stories) {
|
||||
const errors = [];
|
||||
const refs = capabilities(root);
|
||||
@@ -79,10 +83,12 @@ export function validateCatalog(root, catalog, stories) {
|
||||
if (!entry.purpose?.trim() || !entry.notes?.trim()) errors.push(`${label}: purpose and review notes are required`);
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(entry.reviewedAt ?? "")) errors.push(`${label}: missing review date`);
|
||||
if (!Array.isArray(entry.capabilities)) { errors.push(`${label}: missing capabilities`); continue; }
|
||||
if (entry.home !== undefined && entry.home !== "foundations") errors.push(`${label}: only shared foundations may override the capability home`);
|
||||
if (entry.home === "foundations" && !entry.exception?.trim()) errors.push(`${label}: foundation home needs an explicit reason`);
|
||||
for (const ref of entry.capabilities) if (!refs.has(ref)) errors.push(`${label}: unknown feature capability ${ref}`);
|
||||
if (!entry.capabilities.length && !entry.exception?.trim()) errors.push(`${label}: unmapped story needs an explicit reason`);
|
||||
if (entry.capabilities.length !== new Set(entry.capabilities).size) errors.push(`${label}: duplicate capability references`);
|
||||
const area = entry.capabilities[0]?.split("/")[0] ?? (entry.implementation === "guide" ? "overview" : "foundations");
|
||||
const area = storyHome(entry);
|
||||
const prefix = navigation.get(area) ?? ({ overview: "Overview", foundations: "Foundations" })[area];
|
||||
const story = byFile.get(label);
|
||||
if (!label.startsWith(`${storyRoot}/${area}/`)) errors.push(`${label}: story must live in its primary feature folder ${area}`);
|
||||
@@ -104,7 +110,8 @@ export function renderIndex(catalog, stories, index) {
|
||||
const byFile = new Map(stories.map(story => [story.file, story]));
|
||||
const groups = new Map();
|
||||
for (const entry of catalog.entries) {
|
||||
const area = entry.capabilities[0]?.split("/")[0] ?? "foundations-and-guides";
|
||||
const home = storyHome(entry);
|
||||
const area = ["foundations", "overview"].includes(home) ? "foundations-and-guides" : home;
|
||||
if (!groups.has(area)) groups.set(area, []);
|
||||
groups.get(area).push(entry);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,31 @@ test("feature organization rejects wrong folders, sidebar homes and unstable met
|
||||
assert.match(validateCatalog(f.root, f.catalog, f.stories).join("\n"), /sidebar title/);
|
||||
});
|
||||
|
||||
test("shared foundations cross-list capabilities without moving their canonical home or IDs", t => {
|
||||
const f = fixture(t);
|
||||
const entry = f.catalog.entries[0];
|
||||
const file = "ui/storybook/stories/foundations/task.stories.tsx";
|
||||
f.write(file, "// shared control example\n");
|
||||
entry.file = file;
|
||||
entry.home = "foundations";
|
||||
entry.exception = "Shared control with related product examples.";
|
||||
entry.sidebarTitle = "Foundations/Task";
|
||||
entry.sources = [file, "ui/src/Task.tsx"];
|
||||
entry.fingerprint = fingerprint(f.root, entry.sources);
|
||||
f.stories[0] = { ...f.stories[0], file, title: entry.sidebarTitle };
|
||||
assert.deepEqual(validateCatalog(f.root, f.catalog, f.stories), []);
|
||||
const index = renderIndex(f.catalog, f.stories, featureIndex(f.root));
|
||||
assert.match(index, /### Tasks[\s\S]*?No primary story suite/);
|
||||
assert.match(index, /### Shared foundations and guides[\s\S]*?\[Foundations\/Task\]/);
|
||||
assert.match(index, /`tasks\/create`: \[Foundations\/Task\]/);
|
||||
assert.deepEqual(f.stories[0].ids, ["tasks-create--empty"]);
|
||||
entry.home = "tasks";
|
||||
assert.match(validateCatalog(f.root, f.catalog, f.stories).join("\n"), /only shared foundations/);
|
||||
entry.home = "foundations";
|
||||
delete entry.exception;
|
||||
assert.match(validateCatalog(f.root, f.catalog, f.stories).join("\n"), /foundation home needs an explicit reason/);
|
||||
});
|
||||
|
||||
test("production and shared fixture drift invalidate review fingerprints", t => {
|
||||
const f = fixture(t);
|
||||
f.write("ui/src/Task.tsx", "// changed contract\n");
|
||||
|
||||
Reference in new issue
Block a user