@orkestrel/scaffold 0.0.55 → 0.0.57

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.
@@ -108,6 +108,8 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
108
108
  }>;
109
109
  docs: Readonly<{
110
110
  readme: "# {{package}}\n\n{{description}}\n\n## Development\n\n```sh\nnpm install\nnpm test\n```\n";
111
+ agents: "# AGENTS.md\n\nThe `@orkestrel/scaffold` package is this repository's coding and orchestration authority. This\nfile points at it and states no law of its own.\n\nRead these before working: the `AGENTS.md` coding contract, the `.agents/orchestration.md`\nagent-operation contract, every applicable rule the contract's rule map names under\n`.claude/rules/`, and the dispatch-named skill under `.agents/skills/` with the references it\nrequires.\n\nResolve every one of those paths against scaffold, never against this repository:\n\n- When a scaffold checkout sits beside this repository, read `../scaffold/AGENTS.md`, the\n `../scaffold/.agents/orchestration.md` file, the `../scaffold/.claude/rules/` directory, and\n the `../scaffold/.agents/skills/` directory.\n- Otherwise read the installed copy, whose paths drop the dot that opens each segment: the\n `node_modules/@orkestrel/scaffold/dist/host/AGENTS.md` file, the\n `node_modules/@orkestrel/scaffold/dist/host/agents/orchestration.md` file, the\n `node_modules/@orkestrel/scaffold/dist/host/claude/rules/` directory, and the\n `node_modules/@orkestrel/scaffold/dist/host/agents/skills/` directory.\n\nEvery path a scaffold-supplied file names resolves the same way. The files this repository carries\n— the `.claude/agents/orkestrel.md` catalog file, the `.claude/settings.json` permission file,\nand the bench scripts under `scripts/` — are this repository's own copies and resolve here.\n\nEdit none of the scaffold-owned files here. The `scaffold repair` command restores them, so a\nchange to one is a commit in the scaffold repository followed by a release.\n";
112
+ claude: "# CLAUDE.md\n\nRead the `AGENTS.md` file in this repository first. It names the coding and orchestration\nauthority and where to read each contract.\n\nThis file imports nothing. An `@path` import inlines the imported file into every context that\nloads it, which is the cost this pointer removes.\n";
111
113
  }>;
