|
44 | 44 | * branch did not move, and this literal is what would go red if it ever did. |
45 | 45 | * It was recorded on both legs of the ablation in the PR body, from the same |
46 | 46 | * fixture, and compared byte for byte. |
| 47 | + * |
| 48 | + * --------------------------------------------------------------------------- |
| 49 | + * The second describe block (#19246) — the same door, a different reading |
| 50 | + * --------------------------------------------------------------------------- |
| 51 | + * #19246 was filed on a STATIC reading, twice and independently: that a |
| 52 | + * multi-package artifact's top-level-only `docs` register nowhere at boot. |
| 53 | + * Both readings were correct about the two places they looked — |
| 54 | + * `resolveArtifactPackageOrder` does walk package bodies only, and |
| 55 | + * `AppPlugin` does not register `collections.docs` — and both concluded |
| 56 | + * "nowhere" without reaching this door, which is the registrar. Booting the |
| 57 | + * #18431 e2e fixture and asking `GET /api/v1/meta/doc` (the live surface) |
| 58 | + * showed the doc PRESENT, beside a per-package doc as the lit control. The |
| 59 | + * block at the foot of this file is that measurement made permanent, so the |
| 60 | + * next reader of those two files finds a pin instead of a third reading. |
47 | 61 | */ |
48 | 62 |
|
49 | 63 | import { describe, it, expect, vi } from 'vitest'; |
@@ -318,3 +332,119 @@ describe('#14599 artifact door — a `packages[]` artifact is registered per pac |
318 | 332 | expect(warnings.filter((w: string) => w.includes('top-level metadata item'))).toEqual([]); |
319 | 333 | }); |
320 | 334 | }); |
| 335 | + |
| 336 | +/** |
| 337 | + * The doc `os build` writes out of a flat `src/docs/` — judged by |
| 338 | + * `stack.manifest.namespace` and placed at the artifact TOP LEVEL, on no |
| 339 | + * package body at all (#18431 ruling, clause 1). |
| 340 | + * |
| 341 | + * The `content` carries a marker for the same reason the e2e fixture does: a |
| 342 | + * count is satisfiable by an echo of the other doc, and pedigree is not. |
| 343 | + */ |
| 344 | +const FLAT_DOC = { name: 'pkgdocs_index', label: 'Index', content: '# Index\n\nMARKER-flat-doc\n' }; |
| 345 | + |
| 346 | +/** The doc `os build` writes out of `src/orders/docs/` — the OWNING body only. */ |
| 347 | +const PACKAGE_DOC = { |
| 348 | + name: 'ord_playbook', |
| 349 | + label: 'Orders Playbook', |
| 350 | + content: '# Orders Playbook\n\nMARKER-package-doc\n', |
| 351 | +}; |
| 352 | + |
| 353 | +/** |
| 354 | + * The #18431 docs placement, laid over the real composed artifact. |
| 355 | + * |
| 356 | + * ⚠️ The docs half is positioned by hand, and that is deliberate — it is the |
| 357 | + * ONE key on which `composeStacks(…, { manifest: 'preserve' })` is not the |
| 358 | + * producer. `os build`'s docs collector places docs AFTER composition: a |
| 359 | + * package-directory doc goes on its owning body and ⛔ never to the top level, |
| 360 | + * while the stack's own flat `src/docs/` keeps the top level. So composing a |
| 361 | + * `docs`-carrying stack would produce the additive both-places shape, which is |
| 362 | + * precisely NOT the shape under test. The placement below was read off a real |
| 363 | + * `os build` of the #18431 e2e fixture (two packages, `src/docs/` + |
| 364 | + * `src/orders/docs/`): top level `['pkgdocs_index']`, orders body |
| 365 | + * `['ord_playbook']`, core body none. |
| 366 | + */ |
| 367 | +const docsArtifact = () => { |
| 368 | + const artifact = twoPackageArtifact(); |
| 369 | + artifact.docs = [{ ...FLAT_DOC }]; |
| 370 | + const orders = artifact.packages.find((e: any) => e.manifest.id === ORDERS_ID); |
| 371 | + orders.manifest.docs = [{ ...PACKAGE_DOC }]; |
| 372 | + return artifact; |
| 373 | +}; |
| 374 | + |
| 375 | +describe('#19246 artifact door — a `packages[]` artifact\'s TOP-LEVEL-only docs register', () => { |
| 376 | + it('the fixture carries the card shape (premise guard)', () => { |
| 377 | + const artifact = docsArtifact(); |
| 378 | + |
| 379 | + // The subject: a top-level doc that NO package body declares. This is |
| 380 | + // the emitter's intended output for a multi-package project with a flat |
| 381 | + // `src/docs/`, not an accident of `packages` being a `concat` key — so |
| 382 | + // unlike the orphan `object` case above, this shape is on every such |
| 383 | + // artifact the compiler produces. |
| 384 | + expect(artifact.docs.map((d: any) => d.name)).toEqual(['pkgdocs_index']); |
| 385 | + const onBodies = artifact.packages.flatMap((e: any) => (e.manifest.docs ?? []).map((d: any) => d.name)); |
| 386 | + expect(onBodies).not.toContain('pkgdocs_index'); |
| 387 | + |
| 388 | + // The control: a doc that reaches the registry through the package |
| 389 | + // walk, and is NOT at the top level. |
| 390 | + expect(onBodies).toEqual(['ord_playbook']); |
| 391 | + expect(JSON.stringify(artifact.docs)).not.toContain('MARKER-package-doc'); |
| 392 | + }); |
| 393 | + |
| 394 | + it('registers BOTH — the body doc via the package walk, the top-level-only doc via the residual sweep', async () => { |
| 395 | + const { plugin } = await load(docsArtifact()); |
| 396 | + |
| 397 | + // ⭐ The lit control, asserted FIRST and in the same load: a `doc` that |
| 398 | + // does register. Without it an absent subject below would be equally |
| 399 | + // consistent with a door that registers no `doc` at all, a fixture that |
| 400 | + // never parsed, or a harness that recorded nothing. |
| 401 | + expect(await stampOf(plugin, 'doc', 'ord_playbook')) |
| 402 | + .toEqual({ packageId: ORDERS_ID, packageVersion: '2.4.0' }); |
| 403 | + |
| 404 | + // The subject. The static reading this pin exists to contradict was |
| 405 | + // that `resolveArtifactPackageOrder` walks bodies only (true) and that |
| 406 | + // `AppPlugin` registers no `collections.docs` (also true) — and |
| 407 | + // concluded "nowhere", having never reached THIS door's residual sweep, |
| 408 | + // which is the registrar. |
| 409 | + expect(await stampOf(plugin, 'doc', 'pkgdocs_index')) |
| 410 | + .toEqual({ packageId: CORE_ID, packageVersion: '1.0.0' }); |
| 411 | + |
| 412 | + // Pedigree, not counts: each registered doc carries the bytes of the |
| 413 | + // file it came from, so neither assertion above can be satisfied by an |
| 414 | + // echo of the other. |
| 415 | + expect(((await plugin.manager.get('doc', 'pkgdocs_index')) as any).content) |
| 416 | + .toContain('MARKER-flat-doc'); |
| 417 | + expect(((await plugin.manager.get('doc', 'ord_playbook')) as any).content) |
| 418 | + .toContain('MARKER-package-doc'); |
| 419 | + }); |
| 420 | + |
| 421 | + it('the absence arm: with the top-level doc gone the control still registers', async () => { |
| 422 | + // The negative leg of the same instrument. A pin that asserts presence |
| 423 | + // is worth only as much as its ability to report absence, and these two |
| 424 | + // cases differ by exactly the top-level `docs` array. |
| 425 | + const artifact = docsArtifact(); |
| 426 | + delete artifact.docs; |
| 427 | + |
| 428 | + const { plugin, ctx } = await load(artifact); |
| 429 | + |
| 430 | + expect(await stampOf(plugin, 'doc', 'pkgdocs_index')).toBeUndefined(); |
| 431 | + expect(await stampOf(plugin, 'doc', 'ord_playbook')) |
| 432 | + .toEqual({ packageId: ORDERS_ID, packageVersion: '2.4.0' }); |
| 433 | + |
| 434 | + // …and with nothing unowned at the top level, the sweep says nothing. |
| 435 | + const warnings = ctx.logger.warn.mock.calls.map((c: unknown[]) => String(c[0])); |
| 436 | + expect(warnings.filter((w: string) => w.includes('top-level metadata item'))).toEqual([]); |
| 437 | + }); |
| 438 | + |
| 439 | + it('says out loud that the artifact\'s two halves disagree', async () => { |
| 440 | + const { ctx } = await load(docsArtifact()); |
| 441 | + |
| 442 | + // The registration is silent-by-default's opposite: the door warns, and |
| 443 | + // the remedy it names is one an author can actually perform — measured |
| 444 | + // on the same fixture, moving `src/docs/pkgdocs_index.md` to |
| 445 | + // `src/core/docs/` puts the doc on the core body and the top-level |
| 446 | + // `docs` key disappears from the artifact. |
| 447 | + const warnings = ctx.logger.warn.mock.calls.map((c: unknown[]) => String(c[0])); |
| 448 | + expect(warnings.some((w: string) => w.includes('top-level metadata item'))).toBe(true); |
| 449 | + }); |
| 450 | +}); |
0 commit comments