Skip to content

Commit 77b8611

Browse files
committed
test(cli): read the data door beside the metadata door for the residual rows
Every acme_* object /meta/object lists is read back on /data/<name>, through both boots. Row 4 now pins that the residual object the metadata door lists under manifest.id is served by the data door too. Claude-Session: https://claude.ai/code/session_01JfJfBUC3cQ6hhgm9MQK76T Co-authored-by: Claude <noreply@anthropic.com>
1 parent cb3bb93 commit 77b8611

1 file changed

Lines changed: 31 additions & 7 deletions

File tree

‎packages/cli/test/serve-config-boot-residual.integration.test.ts‎

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@
4040
* - CONTROL: a single-package config (no `packages[]`) is unchanged and has
4141
* no residual on either door.
4242
*
43-
* ⚠️ What this file does NOT pin: the data door for a residual OBJECT. Both
44-
* doors list it on `/meta/object` and answer `404` on `/data/<name>` — the
45-
* residual rule registers metadata, and no engine registration follows. That
46-
* is the artifact door's answer this card makes the config boot match, not a
47-
* behaviour to freeze.
43+
* The DATA door is read beside the metadata door (#22615): every `acme_*`
44+
* object `/meta/object` lists is read back on `/data/<name>`. A residual object
45+
* is listed under the stack's `manifest.id` AND served under it — the engine's
46+
* `manifest` service registers the residual rule's own objects
47+
* (`unclaimedTopLevel`), so both doors give one answer through both boots.
48+
* Before that, both boots listed `acme_note` and answered `404` on
49+
* `/data/acme_note`. The bodies' own objects are the control: `200` before and
50+
* after, on every row.
4851
*
4952
* ⚠️ Pedigree, not counts: every doc page carries a marker written into exactly
5053
* one source, read back from the served doc.
@@ -325,6 +328,8 @@ interface Reading {
325328
/** `name@owner`, sorted. */
326329
objects: string[];
327330
views: string[];
331+
/** `name:status` of `GET /data/<name>` for every object `objects` lists, sorted. */
332+
data: string[];
328333
/** The count each residual line reports — one entry per line printed. */
329334
residual: number[];
330335
}
@@ -364,14 +369,23 @@ async function read(dir: string, args: string[]): Promise<Reading> {
364369
marker: /MARKER-22521-[\w-]+/.exec(JSON.stringify(one.body))?.[0],
365370
};
366371
}
367-
const objects = owned(await list('object'));
372+
const listedObjects = await list('object');
373+
const objects = owned(listedObjects);
368374
const views = owned(await list('view'));
375+
// The data door, for exactly the objects the metadata door listed: one
376+
// answer per object across the two doors (#22615).
377+
const data: string[] = [];
378+
for (const item of listedObjects) {
379+
const rows = await request(serve, `the data read of ${item.name}`, `${base}/data/${item.name}`, { headers });
380+
data.push(`${item.name}:${rows.status}`);
381+
}
382+
data.sort();
369383
const residual = serve.output()
370384
.split('\n')
371385
.map((line) => RESIDUAL_LINE.exec(line)?.[1])
372386
.filter((count): count is string => count !== undefined)
373387
.map(Number);
374-
return { docs, objects, views, residual };
388+
return { docs, objects, views, data, residual };
375389
} finally {
376390
await stop(serve.child);
377391
}
@@ -455,6 +469,8 @@ describe('#22521 row 2: flat src/docs with a manifest.id naming no package', ()
455469
acme_faq: { packageId: RELEASE_ID, marker: 'MARKER-22521-flat-faq' },
456470
});
457471
expect(artifact.residual).toEqual([2]);
472+
// The control for #22615's data-door reading: the bodies' own objects.
473+
expect(artifact.data, JSON.stringify(artifact)).toEqual(['acme_account:200', 'acme_case:200']);
458474
});
459475

460476
it('the config boot gives the artifact boot\'s answer, without --dev', () => {
@@ -493,6 +509,12 @@ describe('#22521 row 4: a top-level object and view no package owns', () => {
493509
// Before the fix: neither acme_note nor its view listed, no residual line.
494510
expect(configDev).toEqual(artifact);
495511
});
512+
513+
it('the data door serves the residual object the metadata door lists, through both boots (#22615)', () => {
514+
// Before #22615, on both boots: `acme_note:404` beside the listing above.
515+
expect(artifact.data, JSON.stringify(artifact)).toEqual(['acme_account:200', 'acme_case:200', 'acme_note:200']);
516+
expect(configDev.data, JSON.stringify(configDev)).toEqual(artifact.data);
517+
});
496518
});
497519

498520
describe('#22521 row 3: inline docs spread on a composed stack\'s top level', () => {
@@ -519,6 +541,7 @@ describe('#22521 row 3: inline docs spread on a composed stack\'s top level', ()
519541
acme_inline: { packageId: APP_ID, marker: 'MARKER-22521-inline' },
520542
});
521543
expect(configDev.residual).toEqual([1]);
544+
expect(configDev.data, JSON.stringify(configDev)).toEqual(['acme_account:200', 'acme_case:200']);
522545
});
523546
});
524547

@@ -540,6 +563,7 @@ describe('#22521 control: a single-package config has no residual on either door
540563
});
541564
expect(artifact.objects).toEqual([`acme_account@${APP_ID}`, `acme_note@${APP_ID}`]);
542565
expect(artifact.views).toEqual([`acme_note.default@${APP_ID}`]);
566+
expect(artifact.data).toEqual(['acme_account:200', 'acme_note:200']);
543567
expect(artifact.residual).toEqual([]);
544568
});
545569

0 commit comments

Comments
 (0)