112
114
  guides: Readonly<{
113
115
  readme: "# Guides\n\n## By concept\n\n- Package\n - Spec: Not created. Create this file when the workspace has a public surface:\n `guides/{{guide}}.md`\n - Source:\n{{source}}\n - Tests:\n{{tests}}\n\n## By directory\n\n{{directories}}\n";
@@ -343,7 +345,22 @@ export declare function blueprintToDevDependencies(blueprint: Blueprint): Readon
343
345
  * Compile the generated workspace's root documentation.
344
346
  *
345
347
  * @param blueprint - The workspace specification.
346
- * @returns One birth-owned package front page.
348
+ * @returns The birth-owned package front page and the content-owned `AGENTS.md`
349
+ * and `CLAUDE.md` pointers.
350
+ *
351
+ * @remarks
352
+ * The front page is the workspace's own prose, so it is written once and left
353
+ * alone from then on. The pointers are scaffold's, so they are content-owned and
354
+ * restored whenever they drift.
355
+ *
356
+ * A pointer is planned here rather than vendored because `stageHost` refuses two
357
+ * vendored paths at one storage name, and `AGENTS.md` and `CLAUDE.md` already
358
+ * store the canon a release ships. Planning them as this package's own content
359
+ * leaves each path with one claimant.
360
+ *
361
+ * Neither pointer carries a varying span, so neither is filled: a workspace's
362
+ * name never reaches the text, and the paths a reader follows are the same in
363
+ * every target.
347
364
  */
348
365
  export declare function blueprintToDocumentArtifacts(blueprint: Blueprint): readonly ContentArtifact[];
349
366
 
@@ -674,13 +691,52 @@ export declare type BuildFormat = 'es' | 'cjs';
674
691
  */
675
692
  export declare function bytesToHex(bytes: Uint8Array): string;
676
693
 
694
+ /**
695
+ * The instruction-canon paths staged for reading rather than for a target, frozen.
696
+ *
697
+ * @remarks
698
+ * The root instruction documents, the orchestration contract every harness
699
+ * bridge points at, the rule map's rules, the skills, the templates, the
700
+ * transport contracts, the agent roles each harness dispatches, the bench
701
+ * configuration, and the MCP registrations. A directory entry covers everything
702
+ * beneath it.
703
+ *
704
+ * Staging walks these beside {@link HOST_PATHS}, so a release ships them and a
705
+ * reader reaches them two ways: a scaffold checkout sitting beside the
706
+ * repository, or the `node_modules/@orkestrel/scaffold/dist/host/` root inside
707
+ * the installed package. The `AGENTS.md` and `CLAUDE.md` pointers scaffold plans
708
+ * are what name each location.
709
+ *
710
+ * The lists are disjoint by prefix in either direction: no member of either
711
+ * equals or sits beneath a member of the other. Staging depends on that, because
712
+ * the walk covers the union and a path it discovers twice claims one storage
713
+ * name twice, which refuses the stage.
714
+ *
715
+ * The plan claims paths inside the canon deliberately, and each has a reason.
716
+ * `blueprintToDocumentArtifacts` claims `AGENTS.md` and `CLAUDE.md` as this
717
+ * package's own template pointers. `nameToHostArtifacts` claims
718
+ * {@link CATALOG_AGENT_PATH}, because the catalog verb refuses a target that
719
+ * lacks the file and repair restores its absence.
720
+ *
721
+ * A target therefore holds a file at a canon path only where the plan claims it.
722
+ * That is the rule every verb obeys, and it is what makes a copy found anywhere
723
+ * else superseded.
724
+ */
725
+ export declare const CANON_PATHS: readonly string[];
726
+
677
727
  /**
678
728
  * The agent file whose marker-bounded package table the catalog verb alone owns.
679
729
  *
680
730
  * @remarks
681
- * It is vendored like every other host artifact but claimed by presence rather
682
- * than content, so a consumer's own edits to the file survive every verb and
683
- * only the catalog verb rewrites the region inside the markers.
731
+ * A plan claims it at a canon path, because the catalog verb refuses a target
732
+ * that lacks the file. `nameToHostArtifacts` appends it to the vendored
733
+ * selection, and it reaches a release through the `.claude/agents` directory in
734
+ * {@link CANON_PATHS} rather than through {@link HOST_PATHS}, which is what
735
+ * keeps the two lists disjoint.
736
+ *
737
+ * It is claimed by presence rather than content, so a consumer's own edits to
738
+ * the file survive every verb and only the catalog verb rewrites the region
739
+ * inside the markers.
684
740
  */
685
741
  export declare const CATALOG_AGENT_PATH = ".claude/agents/orkestrel.md";
686
742
 
@@ -1485,18 +1541,24 @@ export declare class Compiler implements CompilerInterface {
1485
1541
  export declare const HOST_INVENTORY_PATH = "host.json";
1486
1542
 
1487
1543
  /**
1488
- * The paths byte-copied from the vendored data root, frozen.
1544
+ * The paths a target receives from the vendored data root, frozen.
1489
1545
  *
1490
1546
  * @remarks
1491
- * These are the files the fleet shares verbatim: the root instruction
1492
- * documents, the licence, the canonical orchestration contract every harness
1493
- * bridge points at, the harness directories, the session hook scripts,
1494
- * the shared policy register, the byte-identical root dotfiles, and the
1495
- * guide mirrors a generated workspace starts from. A directory entry vendors
1547
+ * These are the files the fleet shares verbatim and every target holds a copy
1548
+ * of: the licence, the harness permission file, the session hook scripts, the
1549
+ * shared policy register, the byte-identical root dotfiles, and the guide
1550
+ * mirrors a generated workspace starts from. A directory entry vendors
1496
1551
  * everything beneath it.
1497
1552
  *
1498
1553
  * A plan carries the subset its target selects, which is why the list is a
1499
1554
  * candidate set rather than a plan: a workspace never mirrors its own guide.
1555
+ *
1556
+ * Neither the instruction canon nor the harness wiring is here. A target reads
1557
+ * its rules, its skills, its agent roles, its bench configuration, and its MCP
1558
+ * registrations from {@link CANON_PATHS} inside the installed package, so no
1559
+ * file scaffold leaves in a target names a path the target does not hold.
1560
+ * `nameToHostArtifacts` appends {@link CATALOG_AGENT_PATH} to what this list
1561
+ * selects, which is what keeps the list itself disjoint from the canon.
1500
1562
  */
1501
1563
  export declare const HOST_PATHS: readonly string[];
1502
1564
 
@@ -1686,6 +1748,34 @@ export declare class Compiler implements CompilerInterface {
1686
1748
  */
1687
1749
  export declare const isBlueprint: Guard<Blueprint>;
1688
1750
 
1751
+ /**
1752
+ * Checks whether a path belongs to the instruction canon a target reads rather than holds.
1753
+ *
1754
+ * @param path - The target-relative path to test.
1755
+ * @returns `true` for a {@link CANON_PATHS} member and for any path beneath a
1756
+ * member that is a directory; `false` otherwise.
1757
+ *
1758
+ * @remarks
1759
+ * The one reading of canon membership, so the live overlay and the executable's
1760
+ * fetch list never disagree about what a path is. The match runs to a segment
1761
+ * boundary, so a sibling whose name opens with a member's name —
1762
+ * `.claude/rulesets` beside `.claude/rules` — stays outside.
1763
+ *
1764
+ * Membership answers where a path's bytes are staged, not whether a plan claims
1765
+ * it. A plan claims `AGENTS.md`, `CLAUDE.md`, and {@link CATALOG_AGENT_PATH} at
1766
+ * canon paths deliberately, so a consumer deciding whether to write, restore, or
1767
+ * remove a path reads the plan rather than this predicate.
1768
+ *
1769
+ * @example
1770
+ * ```ts
1771
+ * import { isCanonPath } from '@orkestrel/scaffold'
1772
+ *
1773
+ * isCanonPath('.claude/rules/names.md') // true
1774
+ * isCanonPath('.claude/settings.json') // false
1775
+ * ```
1776
+ */
1777
+ export declare function isCanonPath(path: string): boolean;
1778
+
1689
1779
  /**
1690
1780
  * Narrow a value to a {@link CatalogEntry}.
1691
1781
  *
@@ -2361,7 +2451,8 @@ export declare class Compiler implements CompilerInterface {
2361
2451
  * Compile the vendored host artifacts a named workspace plans.
2362
2452
  *
2363
2453
  * @param name - The target workspace's own bare package name.
2364
- * @returns One artifact per vendored path, in `HOST_PATHS` order.
2454
+ * @returns One artifact per vendored path in `HOST_PATHS` order, then the
2455
+ * catalog file.
2365
2456
  *
2366
2457
  * @remarks
2367
2458
  * Every artifact is claimed by presence, which is the strongest claim a pure
@@ -2375,11 +2466,21 @@ export declare class Compiler implements CompilerInterface {
2375
2466
  * are classified by one rule and a plan never disagrees with the audit beside
2376
2467
  * it.
2377
2468
  *
2469
+ * {@link CATALOG_AGENT_PATH} is appended rather than listed, and it is the canon
2470
+ * path this compiler claims. The catalog verb refuses a target that lacks the
2471
+ * file, so the plan has to carry it; repair restores its absence from the
2472
+ * staged bytes; and the `.claude/agents` directory in `CANON_PATHS` is what
2473
+ * stages those bytes, so listing the file in `HOST_PATHS` as well would claim one
2474
+ * storage name twice and refuse the stage. The rest of the canon a target reads
2475
+ * from the installed package, at the locations the `AGENTS.md` and `CLAUDE.md`
2476
+ * pointers {@link blueprintToDocumentArtifacts} emits name.
2477
+ *
2378
2478
  * @example
2379
2479
  * ```ts
2380
2480
  * import { nameToHostArtifacts } from '@orkestrel/scaffold'
2381
2481
  *
2382
- * nameToHostArtifacts('router').some((artifact) => artifact.path === 'AGENTS.md') // true
2482
+ * nameToHostArtifacts('router').some((artifact) => artifact.path === '.claude/settings.json') // true
2483
+ * nameToHostArtifacts('router').some((artifact) => artifact.path === '.claude/agents/orkestrel.md') // true
2383
2484
  * nameToHostArtifacts('router').some((artifact) => artifact.path === 'guides/router.md') // false
2384
2485
  * ```
2385
2486
  */
@@ -108,6 +108,8 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
108
108
  }>;
109
109
  docs: Readonly<{
110
110
  readme: "# {{package}}\n\n{{description}}\n\n## Development\n\n```sh\nnpm install\nnpm test\n```\n";
111
+ agents: "# AGENTS.md\n\nThe `@orkestrel/scaffold` package is this repository's coding and orchestration authority. This\nfile points at it and states no law of its own.\n\nRead these before working: the `AGENTS.md` coding contract, the `.agents/orchestration.md`\nagent-operation contract, every applicable rule the contract's rule map names under\n`.claude/rules/`, and the dispatch-named skill under `.agents/skills/` with the references it\nrequires.\n\nResolve every one of those paths against scaffold, never against this repository:\n\n- When a scaffold checkout sits beside this repository, read `../scaffold/AGENTS.md`, the\n `../scaffold/.agents/orchestration.md` file, the `../scaffold/.claude/rules/` directory, and\n the `../scaffold/.agents/skills/` directory.\n- Otherwise read the installed copy, whose paths drop the dot that opens each segment: the\n `node_modules/@orkestrel/scaffold/dist/host/AGENTS.md` file, the\n `node_modules/@orkestrel/scaffold/dist/host/agents/orchestration.md` file, the\n `node_modules/@orkestrel/scaffold/dist/host/claude/rules/` directory, and the\n `node_modules/@orkestrel/scaffold/dist/host/agents/skills/` directory.\n\nEvery path a scaffold-supplied file names resolves the same way. The files this repository carries\n— the `.claude/agents/orkestrel.md` catalog file, the `.claude/settings.json` permission file,\nand the bench scripts under `scripts/` — are this repository's own copies and resolve here.\n\nEdit none of the scaffold-owned files here. The `scaffold repair` command restores them, so a\nchange to one is a commit in the scaffold repository followed by a release.\n";
112
+ claude: "# CLAUDE.md\n\nRead the `AGENTS.md` file in this repository first. It names the coding and orchestration\nauthority and where to read each contract.\n\nThis file imports nothing. An `@path` import inlines the imported file into every context that\nloads it, which is the cost this pointer removes.\n";
111
113
  }>;
112
114
  guides: Readonly<{
113
115
  readme: "# Guides\n\n## By concept\n\n- Package\n - Spec: Not created. Create this file when the workspace has a public surface:\n `guides/{{guide}}.md`\n - Source:\n{{source}}\n - Tests:\n{{tests}}\n\n## By directory\n\n{{directories}}\n";
@@ -343,7 +345,22 @@ export declare function blueprintToDevDependencies(blueprint: Blueprint): Readon
343
345
  * Compile the generated workspace's root documentation.
344
346
  *
345
347
  * @param blueprint - The workspace specification.
346
- * @returns One birth-owned package front page.
348
+ * @returns The birth-owned package front page and the content-owned `AGENTS.md`
349
+ * and `CLAUDE.md` pointers.
350
+ *
351
+ * @remarks
352
+ * The front page is the workspace's own prose, so it is written once and left
353
+ * alone from then on. The pointers are scaffold's, so they are content-owned and
354
+ * restored whenever they drift.
355
+ *
356
+ * A pointer is planned here rather than vendored because `stageHost` refuses two
357
+ * vendored paths at one storage name, and `AGENTS.md` and `CLAUDE.md` already
358
+ * store the canon a release ships. Planning them as this package's own content
359
+ * leaves each path with one claimant.
360
+ *
361
+ * Neither pointer carries a varying span, so neither is filled: a workspace's
362
+ * name never reaches the text, and the paths a reader follows are the same in
363
+ * every target.
347
364
  */
348
365
  export declare function blueprintToDocumentArtifacts(blueprint: Blueprint): readonly ContentArtifact[];
349
366
 
@@ -674,13 +691,52 @@ export declare type BuildFormat = 'es' | 'cjs';
674
691
  */
675
692
  export declare function bytesToHex(bytes: Uint8Array): string;
676
693
 
694
+ /**
695
+ * The instruction-canon paths staged for reading rather than for a target, frozen.
696
+ *
697
+ * @remarks
698
+ * The root instruction documents, the orchestration contract every harness
699
+ * bridge points at, the rule map's rules, the skills, the templates, the
700
+ * transport contracts, the agent roles each harness dispatches, the bench
701
+ * configuration, and the MCP registrations. A directory entry covers everything
702
+ * beneath it.
703
+ *
704
+ * Staging walks these beside {@link HOST_PATHS}, so a release ships them and a
705
+ * reader reaches them two ways: a scaffold checkout sitting beside the
706
+ * repository, or the `node_modules/@orkestrel/scaffold/dist/host/` root inside
707
+ * the installed package. The `AGENTS.md` and `CLAUDE.md` pointers scaffold plans
708
+ * are what name each location.
709
+ *
710
+ * The lists are disjoint by prefix in either direction: no member of either
711
+ * equals or sits beneath a member of the other. Staging depends on that, because
712
+ * the walk covers the union and a path it discovers twice claims one storage
713
+ * name twice, which refuses the stage.
714
+ *
715
+ * The plan claims paths inside the canon deliberately, and each has a reason.
716
+ * `blueprintToDocumentArtifacts` claims `AGENTS.md` and `CLAUDE.md` as this
717
+ * package's own template pointers. `nameToHostArtifacts` claims
718
+ * {@link CATALOG_AGENT_PATH}, because the catalog verb refuses a target that
719
+ * lacks the file and repair restores its absence.
720
+ *
721
+ * A target therefore holds a file at a canon path only where the plan claims it.
722
+ * That is the rule every verb obeys, and it is what makes a copy found anywhere
723
+ * else superseded.
724
+ */
725
+ export declare const CANON_PATHS: readonly string[];
726
+
677
727
  /**
678
728
  * The agent file whose marker-bounded package table the catalog verb alone owns.
679
729
  *
680
730
  * @remarks
681
- * It is vendored like every other host artifact but claimed by presence rather
682
- * than content, so a consumer's own edits to the file survive every verb and
683
- * only the catalog verb rewrites the region inside the markers.
731
+ * A plan claims it at a canon path, because the catalog verb refuses a target
732
+ * that lacks the file. `nameToHostArtifacts` appends it to the vendored
733
+ * selection, and it reaches a release through the `.claude/agents` directory in
734
+ * {@link CANON_PATHS} rather than through {@link HOST_PATHS}, which is what
735
+ * keeps the two lists disjoint.
736
+ *
737
+ * It is claimed by presence rather than content, so a consumer's own edits to
738
+ * the file survive every verb and only the catalog verb rewrites the region
739
+ * inside the markers.
684
740
  */
685
741
  export declare const CATALOG_AGENT_PATH = ".claude/agents/orkestrel.md";
686
742
 
@@ -1485,18 +1541,24 @@ export declare class Compiler implements CompilerInterface {
1485
1541
  export declare const HOST_INVENTORY_PATH = "host.json";
1486
1542
 
1487
1543
  /**
1488
- * The paths byte-copied from the vendored data root, frozen.
1544
+ * The paths a target receives from the vendored data root, frozen.
1489
1545
  *
1490
1546
  * @remarks
1491
- * These are the files the fleet shares verbatim: the root instruction
1492
- * documents, the licence, the canonical orchestration contract every harness
1493
- * bridge points at, the harness directories, the session hook scripts,
1494
- * the shared policy register, the byte-identical root dotfiles, and the
1495
- * guide mirrors a generated workspace starts from. A directory entry vendors
1547
+ * These are the files the fleet shares verbatim and every target holds a copy
1548
+ * of: the licence, the harness permission file, the session hook scripts, the
1549
+ * shared policy register, the byte-identical root dotfiles, and the guide
1550
+ * mirrors a generated workspace starts from. A directory entry vendors
1496
1551
  * everything beneath it.
1497
1552
  *
1498
1553
  * A plan carries the subset its target selects, which is why the list is a
1499
1554
  * candidate set rather than a plan: a workspace never mirrors its own guide.
1555
+ *
1556
+ * Neither the instruction canon nor the harness wiring is here. A target reads
1557
+ * its rules, its skills, its agent roles, its bench configuration, and its MCP
1558
+ * registrations from {@link CANON_PATHS} inside the installed package, so no
1559
+ * file scaffold leaves in a target names a path the target does not hold.
1560
+ * `nameToHostArtifacts` appends {@link CATALOG_AGENT_PATH} to what this list
1561
+ * selects, which is what keeps the list itself disjoint from the canon.
1500
1562
  */
1501
1563
  export declare const HOST_PATHS: readonly string[];
1502
1564
 
@@ -1686,6 +1748,34 @@ export declare class Compiler implements CompilerInterface {
1686
1748
  */
1687
1749
  export declare const isBlueprint: Guard<Blueprint>;
1688
1750
 
1751
+ /**
1752
+ * Checks whether a path belongs to the instruction canon a target reads rather than holds.
1753
+ *
1754
+ * @param path - The target-relative path to test.
1755
+ * @returns `true` for a {@link CANON_PATHS} member and for any path beneath a
1756
+ * member that is a directory; `false` otherwise.
1757
+ *
1758
+ * @remarks
1759
+ * The one reading of canon membership, so the live overlay and the executable's
1760
+ * fetch list never disagree about what a path is. The match runs to a segment
1761
+ * boundary, so a sibling whose name opens with a member's name —
1762
+ * `.claude/rulesets` beside `.claude/rules` — stays outside.
1763
+ *
1764
+ * Membership answers where a path's bytes are staged, not whether a plan claims
1765
+ * it. A plan claims `AGENTS.md`, `CLAUDE.md`, and {@link CATALOG_AGENT_PATH} at
1766
+ * canon paths deliberately, so a consumer deciding whether to write, restore, or
1767
+ * remove a path reads the plan rather than this predicate.
1768
+ *
1769
+ * @example
1770
+ * ```ts
1771
+ * import { isCanonPath } from '@orkestrel/scaffold'
1772
+ *
1773
+ * isCanonPath('.claude/rules/names.md') // true
1774
+ * isCanonPath('.claude/settings.json') // false
1775
+ * ```
1776
+ */
1777
+ export declare function isCanonPath(path: string): boolean;
1778
+
1689
1779
  /**
1690
1780
  * Narrow a value to a {@link CatalogEntry}.
1691
1781
  *
@@ -2361,7 +2451,8 @@ export declare class Compiler implements CompilerInterface {
2361
2451
  * Compile the vendored host artifacts a named workspace plans.
2362
2452
  *
2363
2453
  * @param name - The target workspace's own bare package name.
2364
- * @returns One artifact per vendored path, in `HOST_PATHS` order.
2454
+ * @returns One artifact per vendored path in `HOST_PATHS` order, then the
2455
+ * catalog file.
2365
2456
  *
2366
2457
  * @remarks
2367
2458
  * Every artifact is claimed by presence, which is the strongest claim a pure
@@ -2375,11 +2466,21 @@ export declare class Compiler implements CompilerInterface {
2375
2466
  * are classified by one rule and a plan never disagrees with the audit beside
2376
2467
  * it.
2377
2468
  *
2469
+ * {@link CATALOG_AGENT_PATH} is appended rather than listed, and it is the canon
2470
+ * path this compiler claims. The catalog verb refuses a target that lacks the
2471
+ * file, so the plan has to carry it; repair restores its absence from the
2472
+ * staged bytes; and the `.claude/agents` directory in `CANON_PATHS` is what
2473
+ * stages those bytes, so listing the file in `HOST_PATHS` as well would claim one
2474
+ * storage name twice and refuse the stage. The rest of the canon a target reads
2475
+ * from the installed package, at the locations the `AGENTS.md` and `CLAUDE.md`
2476
+ * pointers {@link blueprintToDocumentArtifacts} emits name.
2477
+ *
2378
2478
  * @example
2379
2479
  * ```ts
2380
2480
  * import { nameToHostArtifacts } from '@orkestrel/scaffold'
2381
2481
  *
2382
- * nameToHostArtifacts('router').some((artifact) => artifact.path === 'AGENTS.md') // true
2482
+ * nameToHostArtifacts('router').some((artifact) => artifact.path === '.claude/settings.json') // true
2483
+ * nameToHostArtifacts('router').some((artifact) => artifact.path === '.claude/agents/orkestrel.md') // true
2383
2484
  * nameToHostArtifacts('router').some((artifact) => artifact.path === 'guides/router.md') // false
2384
2485
  * ```
2385
2486
  */