feat(steps): one reply box per outcome
A reply's identity is its status, not its call: a handler answering 200 or 401 draws two boxes (id per function, response, status), so each line from the handler carries its own condition on the picture — the Screens view's idiom — and the anchor's Leads-to list reads as the contract; replies whose status the code does not spell out share one box labelled by the call. Panel note, spec §3.13, CHANGELOG, plan; servers test asserts the ASP.NET and Spring outcomes per box. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Fable 5
parent
02430ccc32
commit
46e3e7aaa0
+22
-15
@@ -547,12 +547,16 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
|
||||
// One box per (function, category): `uploadARCapture` makes one network
|
||||
// call, three storage calls and three telemetry calls — three boxes, each
|
||||
// listing its calls, not seven.
|
||||
// listing its calls, not seven. A reply is the exception: its identity is
|
||||
// the outcome, so `authUser` answering 200 or 401 is two boxes — each
|
||||
// line into them then carries its own condition on the picture, the
|
||||
// Screens view's idiom — and the sites whose status cannot be read share
|
||||
// one `response` box labelled by the call.
|
||||
const effectSub = (e: NonNullable<WireStep['effect']>, by: Node): string =>
|
||||
[e.category, e.model, e.access, by.name].filter((x): x is string => !!x).join(' · ');
|
||||
const effectStep = (by: Node, ref: { referenceName: string; line: number }, effect: Effect, depth: number): StepRecord | null => {
|
||||
const effectStep = (by: Node, ref: { referenceName: string; line: number }, effect: Effect, depth: number, status: number | null = null): StepRecord | null => {
|
||||
const category = effect.category;
|
||||
const id = `effect:${by.id}:${category}`;
|
||||
const id = status !== null ? `effect:${by.id}:${category}:${status}` : `effect:${by.id}:${category}`;
|
||||
const existing = steps.get(id);
|
||||
if (existing) {
|
||||
const e = existing.effect!;
|
||||
@@ -631,20 +635,21 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
args,
|
||||
});
|
||||
if (effect === null) return false;
|
||||
const target = effectStep(fold.node, { referenceName: text, line: ref.line }, effect, step.depth + 1);
|
||||
// A reply's status, read before its box exists — the box is per outcome.
|
||||
// `NextResponse.json(user, { status: 201 })`: the code sits in an object
|
||||
// the abbreviation reduced to its keys; the site reader kept it. And a
|
||||
// body-sending reply that sets none is a 200, so a success has a box of
|
||||
// its own beside the 401's.
|
||||
const status =
|
||||
effect.category === 'response'
|
||||
? (responseStatus(text, args, ref.referenceKind) ?? (usable && typeof site.status === 'number' ? site.status : null) ?? implicitResponseStatus(text))
|
||||
: null;
|
||||
const target = effectStep(fold.node, { referenceName: text, line: ref.line }, effect, step.depth + 1, status);
|
||||
if (target === null) return true;
|
||||
const when = await whenAt(fold.node, at);
|
||||
const wireSite: WireStepSite = { file: posix(fold.node.filePath), line: ref.line, text, when: '' };
|
||||
if (args !== null) wireSite.args = args;
|
||||
if (effect.category === 'response') {
|
||||
// `NextResponse.json(user, { status: 201 })`: the code sits in an object
|
||||
// the abbreviation reduced to its keys; the site reader kept it.
|
||||
// — and a body-sending reply that sets none is a 200, so a success row
|
||||
// says so beside the 401s.
|
||||
const status =
|
||||
responseStatus(text, args, ref.referenceKind) ?? (usable && typeof site.status === 'number' ? site.status : null) ?? implicitResponseStatus(text);
|
||||
if (status !== null) wireSite.status = status;
|
||||
}
|
||||
if (status !== null) wireSite.status = status;
|
||||
link(step, target, 'effect', fold.chain, [...fold.whens, when], wireSite, null, trigger ?? (await triggerAt(fold.node, at)));
|
||||
return true;
|
||||
};
|
||||
@@ -1099,8 +1104,10 @@ export async function buildSteps(cg: CodeGraph, projectRoot: string, query: URLS
|
||||
for (const step of steps.values()) {
|
||||
if (step.kind !== 'effect' || !step.effect) continue;
|
||||
const sites = sitesByStep.get(step.id) ?? [];
|
||||
// A response box is the endpoint's contract: the status codes it can
|
||||
// send, when they are literal, are its label; the rows say when.
|
||||
// A response box is one outcome of the endpoint's contract: its status,
|
||||
// when literal, is its label (one per box by construction); the rows say
|
||||
// when. The box of unreadable statuses holds none and is labelled by its
|
||||
// call below.
|
||||
if (step.effect.category === 'response') {
|
||||
const statuses = [...new Set(sites.map((s) => s.status).filter((x): x is number => typeof x === 'number'))].sort((a, b) => a - b);
|
||||
if (statuses.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user