mandrel 2.38.0 → 2.39.0

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.
@@ -622,6 +622,17 @@ const PLANNING_SCHEMA = {
622
622
  // qa.* — Agent-driven QA harness contract (Epic #3214)
623
623
  // ---------------------------------------------------------------------------
624
624
 
625
+ // The per-environment sign-in seam. `{ urlTemplate }` is a dev
626
+ // impersonation route; `{ skill }` names a skill by its tier-relative id
627
+ // (e.g. `stack/qa/acme-sso`), resolved against the payload skills root and
628
+ // then the consumer-writable `.agents/local/skills/` zone (Story #5135).
629
+ //
630
+ // No default anywhere in this file may name a skill id: the framework ships
631
+ // no sign-in skill, so any id baked into an inventory value would be a
632
+ // dangling pointer a consumer copies verbatim — the exact defect #5134
633
+ // reported. The `{ skill }` arm is taught in prose (`.agents/README.md`
634
+ // § "Expose a `signInSeam`"), and `resolveQaEnvironment` fails loudly on an
635
+ // id that resolves under neither root.
625
636
  const QA_SIGN_IN_SEAM_SCHEMA = {
626
637
  oneOf: [
627
638
  {
@@ -654,9 +665,13 @@ const QA_PERSONAS_SCHEMA = {
654
665
  description:
655
666
  'Personas the QA-harness sign-in seam accepts. Two accepted shapes: (1) a plain array of persona names — the honest shape for a `urlTemplate` dev-impersonation seam, where the persona name is the sole input the workflow consumes; (2) the object-map form keyed by persona name, where each entry carries per-persona auth material (`credentialRef` or `signInSkill`) consulted only under a skill-based or credential-based seam.',
656
667
  // Inventory value: an illustrative map showing both per-persona shapes.
668
+ // Inventory value: illustrative credential references, not resolvable
669
+ // ones. It deliberately does NOT illustrate the `signInSkill` arm — a
670
+ // skill id in a shipped default is a dangling pointer (see
671
+ // QA_SIGN_IN_SEAM_SCHEMA above); that arm is taught in prose instead.
657
672
  default: {
658
673
  admin: { credentialRef: 'QA_ADMIN_CREDENTIAL' },
659
- member: { signInSkill: 'stack/qa/sign-in-member' },
674
+ member: { credentialRef: 'QA_MEMBER_CREDENTIAL' },
660
675
  },
661
676
  oneOf: [
662
677
  {
@@ -703,11 +718,11 @@ const QA_PERSONAS_SCHEMA = {
703
718
  const QA_ENVIRONMENTS_SCHEMA = {
704
719
  type: 'object',
705
720
  description:
706
- 'Deployment targets the QA harness can run against (Epic #4326). A map keyed by environment name (e.g. `local`, `staging`), each carrying its own `baseUrl`, its own per-environment sign-in seam (the same url-template/skill union as the top-level seam), and an optional `allowWrites` gate. resolveQaEnvironment selects one environment per invocation by name or by raw-URL origin match against `baseUrl`; `allowWrites` defaults to true only for the `local` environment. Replaces the retired top-level single `signInSeam`.',
721
+ 'Deployment targets the QA harness can run against (Epic #4326). A map keyed by environment name (e.g. `local`, `staging`), each carrying its own `baseUrl`, an optional per-environment sign-in seam, and an optional `allowWrites` gate. `signInSeam` is the union `{ urlTemplate }` (a dev impersonation route) or `{ skill }` (a skill id such as `stack/qa/acme-sso`, resolved against `.agents/skills/` then the consumer-writable `.agents/local/skills/` zone, and rejected loudly by resolveQaEnvironment when it resolves under neither); omit it entirely for a target with no sign-in seam. resolveQaEnvironment selects one environment per invocation by name or by raw-URL origin match against `baseUrl`; `allowWrites` defaults to true only for the `local` environment. Replaces the retired top-level single `signInSeam`.',
707
722
  // Inventory value: an illustrative two-environment map, not a resolvable
708
- // default. The QA harness is opt-in and every value here is
709
- // project-specific; the entry exists so `mandrel explain` can show the
710
- // expected shape.
723
+ // default. `staging` deliberately carries NO `signInSeam` that is the
724
+ // honest shape for a deployed target with no dev sign-in seam, and it
725
+ // shows the field is optional (Story #5135).
711
726
  default: {
712
727
  local: {
713
728
  baseUrl: 'http://localhost:3000',
@@ -715,7 +730,6 @@ const QA_ENVIRONMENTS_SCHEMA = {
715
730
  },
716
731
  staging: {
717
732
  baseUrl: 'https://staging.example.test',
718
- signInSeam: { skill: 'stack/qa/sign-in' },
719
733
  allowWrites: false,
720
734
  },
721
735
  },
@@ -727,7 +741,11 @@ const QA_ENVIRONMENTS_SCHEMA = {
727
741
  signInSeam: QA_SIGN_IN_SEAM_SCHEMA,
728
742
  allowWrites: { type: 'boolean' },
729
743
  },
730
- required: ['baseUrl', 'signInSeam'],
744
+ // `signInSeam` is OPTIONAL (Story #5135). An environment that resolves no
745
+ // seam is a state the QA workflows already branch on — they drive the
746
+ // unauthenticated surface and record the gap — so requiring it made an
747
+ // honestly seamless remote target undeclarable.
748
+ required: ['baseUrl'],
731
749
  additionalProperties: false,
732
750
  },
733
751
  };