@intentset/core 0.1.0 → 0.2.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.
package/src/types.ts CHANGED
@@ -296,8 +296,19 @@ export interface ImpactReport {
296
296
  ancestors: string[];
297
297
  }
298
298
 
299
- /** The versioned export envelope (integration contract; spec/export.schema.json). */
300
- export const EXPORT_CONTRACT = "intentset/export/0.1";
299
+ /**
300
+ * The versioned export envelope (spec/export.md; spec/export.schema.json). 0.2 is
301
+ * the first version a consumer may pin: 0.1 carried untyped report slots and
302
+ * restricted artifacts by default (ADR 0008).
303
+ */
304
+ export const EXPORT_CONTRACT = "intentset/export/0.2";
305
+
306
+ /** The contracts this implementation reads. A consumer rejects every other value (spec/export.md §5). */
307
+ export const SUPPORTED_EXPORT_CONTRACTS: readonly string[] = [EXPORT_CONTRACT];
308
+
309
+ /** The optional report sections, in the order they are written. An absent section means not supplied. */
310
+ export const EXPORT_REPORTS = ["evidence", "knowledge", "impact", "ownership"] as const;
311
+ export type ExportReportName = (typeof EXPORT_REPORTS)[number];
301
312
 
302
313
  export interface ExportArtifact {
303
314
  id: string;
@@ -311,10 +322,13 @@ export interface ExportArtifact {
311
322
  revision: number | null;
312
323
  path: string;
313
324
  sourceHash: string;
325
+ /** Null when there is none, or when the parent is withheld (and counted in `withheldLinks`). */
314
326
  parent: string | null;
315
327
  links: Partial<Record<Exclude<LinkKind, "parent">, string[]>>;
316
328
  /** Inverse edges, keyed by the authored kind, marked derived by living here. */
317
329
  derived: Partial<Record<LinkKind, string[]>>;
330
+ /** Link targets and sources left out because the artifact at the other end is withheld: authored, derived and parent. */
331
+ withheldLinks: number;
318
332
  availability: Availability | null;
319
333
  slice: SliceMeta | null;
320
334
  verification: VerificationMeta | null;
@@ -323,35 +337,211 @@ export interface ExportArtifact {
323
337
  body?: string;
324
338
  }
325
339
 
340
+ /** A run record as the evidence report carries it: spec/evidence.schema.json's record, unchanged. */
341
+ export interface ExportRunRecord {
342
+ evidenceId: string;
343
+ verificationId: string;
344
+ commit: string;
345
+ graphHash: string;
346
+ environment: string;
347
+ scope: { product: string; release: string };
348
+ tool: { name: string; version: string } | null;
349
+ reviewer: string | null;
350
+ startedAt: string;
351
+ finishedAt: string;
352
+ result: "pass" | "fail" | "skip" | "error";
353
+ uri: string;
354
+ rationale?: string;
355
+ extensions?: Record<string, unknown>;
356
+ }
357
+
358
+ /** Core §8 freshness, as the evidence check classifies it. Only current-pass is a pass. */
359
+ export const EXPORT_EVIDENCE_STATUSES = [
360
+ "current-pass",
361
+ "current-fail",
362
+ "stale",
363
+ "skip",
364
+ "error",
365
+ "missing",
366
+ "unresolved",
367
+ ] as const;
368
+ export type ExportEvidenceStatus = (typeof EXPORT_EVIDENCE_STATUSES)[number];
369
+
370
+ /** `reports.evidence`: every verification classified at the envelope's snapshot, and every claim's coverage. */
371
+ export interface EvidenceReportSection {
372
+ /** The snapshot the records were classified against: the envelope's own. */
373
+ commit: string | null;
374
+ graphHash: string;
375
+ /** The exact product and release assessed, or null when records of every scope were considered. */
376
+ scope: { product: string; release: string } | null;
377
+ /** Run records read, before classification. */
378
+ records: number;
379
+ /** One per verification artifact, sorted by ID. */
380
+ verifications: ExportVerificationEvidence[];
381
+ /** One per behavior, rule and scenario that is not retired, sorted by ID. */
382
+ claims: ExportClaimCoverage[];
383
+ }
384
+
385
+ export interface ExportVerificationEvidence {
386
+ id: string;
387
+ method: "automated" | "manual";
388
+ status: ExportEvidenceStatus;
389
+ /** Why the status is qualified, or what was set aside; null when nothing was. */
390
+ note: string | null;
391
+ /** The record that decided the status: the latest at the snapshot, else the latest in scope; null when none. */
392
+ latest: ExportRunRecord | null;
393
+ /** Results of the records at the snapshot, so a failure followed by a pass is still countable. */
394
+ atSnapshot: { pass: number; fail: number; skip: number; error: number };
395
+ /** In-scope records for this verification, at any snapshot. */
396
+ runs: number;
397
+ /** Records for this verification that named another product or release and were not considered. */
398
+ outOfScope: number;
399
+ }
400
+
401
+ export interface ExportClaimCoverage {
402
+ id: string;
403
+ type: "behavior" | "rule" | "scenario";
404
+ /** The claim's lifecycle status: an editorial claim, never a test result. */
405
+ lifecycle: Status;
406
+ /** True when the level asks for evidence (L3 and above) and the claim is not a draft. */
407
+ required: boolean;
408
+ /** At least one applicable verification names the claim. */
409
+ linked: boolean;
410
+ /** At least one applicable verification, and every one of them a current pass. */
411
+ verified: boolean;
412
+ /** Applicable verifications naming the claim, sorted. */
413
+ verifications: string[];
414
+ /** Verifications left out of that list because they are withheld. */
415
+ withheld: number;
416
+ }
417
+
418
+ /** `reports.knowledge`: the review status of every knowledge artifact (Core §9). */
419
+ export interface KnowledgeReportSection {
420
+ graphHash: string;
421
+ /** One per knowledge artifact, sorted by ID. */
422
+ artifacts: ExportKnowledgeReview[];
423
+ }
424
+
425
+ export interface ExportKnowledgeReview {
426
+ id: string;
427
+ lifecycle: Status;
428
+ /** current only while every source still has the hash it was reviewed against and a reviewer and time are named. */
429
+ status: "current" | "needs-review";
430
+ reviewer: string | null;
431
+ reviewedAt: string | null;
432
+ /** What a review must pin: the explained artifacts and the rules governing each explained behavior. Sorted. */
433
+ sources: string[];
434
+ /** Sources whose hash differs from the pin, or that are gone. Sorted. */
435
+ changed: string[];
436
+ /** Sources the review record does not pin. Sorted. */
437
+ missing: string[];
438
+ /** Entries left out of sources, changed and missing because they are withheld. */
439
+ withheld: number;
440
+ }
441
+
442
+ /** One hit in the impact report: the artifact and the path that reached it. Join to `artifacts` by ID. */
443
+ export interface ExportImpactHit {
444
+ id: string;
445
+ path: ImpactStep[];
446
+ }
447
+
448
+ export interface ExportImpactEntry {
449
+ start: string;
450
+ direct: ExportImpactHit[];
451
+ candidates: ExportImpactHit[];
452
+ context: ExportImpactHit[];
453
+ ancestors: string[];
454
+ /** Hits and ancestors left out because they, or a step on their path, are withheld. */
455
+ withheld: number;
456
+ }
457
+
458
+ /** `reports.impact`: Core §10 impact from every exported artifact. A start absent here was not computed. */
459
+ export interface ImpactReportSection {
460
+ graphHash: string;
461
+ /** Reachability marks an artifact for review; it is not proof that runtime behavior changed. */
462
+ note: string;
463
+ /** One per exported artifact, sorted by start. */
464
+ starts: ExportImpactEntry[];
465
+ }
466
+
467
+ /**
468
+ * Where a file falls (VSA §1, §3, §5): the region kinds of the architecture
469
+ * check, plus "test" for a test file, whose owner is the slice its claims
470
+ * match or null.
471
+ */
472
+ export const OWNERSHIP_REGIONS = [
473
+ "slice",
474
+ "composition",
475
+ "shared",
476
+ "infrastructure",
477
+ "resource",
478
+ "backend",
479
+ "unowned",
480
+ "test",
481
+ ] as const;
482
+ export type OwnershipRegion = (typeof OWNERSHIP_REGIONS)[number];
483
+
484
+ export interface OwnershipEntry {
485
+ path: string;
486
+ region: OwnershipRegion;
487
+ /** The slice ID for "slice" and "test", the resource ID for "resource", otherwise null. */
488
+ owner: string | null;
489
+ }
490
+
491
+ /** `reports.ownership`: every file the architecture check attributed, at the envelope's snapshot (L2 and above). */
492
+ export interface OwnershipReportSection {
493
+ commit: string | null;
494
+ graphHash: string;
495
+ /** Sorted by path. Files outside the source and backend roots that nothing claims are not listed. */
496
+ files: OwnershipEntry[];
497
+ /** Files left out because the slice that owns them is withheld. */
498
+ withheld: number;
499
+ }
500
+
501
+ export interface ExportReports {
502
+ evidence?: EvidenceReportSection;
503
+ knowledge?: KnowledgeReportSection;
504
+ impact?: ImpactReportSection;
505
+ ownership?: OwnershipReportSection;
506
+ }
507
+
326
508
  export interface ExportEnvelope {
327
509
  contract: typeof EXPORT_CONTRACT;
328
510
  spec: typeof SPEC_VERSION;
329
511
  generatedAt: string;
330
512
  /** Stable identity of the repository, from config (e.g. "intentset/intentset"). */
331
513
  repository: string;
514
+ /** Product artifact IDs in the export, sorted. */
332
515
  products: string[];
333
516
  source: {
334
517
  /** The commit the export describes, or null with a reason when none could be read. */
335
518
  commit: string | null;
336
519
  commitUnavailable?: string;
520
+ /** True when tracked files differed from the commit, so the commit alone does not describe what was read. */
521
+ uncommitted: boolean;
337
522
  };
338
- /** SHA-256 over the canonical graph (ADR 0005). */
523
+ /** SHA-256 over the canonical graph (ADR 0005), withheld artifacts included: it names the snapshot, not the projection. */
339
524
  graphHash: string;
340
525
  release: { product: string; label: string } | null;
341
526
  validation: {
342
527
  level: Level;
343
528
  scope: string[];
344
529
  status: "pass" | "fail";
530
+ /** Totals over the whole validation, withheld artifacts included, so the status is never flattered. */
345
531
  errors: number;
346
532
  warnings: number;
533
+ /** The diagnostics about exported artifacts; those about withheld ones are counted in `withholding`. */
347
534
  diagnostics: Diagnostic[];
348
535
  };
536
+ /** What the export leaves out, so a short export never reads as a complete one. */
537
+ withholding: {
538
+ /** The visibilities withheld: ["restricted"] by default, [] when restricted artifacts were asked for. */
539
+ visibilities: Visibility[];
540
+ artifacts: number;
541
+ diagnostics: number;
542
+ };
349
543
  registries: Registries;
350
544
  artifacts: ExportArtifact[];
351
545
  /** Optional report sections. Absent means "not supplied", never zero or pass. */
352
- reports?: {
353
- evidence?: unknown;
354
- knowledge?: unknown;
355
- impact?: unknown;
356
- };
546
+ reports: ExportReports;
357
547
  }