@besales/ops-framework 0.1.16 → 0.1.17

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.17
4
+
5
+ - Broadened the schema compatibility gate so it blocks any schema/foundation requirement that omits fields required by approved dependent requirements, even when the schema text is not written as an explicit closed list.
6
+ - Expanded the schema gate action to call out `person_aliases` or alias storage plus required `meetings.*` fields for track classification and speaker resolution.
7
+
3
8
  ## 0.1.16
4
9
 
5
10
  - Added a schema compatibility readiness gate that blocks planning when a closed/minimal schema requirement does not support dependent approved requirements such as speaker resolution, aliases and meeting track classification.
@@ -1126,14 +1126,15 @@ function addSchemaCompatibilityGate({ gates, sourceText, requirements }) {
1126
1126
  if (!schemaSupportsMeetingOperationalFields) {
1127
1127
  missing.push('meeting operational fields mentioned by sources, such as `series_id` and `asr_quality`');
1128
1128
  }
1129
- if (missing.length && schemaLooksClosed) {
1129
+ if (missing.length) {
1130
+ const schemaShape = schemaLooksClosed ? 'closed/minimal schema list' : 'schema/foundation contract';
1130
1131
  gates.push({
1131
1132
  id: 'schema-supports-derived-requirements',
1132
1133
  severity: 'critical',
1133
1134
  blocking: true,
1134
1135
  title: 'Schema requirement does not support dependent requirements',
1135
- issue: `Schema requirement ${schemaReq.id} is written as a closed/minimal schema list but omits ${missing.join(', ')}.`,
1136
- action: 'Update the schema requirement before WP planning: add the missing schema support, or explicitly state the alternative Phase 1 storage contract and defer the dependent behavior.',
1136
+ issue: `Schema requirement ${schemaReq.id} is written as a ${schemaShape} but omits ${missing.join(', ')}.`,
1137
+ action: 'Update the schema requirement before WP planning: add the missing schema support, or explicitly state the alternative Phase 1 storage contract and defer the dependent behavior. For meeting extraction this usually means `person_aliases` or documented alias storage plus `meetings.meeting_track`, `meetings.series_id`, `meetings.asr_quality`, `meetings.speaker_resolution_status` and `meetings.raw_speaker_labels` when those behaviors are approved.',
1137
1138
  });
1138
1139
  }
1139
1140
  }
@@ -593,6 +593,92 @@ describe('initiative framework', () => {
593
593
  });
594
594
  expect(synthesis.rewriteRequired).toBe(true);
595
595
  });
596
+
597
+ it('blocks planning when a non-closed schema foundation omits speaker and meeting fields', () => {
598
+ const root = makeProject();
599
+ const docsDir = path.join(root, 'docs', 'delivery-os');
600
+ fs.mkdirSync(docsDir, { recursive: true });
601
+ fs.writeFileSync(path.join(docsDir, '06-roadmap.md'), [
602
+ '# Phase 1',
603
+ '',
604
+ '- Migration 001b: person_aliases. Meeting fields: meeting_track, series_id, asr_quality, speaker_resolution_status, raw_speaker_labels.',
605
+ ].join('\n'));
606
+ createInitiative({
607
+ projectRoot: root,
608
+ initiativeId: 'delivery-os-mvp',
609
+ title: 'Delivery OS MVP',
610
+ });
611
+ initiativeIntake({
612
+ projectRoot: root,
613
+ initiativeId: 'delivery-os-mvp',
614
+ docsDir: 'docs/delivery-os',
615
+ phase: 'phase-1',
616
+ });
617
+ const initiativeDir = path.join(root, 'ops', 'agent-pipeline', 'initiatives', 'delivery-os-mvp');
618
+ fs.writeFileSync(path.join(initiativeDir, 'requirements-map.md'), [
619
+ '# Requirements Map',
620
+ '',
621
+ '## Requirement Details',
622
+ '',
623
+ '### REQ-002',
624
+ '',
625
+ '- Status: `approved`',
626
+ '- Source: `docs/delivery-os/04-data-model.md:1206`',
627
+ '- Source hash: `sha`',
628
+ '- Phase: `phase-1`',
629
+ '- Quality: `complete`',
630
+ '- Quality issue: (none)',
631
+ '- Work package: WP-001',
632
+ '- Acceptance: Schema includes approved Phase 1 entities plus attribution/access foundations: created_by, app.current_user_id, owner_id, entity_history, enforcement-deferred.',
633
+ '- Decision: `approve`',
634
+ '- Notes: Human-approved attribution update.',
635
+ '- Requirement: Minimal Phase 1 Schema And Attribution Foundations.',
636
+ '',
637
+ '### REQ-003',
638
+ '',
639
+ '- Status: `approved`',
640
+ '- Source: `docs/delivery-os/06-roadmap.md:10`',
641
+ '- Source hash: `sha`',
642
+ '- Phase: `phase-1`',
643
+ '- Quality: `complete`',
644
+ '- Quality issue: (none)',
645
+ '- Work package: WP-003',
646
+ '- Acceptance: Meetings are classified with meeting_track.',
647
+ '- Decision: `approve`',
648
+ '- Notes: (empty)',
649
+ '- Requirement: Phase 1 classification uses meeting_track for client/internal/tracker/advisor_network/investor/grant_funding.',
650
+ '',
651
+ '### REQ-004',
652
+ '',
653
+ '- Status: `approved`',
654
+ '- Source: `docs/delivery-os/13-meeting-extraction-profiles.md:240`',
655
+ '- Source hash: `sha`',
656
+ '- Phase: `phase-1`',
657
+ '- Quality: `complete`',
658
+ '- Quality issue: (none)',
659
+ '- Work package: WP-001, WP-003',
660
+ '- Acceptance: Speaker resolution stores raw speaker labels/aliases and speaker_resolution_status.',
661
+ '- Decision: `approve`',
662
+ '- Notes: (empty)',
663
+ '- Requirement: Phase 1 supports speaker identity resolution and alias storage.',
664
+ '',
665
+ ].join('\n'));
666
+
667
+ const synthesis = initiativeRequirementsSynthesis({
668
+ projectRoot: root,
669
+ initiativeId: 'delivery-os-mvp',
670
+ });
671
+
672
+ const schemaGate = synthesis.gates.find((gate) => gate.id === 'schema-supports-derived-requirements');
673
+ expect(schemaGate).toMatchObject({
674
+ severity: 'critical',
675
+ blocking: true,
676
+ });
677
+ expect(schemaGate.issue).toContain('schema/foundation contract');
678
+ expect(schemaGate.issue).toContain('person_aliases');
679
+ expect(schemaGate.issue).toContain('meeting_track');
680
+ expect(schemaGate.action).toContain('meetings.raw_speaker_labels');
681
+ });
596
682
  });
597
683
 
598
684
  function makeProject() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@besales/ops-framework",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "ops-agent": "bin/ops-agent.mjs"