@cejel/cejel 0.1.1 → 0.1.3

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.
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  mod
30
30
  ));
31
31
 
32
- // src/witan/external-findings.ts
32
+ // ../witan/src/external-findings.ts
33
33
  var EXTERNAL_FINDINGS_DISPLAY_LIMIT = 10;
34
34
  var SEVERITY_RANK = {
35
35
  critical: 0,
@@ -82,7 +82,7 @@ function collectExternalFindings(consumedSignals) {
82
82
  });
83
83
  }
84
84
 
85
- // src/witan/html.ts
85
+ // ../witan/src/html.ts
86
86
  function renderWitanHtmlReport(report) {
87
87
  const codeCriteria = criteriaByCategory(report, "code_trust");
88
88
  const processCriteria = criteriaByCategory(report, "process_trust");
@@ -403,7 +403,7 @@ a:hover { text-decoration: underline; text-underline-offset: 2px; }
403
403
  }
404
404
  `;
405
405
 
406
- // src/witan/badge.ts
406
+ // ../witan/src/badge.ts
407
407
  var VERDICT_COLOR = {
408
408
  Verified: "brightgreen",
409
409
  Conditional: "yellow",
@@ -470,7 +470,15 @@ function escapeXml(value) {
470
470
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
471
471
  }
472
472
 
473
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
473
+ // ../witan/src/claim-reality.ts
474
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
475
+ import { join } from "path";
476
+
477
+ // ../witan/src/leaderboard.ts
478
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
479
+ import { join as join6 } from "path";
480
+
481
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
474
482
  var external_exports = {};
475
483
  __export(external_exports, {
476
484
  BRAND: () => BRAND,
@@ -582,7 +590,7 @@ __export(external_exports, {
582
590
  void: () => voidType
583
591
  });
584
592
 
585
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
593
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
586
594
  var util;
587
595
  (function(util2) {
588
596
  util2.assertEqual = (_) => {
@@ -716,7 +724,7 @@ var getParsedType = (data) => {
716
724
  }
717
725
  };
718
726
 
719
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
727
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
720
728
  var ZodIssueCode = util.arrayToEnum([
721
729
  "invalid_type",
722
730
  "invalid_literal",
@@ -834,7 +842,7 @@ ZodError.create = (issues) => {
834
842
  return error;
835
843
  };
836
844
 
837
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
845
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
838
846
  var errorMap = (issue, _ctx) => {
839
847
  let message;
840
848
  switch (issue.code) {
@@ -937,7 +945,7 @@ var errorMap = (issue, _ctx) => {
937
945
  };
938
946
  var en_default = errorMap;
939
947
 
940
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
948
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
941
949
  var overrideErrorMap = en_default;
942
950
  function setErrorMap(map) {
943
951
  overrideErrorMap = map;
@@ -946,7 +954,7 @@ function getErrorMap() {
946
954
  return overrideErrorMap;
947
955
  }
948
956
 
949
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
957
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
950
958
  var makeIssue = (params) => {
951
959
  const { data, path, errorMaps, issueData } = params;
952
960
  const fullPath = [...path, ...issueData.path || []];
@@ -1056,14 +1064,14 @@ var isDirty = (x) => x.status === "dirty";
1056
1064
  var isValid = (x) => x.status === "valid";
1057
1065
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
1058
1066
 
1059
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
1067
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
1060
1068
  var errorUtil;
1061
1069
  (function(errorUtil2) {
1062
1070
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
1063
1071
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
1064
1072
  })(errorUtil || (errorUtil = {}));
1065
1073
 
1066
- // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
1074
+ // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
1067
1075
  var ParseInputLazyPath = class {
1068
1076
  constructor(parent, value, path, key) {
1069
1077
  this._cachedPath = [];
@@ -4511,10 +4519,853 @@ var coerce = {
4511
4519
  };
4512
4520
  var NEVER = INVALID;
4513
4521
 
4514
- // src/witan/schemas.ts
4522
+ // ../shared/src/types/attestation.ts
4523
+ var attestationOutcomeSchema = external_exports.enum([
4524
+ "ATTESTED_READY",
4525
+ "ATTESTED_WITH_GAPS",
4526
+ "NOT_READY",
4527
+ "REVOKED"
4528
+ ]);
4529
+ var attestationKindSchema = external_exports.enum(["OPERATOR_READINESS", "EXTERNAL_ASSESSOR_REFERENCE"]);
4530
+ var attestationEvidenceRefKindSchema = external_exports.enum([
4531
+ "runbook_path",
4532
+ "github_run_url",
4533
+ "vercel_deployment_id",
4534
+ "neon_query_evidence",
4535
+ "report_hash",
4536
+ "external_assessor_ref"
4537
+ ]);
4538
+ var attestationEvidenceRefSchema = external_exports.object({
4539
+ kind: attestationEvidenceRefKindSchema,
4540
+ /** Redacted reference string (path, URL, ID, or hash). Max 512 chars. */
4541
+ ref: external_exports.string().min(1).max(512),
4542
+ /** Optional one-line redacted description. */
4543
+ note: external_exports.string().max(280).optional()
4544
+ });
4545
+ var createAttestationInputSchema = external_exports.object({
4546
+ studioId: external_exports.string().uuid(),
4547
+ complianceProfileId: external_exports.string().uuid(),
4548
+ productId: external_exports.string().uuid().nullable().optional(),
4549
+ framework: external_exports.string().min(1).max(120),
4550
+ kind: attestationKindSchema,
4551
+ outcome: attestationOutcomeSchema,
4552
+ /** Redacted operator statement; no payloads. */
4553
+ statement: external_exports.string().min(1).max(4e3),
4554
+ evidenceRefs: external_exports.array(attestationEvidenceRefSchema).min(1),
4555
+ supersedesAttestationId: external_exports.string().uuid().nullable().optional(),
4556
+ metadata: external_exports.record(external_exports.unknown()).default({})
4557
+ });
4558
+
4559
+ // ../shared/src/types/standup-provisioning.ts
4560
+ var ScaffoldFileSchema = external_exports.object({
4561
+ path: external_exports.string().min(1),
4562
+ contents: external_exports.string()
4563
+ }).strict();
4564
+ var ScaffoldManifestSchema = external_exports.array(ScaffoldFileSchema).min(1);
4565
+ var RepoRefSchema = external_exports.object({
4566
+ studioId: external_exports.string().uuid(),
4567
+ owner: external_exports.string().min(1),
4568
+ // GitHub org/account that owns the repo
4569
+ name: external_exports.string().min(1),
4570
+ fullName: external_exports.string().min(1),
4571
+ // owner/name
4572
+ htmlUrl: external_exports.string().url(),
4573
+ defaultBranch: external_exports.string().min(1).default("main")
4574
+ }).strict();
4575
+ var ScopedTokenSchema = external_exports.object({
4576
+ token: external_exports.string().min(1),
4577
+ expiresAt: external_exports.string(),
4578
+ // ISO-8601
4579
+ scope: external_exports.string().min(1)
4580
+ // human-readable, e.g. "contents:write on owner/name"
4581
+ }).strict();
4582
+ var BranchProtectionStatusSchema = external_exports.object({
4583
+ protected: external_exports.boolean(),
4584
+ requiresPullRequestReview: external_exports.boolean(),
4585
+ requiredApprovingReviewCount: external_exports.number().int().nonnegative(),
4586
+ allowsForcePushes: external_exports.boolean(),
4587
+ allowsDeletions: external_exports.boolean()
4588
+ }).strict();
4589
+ var RenderParamsSchema = external_exports.object({
4590
+ productName: external_exports.string().min(1),
4591
+ slug: external_exports.string().min(1),
4592
+ vertical: external_exports.string().min(1)
4593
+ }).strict();
4594
+ var TemplateInputFieldSchema = external_exports.object({
4595
+ name: external_exports.string().min(1),
4596
+ label: external_exports.string().min(1),
4597
+ inputType: external_exports.enum(["text", "number", "date", "slug"]),
4598
+ required: external_exports.boolean().default(true),
4599
+ helperText: external_exports.string().min(1),
4600
+ example: external_exports.string().min(1),
4601
+ defaultValue: external_exports.string().optional()
4602
+ }).strict();
4603
+ var TemplateInputSchema = external_exports.object({
4604
+ fields: external_exports.array(TemplateInputFieldSchema).min(1)
4605
+ }).strict();
4606
+ var TemplateDescriptorSchema = external_exports.object({
4607
+ templateRef: external_exports.string().min(1),
4608
+ vertical: external_exports.string().min(1),
4609
+ description: external_exports.string().default(""),
4610
+ inputSchema: TemplateInputSchema.optional()
4611
+ }).strict();
4612
+ var StandupDryRunPlanSchema = external_exports.object({
4613
+ planOnly: external_exports.literal(true),
4614
+ planOnlyMessage: external_exports.string().min(1),
4615
+ product: external_exports.object({
4616
+ studioId: external_exports.string().min(1),
4617
+ productId: external_exports.string().min(1),
4618
+ name: external_exports.string().min(1),
4619
+ slug: external_exports.string().min(1),
4620
+ vertical: external_exports.string().min(1)
4621
+ }).strict(),
4622
+ targetRepo: external_exports.object({
4623
+ owner: external_exports.string().min(1),
4624
+ name: external_exports.string().min(1),
4625
+ fullName: external_exports.string().min(1),
4626
+ defaultBranch: external_exports.string().min(1),
4627
+ plannedState: external_exports.literal("would_create"),
4628
+ exists: external_exports.literal(false)
4629
+ }).strict(),
4630
+ template: TemplateDescriptorSchema,
4631
+ scaffold: external_exports.object({
4632
+ label: external_exports.literal("scaffold (template output)"),
4633
+ files: ScaffoldManifestSchema
4634
+ }).strict(),
4635
+ buildAgentSeed: external_exports.object({
4636
+ label: external_exports.literal("build-agent instructions (not yet run)"),
4637
+ instructions: external_exports.array(external_exports.string().min(1)).min(1),
4638
+ product: external_exports.object({
4639
+ name: external_exports.string().min(1),
4640
+ slug: external_exports.string().min(1),
4641
+ vertical: external_exports.string().min(1)
4642
+ }).strict(),
4643
+ repoFullName: external_exports.string().min(1)
4644
+ }).strict(),
4645
+ safetyEnvelope: external_exports.object({
4646
+ estimatedCostUsd: external_exports.number().finite().nonnegative(),
4647
+ costCapUsd: external_exports.number().finite().nonnegative(),
4648
+ networkPolicy: external_exports.object({
4649
+ mode: external_exports.literal("restricted"),
4650
+ allowedHosts: external_exports.array(external_exports.string().min(1)).min(1)
4651
+ }).strict(),
4652
+ scopedToken: external_exports.object({
4653
+ tokenMinted: external_exports.literal(false),
4654
+ scope: external_exports.string().min(1),
4655
+ ttlSeconds: external_exports.number().int().positive()
4656
+ }).strict()
4657
+ }).strict()
4658
+ }).strict();
4659
+ var ConstructionWorkflowArtifactKindSchema = external_exports.enum([
4660
+ "profile",
4661
+ "milestone_schedule",
4662
+ "risk_register",
4663
+ "submittal_register",
4664
+ "long_lead_log",
4665
+ "rfi_log",
4666
+ "responsibility_matrix"
4667
+ ]);
4668
+ var IsoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/);
4669
+ var ConstructionWorkflowTemplateDescriptorSchema = external_exports.object({
4670
+ templateRef: external_exports.string().min(1),
4671
+ workflowKind: external_exports.literal("construction_project"),
4672
+ templateKind: external_exports.literal("workflow_documents"),
4673
+ name: external_exports.string().min(1),
4674
+ description: external_exports.string().default(""),
4675
+ artifacts: external_exports.array(ConstructionWorkflowArtifactKindSchema).min(1),
4676
+ inputSchema: TemplateInputSchema
4677
+ }).strict();
4678
+ var ConstructionProjectSeedSchema = external_exports.object({
4679
+ projectName: external_exports.string().min(1).max(120),
4680
+ areaSqFt: external_exports.number().int().positive(),
4681
+ projectType: external_exports.string().min(1).max(120),
4682
+ buildingName: external_exports.string().min(1).max(160),
4683
+ ntpDate: IsoDateSchema,
4684
+ scheduleTargetDate: IsoDateSchema
4685
+ }).strict();
4686
+ var ConstructionMilestoneSchema = external_exports.object({
4687
+ id: external_exports.string().min(1),
4688
+ name: external_exports.string().min(1),
4689
+ targetDate: IsoDateSchema,
4690
+ status: external_exports.enum(["planned", "at_risk", "slipped", "complete"])
4691
+ }).strict();
4692
+ var ConstructionSubmittalSchema = external_exports.object({
4693
+ id: external_exports.string().min(1),
4694
+ item: external_exports.string().min(1),
4695
+ division: external_exports.string().min(1),
4696
+ needByDate: IsoDateSchema,
4697
+ status: external_exports.enum(["not_started", "open", "in_review", "approved", "done"])
4698
+ }).strict();
4699
+ var ConstructionRfiSchema = external_exports.object({
4700
+ id: external_exports.string().min(1),
4701
+ subject: external_exports.string().min(1),
4702
+ to: external_exports.string().min(1),
4703
+ status: external_exports.enum(["draft", "open", "answered", "closed"]),
4704
+ openedDate: IsoDateSchema
4705
+ }).strict();
4706
+ var ConstructionRiskSchema = external_exports.object({
4707
+ id: external_exports.string().min(1),
4708
+ risk: external_exports.string().min(1),
4709
+ rating: external_exports.enum(["low", "medium", "high"]),
4710
+ mitigation: external_exports.string().min(1),
4711
+ confidence: external_exports.number().min(0).max(1)
4712
+ }).strict();
4713
+ var ConstructionLongLeadItemSchema = external_exports.object({
4714
+ id: external_exports.string().min(1),
4715
+ item: external_exports.string().min(1),
4716
+ needByDate: IsoDateSchema,
4717
+ status: external_exports.enum(["tracking", "ordered", "received", "done"]),
4718
+ assumption: external_exports.string().min(1)
4719
+ }).strict();
4720
+ var ConstructionResponsibilitySchema = external_exports.object({
4721
+ id: external_exports.string().min(1),
4722
+ role: external_exports.string().min(1),
4723
+ owner: external_exports.string().min(1),
4724
+ responsibility: external_exports.string().min(1)
4725
+ }).strict();
4726
+ var ConstructionMarkdownArtifactSchema = external_exports.object({
4727
+ kind: ConstructionWorkflowArtifactKindSchema,
4728
+ path: external_exports.string().min(1),
4729
+ markdown: external_exports.string().min(1)
4730
+ }).strict();
4731
+ var ConstructionWorkflowArtifactSetSchema = external_exports.object({
4732
+ projectName: external_exports.string().min(1),
4733
+ generatedAt: external_exports.string().datetime(),
4734
+ assumptions: external_exports.array(external_exports.string().min(1)).default([]),
4735
+ needsPmData: external_exports.array(external_exports.string().min(1)).default([]),
4736
+ markdownArtifacts: external_exports.array(ConstructionMarkdownArtifactSchema).min(1),
4737
+ structured: external_exports.object({
4738
+ milestones: external_exports.array(ConstructionMilestoneSchema),
4739
+ submittals: external_exports.array(ConstructionSubmittalSchema),
4740
+ rfis: external_exports.array(ConstructionRfiSchema),
4741
+ risks: external_exports.array(ConstructionRiskSchema),
4742
+ longLeadItems: external_exports.array(ConstructionLongLeadItemSchema),
4743
+ responsibilities: external_exports.array(ConstructionResponsibilitySchema)
4744
+ }).strict()
4745
+ }).strict();
4746
+ var ConstructionWorkflowDryRunPlanSchema = external_exports.object({
4747
+ planOnly: external_exports.literal(true),
4748
+ planOnlyMessage: external_exports.string().min(1),
4749
+ product: external_exports.object({
4750
+ studioId: external_exports.string().min(1),
4751
+ productId: external_exports.string().min(1),
4752
+ name: external_exports.string().min(1),
4753
+ vertical: external_exports.string().min(1)
4754
+ }).strict(),
4755
+ template: ConstructionWorkflowTemplateDescriptorSchema,
4756
+ seed: ConstructionProjectSeedSchema,
4757
+ safetyEnvelope: external_exports.object({
4758
+ executor: external_exports.literal("benign_workflow_populator"),
4759
+ sandboxUsed: external_exports.literal(false),
4760
+ scopedTokenMinted: external_exports.literal(false),
4761
+ externalWritesAllowed: external_exports.literal(false),
4762
+ workspaceWriteMode: external_exports.literal("markdown_only")
4763
+ }).strict()
4764
+ }).strict();
4765
+
4766
+ // ../shared/src/types/construction-log-excel.ts
4767
+ var CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION = "construction-log-excel-v1";
4768
+ var ConstructionLogExcelSheetKeySchema = external_exports.enum([
4769
+ "submittals",
4770
+ "rfis",
4771
+ "riskRegister",
4772
+ "longLead",
4773
+ "responsibilityMatrix",
4774
+ "milestones"
4775
+ ]);
4776
+ var ConstructionLogExcelColumnSchema = external_exports.object({
4777
+ key: external_exports.string().min(1),
4778
+ header: external_exports.string().min(1),
4779
+ required: external_exports.boolean(),
4780
+ description: external_exports.string().min(1)
4781
+ }).strict().describe("Canonical column definition for Alfred construction log Excel round-trips.");
4782
+ var ConstructionLogExcelSheetSchema = external_exports.object({
4783
+ key: ConstructionLogExcelSheetKeySchema,
4784
+ sheetName: external_exports.string().min(1),
4785
+ description: external_exports.string().min(1),
4786
+ columns: external_exports.array(ConstructionLogExcelColumnSchema).min(1)
4787
+ }).strict().describe("Canonical worksheet definition for Alfred construction log Excel round-trips.");
4788
+ var ConstructionLogExcelWorkbookSchema = external_exports.object({
4789
+ schemaVersion: external_exports.literal(CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION),
4790
+ sheets: external_exports.record(ConstructionLogExcelSheetKeySchema, ConstructionLogExcelSheetSchema)
4791
+ }).strict().describe(
4792
+ "Canonical Alfred construction log Excel workbook schema shared by native output generation and export-upload ingestion."
4793
+ );
4794
+ var CONSTRUCTION_LOG_EXCEL_SHEETS = {
4795
+ submittals: {
4796
+ key: "submittals",
4797
+ sheetName: "Submittals",
4798
+ description: "Submittal register rows generated by Alfred or edited by the PM.",
4799
+ columns: [
4800
+ column("id", "ID", true, "Stable submittal identifier, for example SUB-001."),
4801
+ column("item", "Item", true, "Submittal item or package name."),
4802
+ column("division", "Division", true, "Spec division or trade grouping."),
4803
+ column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
4804
+ column("status", "Status", true, "One of not_started, open, in_review, approved, or done."),
4805
+ commonColumn("assumptionsNotes")
4806
+ ]
4807
+ },
4808
+ rfis: {
4809
+ key: "rfis",
4810
+ sheetName: "RFIs",
4811
+ description: "RFI log rows generated by Alfred or edited by the PM.",
4812
+ columns: [
4813
+ column("id", "ID", true, "Stable RFI identifier, for example RFI-001."),
4814
+ column("subject", "Subject", true, "RFI subject."),
4815
+ column("to", "To", true, "Responsible recipient or ball-in-court party."),
4816
+ column("status", "Status", true, "One of draft, open, answered, or closed."),
4817
+ column("openedDate", "Opened Date", true, "Date opened in YYYY-MM-DD format."),
4818
+ commonColumn("assumptionsNotes")
4819
+ ]
4820
+ },
4821
+ riskRegister: {
4822
+ key: "riskRegister",
4823
+ sheetName: "Risk Register",
4824
+ description: "Risk register rows generated by Alfred or edited by the PM.",
4825
+ columns: [
4826
+ column("id", "ID", true, "Stable risk identifier, for example RISK-001."),
4827
+ column("risk", "Risk", true, "Risk statement."),
4828
+ column("rating", "Rating", true, "One of low, medium, or high."),
4829
+ column("mitigation", "Mitigation", true, "Mitigation plan."),
4830
+ column("confidence", "Confidence", true, "Confidence score from 0 to 1."),
4831
+ commonColumn("assumptionsNotes")
4832
+ ]
4833
+ },
4834
+ longLead: {
4835
+ key: "longLead",
4836
+ sheetName: "Long-Lead",
4837
+ description: "Long-lead procurement rows generated by Alfred or edited by the PM.",
4838
+ columns: [
4839
+ column("id", "ID", true, "Stable long-lead identifier, for example LL-001."),
4840
+ column("item", "Item", true, "Long-lead item name."),
4841
+ column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
4842
+ column("status", "Status", true, "One of tracking, ordered, received, or done."),
4843
+ column("assumption", "Assumption", true, "Procurement assumption behind this row."),
4844
+ commonColumn("assumptionsNotes")
4845
+ ]
4846
+ },
4847
+ responsibilityMatrix: {
4848
+ key: "responsibilityMatrix",
4849
+ sheetName: "Responsibility Matrix",
4850
+ description: "Responsibility matrix rows generated by Alfred or edited by the PM.",
4851
+ columns: [
4852
+ column("id", "ID", true, "Stable responsibility identifier, for example RESP-001."),
4853
+ column("role", "Role", true, "Role or party."),
4854
+ column("owner", "Owner", true, "Named owner, or Needs PM input when unknown."),
4855
+ column("responsibility", "Responsibility", true, "Responsibility statement."),
4856
+ commonColumn("assumptionsNotes")
4857
+ ]
4858
+ },
4859
+ milestones: {
4860
+ key: "milestones",
4861
+ sheetName: "Milestones",
4862
+ description: "Milestone schedule rows used to generate the MS Project XML schedule.",
4863
+ columns: [
4864
+ column("id", "ID", true, "Stable milestone identifier, for example MS-001."),
4865
+ column("name", "Name", true, "Milestone or task name."),
4866
+ column("targetDate", "Target Date", true, "Target date in YYYY-MM-DD format."),
4867
+ column("status", "Status", true, "One of planned, at_risk, slipped, or complete."),
4868
+ column("predecessorId", "Predecessor ID", false, "Optional predecessor milestone ID."),
4869
+ commonColumn("assumptionsNotes")
4870
+ ]
4871
+ }
4872
+ };
4873
+ var CONSTRUCTION_LOG_EXCEL_WORKBOOK_SCHEMA = ConstructionLogExcelWorkbookSchema.parse({
4874
+ schemaVersion: CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION,
4875
+ sheets: CONSTRUCTION_LOG_EXCEL_SHEETS
4876
+ });
4877
+ function column(key, header, required, description) {
4878
+ return { key, header, required, description };
4879
+ }
4880
+ function commonColumn(key) {
4881
+ return column(
4882
+ key,
4883
+ "Assumptions / Notes",
4884
+ false,
4885
+ "Show-your-work note, including generated assumptions and PM-input gaps."
4886
+ );
4887
+ }
4888
+
4889
+ // ../shared/src/types/dev-task-dispatch.ts
4890
+ var CodingAgentExecutorSchema = external_exports.enum(["claude-code", "codex"]);
4891
+ var DevTaskDispatchRequestSchema = external_exports.object({
4892
+ studioId: external_exports.string().uuid(),
4893
+ productId: external_exports.string().uuid(),
4894
+ repo: RepoRefSchema,
4895
+ task: external_exports.string().min(1).max(2e4),
4896
+ executor: CodingAgentExecutorSchema
4897
+ }).strict();
4898
+ var DevTaskDispatchDryRunPlanSchema = external_exports.object({
4899
+ planOnly: external_exports.literal(true),
4900
+ planOnlyMessage: external_exports.string().min(1),
4901
+ targetRepo: RepoRefSchema,
4902
+ task: external_exports.string().min(1),
4903
+ executor: CodingAgentExecutorSchema,
4904
+ branchName: external_exports.string().min(1),
4905
+ safetyEnvelope: external_exports.object({
4906
+ estimatedCostUsd: external_exports.number().finite().nonnegative(),
4907
+ costCapUsd: external_exports.number().finite().nonnegative(),
4908
+ timeoutMs: external_exports.number().int().positive(),
4909
+ scopedToken: external_exports.object({
4910
+ tokenMinted: external_exports.literal(false),
4911
+ scope: external_exports.string().min(1),
4912
+ ttlSeconds: external_exports.number().int().positive()
4913
+ }).strict(),
4914
+ prOnly: external_exports.object({
4915
+ opensPullRequest: external_exports.literal(true),
4916
+ mergesPullRequest: external_exports.literal(false),
4917
+ pushesMain: external_exports.literal(false),
4918
+ deploys: external_exports.literal(false)
4919
+ }).strict()
4920
+ }).strict()
4921
+ }).strict();
4922
+ var CodingAgentRunInputSchema = external_exports.object({
4923
+ executor: CodingAgentExecutorSchema,
4924
+ repo: RepoRefSchema,
4925
+ task: external_exports.string().min(1),
4926
+ scopedToken: ScopedTokenSchema,
4927
+ branchName: external_exports.string().min(1),
4928
+ costCapUsd: external_exports.number().finite().nonnegative(),
4929
+ timeoutMs: external_exports.number().int().positive()
4930
+ }).strict();
4931
+ var CodingAgentRunResultSchema = external_exports.discriminatedUnion("status", [
4932
+ external_exports.object({
4933
+ status: external_exports.literal("succeeded"),
4934
+ prUrl: external_exports.string().url(),
4935
+ summary: external_exports.string().min(1),
4936
+ costUsd: external_exports.number().finite().nonnegative(),
4937
+ /**
4938
+ * The exact commit sha the PR branch was pushed at when it opened —
4939
+ * captured server-side (see server-dispatch-backend.ts) right after a
4940
+ * successful run, before the workspace is torn down. Lets the Maeve
4941
+ * in-flight-fix detector (maeve-in-flight-pr-fix-lesson.ts) key off the
4942
+ * real PR-open head instead of falling back to timestamp matching.
4943
+ */
4944
+ openedHeadSha: external_exports.string().min(1).optional()
4945
+ }).strict(),
4946
+ external_exports.object({
4947
+ status: external_exports.literal("failed"),
4948
+ summary: external_exports.string().min(1),
4949
+ reason: external_exports.string().min(1),
4950
+ costUsd: external_exports.number().finite().nonnegative().optional()
4951
+ }).strict()
4952
+ ]);
4953
+ var DevTaskOutcomeSchema = external_exports.enum(["ci_passed", "pr_merged", "ci_failed"]);
4954
+ var SecurityFindingClassSchema = external_exports.enum(["authz", "csrf", "injection", "secrets", "ssrf"]);
4955
+ var RecordDevTaskOutcomeInputSchema = external_exports.object({
4956
+ product: external_exports.string().min(1).max(120),
4957
+ repo: external_exports.string().min(1).max(240),
4958
+ prUrl: external_exports.string().url(),
4959
+ outcome: DevTaskOutcomeSchema,
4960
+ task: external_exports.string().min(1).max(2e4).optional(),
4961
+ executor: CodingAgentExecutorSchema.optional(),
4962
+ occurredAt: external_exports.string().datetime().optional(),
4963
+ maeveLessonStatement: external_exports.string().min(1).max(1e3).optional(),
4964
+ maeveLessonTags: external_exports.array(external_exports.string().min(1).max(120)).optional(),
4965
+ /** Security metadata — enriches the Maeve lesson with class/pattern, never raw vulnerable detail. */
4966
+ findingClass: SecurityFindingClassSchema.optional(),
4967
+ ruleId: external_exports.string().min(1).max(120).optional(),
4968
+ signalSource: external_exports.string().min(1).max(240).optional()
4969
+ }).strict();
4970
+
4971
+ // ../shared/src/schemas/standup-plan.ts
4972
+ var StandupRequestSchema = external_exports.object({
4973
+ productName: external_exports.string().min(1).max(80),
4974
+ slug: external_exports.string().min(1).optional(),
4975
+ vertical: external_exports.string().min(1).max(80),
4976
+ repoTarget: external_exports.string().min(1).default("barg-labs"),
4977
+ repoName: external_exports.string().min(1).optional(),
4978
+ templateRef: external_exports.string().min(1).optional(),
4979
+ scopeNotes: external_exports.string().max(2e3).optional()
4980
+ }).strict();
4981
+ var StandupPlanSchema = external_exports.object({
4982
+ productName: external_exports.string().min(1).max(80),
4983
+ slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
4984
+ vertical: external_exports.string().min(1).max(80),
4985
+ templateRef: external_exports.string().min(1),
4986
+ repoTarget: external_exports.string().min(1),
4987
+ repoName: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
4988
+ fileManifest: external_exports.array(external_exports.string().min(1)).min(1),
4989
+ credentialScope: external_exports.string().min(1),
4990
+ estimatedCostUsd: external_exports.number().nonnegative(),
4991
+ steps: external_exports.array(external_exports.string().min(1)).min(1),
4992
+ dryRun: external_exports.literal(true)
4993
+ }).strict();
4994
+
4995
+ // ../shared/src/types/coordinator-prompt.ts
4996
+ var CoordinatorPromptContextBlockSchema = external_exports.object({
4997
+ title: external_exports.string().min(1).max(120),
4998
+ body: external_exports.string().min(1).max(6e3),
4999
+ source: external_exports.string().max(500).optional()
5000
+ });
5001
+ var CoordinatorPromptInputPayloadSchema = external_exports.object({
5002
+ objective: external_exports.string().min(1).max(4e3),
5003
+ productId: external_exports.string().min(1),
5004
+ context: external_exports.array(CoordinatorPromptContextBlockSchema).min(1).max(20),
5005
+ escalationHints: external_exports.array(external_exports.string().min(1).max(500)).max(10).optional()
5006
+ });
5007
+ var CoordinatorPromptTokensUsedSchema = external_exports.object({
5008
+ input: external_exports.number().int().nonnegative(),
5009
+ output: external_exports.number().int().nonnegative(),
5010
+ total: external_exports.number().int().nonnegative(),
5011
+ costCents: external_exports.number().nonnegative()
5012
+ });
5013
+ var CoordinatorPromptSchema = external_exports.object({
5014
+ id: external_exports.string().uuid(),
5015
+ studioId: external_exports.string().min(1),
5016
+ productId: external_exports.string().min(1),
5017
+ draftedAt: external_exports.coerce.date(),
5018
+ inputPayload: CoordinatorPromptInputPayloadSchema,
5019
+ markdown: external_exports.string().min(1),
5020
+ metadata: external_exports.object({
5021
+ tokensUsed: CoordinatorPromptTokensUsedSchema.optional(),
5022
+ model: external_exports.string().optional(),
5023
+ templateVersion: external_exports.string().optional()
5024
+ }).catchall(external_exports.unknown()).optional()
5025
+ });
5026
+ var CreateCoordinatorPromptInputSchema = external_exports.object({
5027
+ productId: external_exports.string().min(1),
5028
+ inputPayload: CoordinatorPromptInputPayloadSchema,
5029
+ markdown: external_exports.string().min(1),
5030
+ metadata: external_exports.record(external_exports.unknown()).optional(),
5031
+ draftedAt: external_exports.coerce.date().optional()
5032
+ });
5033
+ var ListCoordinatorPromptsInputSchema = external_exports.object({
5034
+ productId: external_exports.string().min(1).optional(),
5035
+ since: external_exports.coerce.date().optional()
5036
+ });
5037
+
5038
+ // ../shared/src/schemas/inbox-triage.ts
5039
+ var InboxTriageClassificationSchema = external_exports.enum([
5040
+ "needs_reply",
5041
+ "fyi",
5042
+ "waiting",
5043
+ "escalate"
5044
+ ]);
5045
+ var InboxTriageLegacyUrgencySchema = external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]);
5046
+ var InboxTriageThreadSchema = external_exports.object({
5047
+ id: external_exports.string().min(1),
5048
+ subject: external_exports.string().min(1),
5049
+ from: external_exports.string(),
5050
+ to: external_exports.string(),
5051
+ snippet: external_exports.string(),
5052
+ labels: external_exports.array(external_exports.string()),
5053
+ unread: external_exports.boolean(),
5054
+ needsReply: external_exports.boolean(),
5055
+ updatedAt: external_exports.string().min(1),
5056
+ url: external_exports.string().min(1),
5057
+ messageCount: external_exports.number().int().nonnegative()
5058
+ });
5059
+ var InboxTriageResultSchema = external_exports.object({
5060
+ threadId: external_exports.string().min(1),
5061
+ classification: InboxTriageClassificationSchema,
5062
+ confidence: external_exports.number().min(0).max(1),
5063
+ reason: external_exports.string(),
5064
+ labelName: external_exports.string(),
5065
+ applied: external_exports.boolean(),
5066
+ error: external_exports.string().optional()
5067
+ });
5068
+ var TriageInboxUsageSchema = external_exports.object({
5069
+ input_tokens: external_exports.number().int().nonnegative(),
5070
+ output_tokens: external_exports.number().int().nonnegative(),
5071
+ cached_tokens: external_exports.number().int().nonnegative().optional(),
5072
+ cost_cents: external_exports.number().nonnegative()
5073
+ });
5074
+ var TriageInboxResultSchema = external_exports.object({
5075
+ productId: external_exports.string().min(1),
5076
+ results: external_exports.array(InboxTriageResultSchema),
5077
+ usage: TriageInboxUsageSchema.optional()
5078
+ });
5079
+
5080
+ // ../shared/src/schemas/inference-usage.ts
5081
+ var InferenceUsageSurfaceSchema = external_exports.string().min(1).max(80).regex(/^[a-z][a-z0-9_-]*$/);
5082
+ var RecordInferenceUsageInputSchema = external_exports.object({
5083
+ product: external_exports.string().min(1).optional(),
5084
+ surface: InferenceUsageSurfaceSchema,
5085
+ model: external_exports.string().min(1).max(120),
5086
+ inputTokens: external_exports.number().int().nonnegative(),
5087
+ outputTokens: external_exports.number().int().nonnegative(),
5088
+ cachedTokens: external_exports.number().int().nonnegative().default(0),
5089
+ costCents: external_exports.number().nonnegative(),
5090
+ timestamp: external_exports.coerce.date().optional()
5091
+ });
5092
+ var InferenceUsageBreakdownQuerySchema = external_exports.object({
5093
+ from: external_exports.coerce.date(),
5094
+ to: external_exports.coerce.date()
5095
+ });
5096
+ var InferenceUsageGroupSchema = external_exports.object({
5097
+ calls: external_exports.number().int().nonnegative(),
5098
+ costCents: external_exports.number().nonnegative(),
5099
+ inputTokens: external_exports.number().int().nonnegative(),
5100
+ outputTokens: external_exports.number().int().nonnegative(),
5101
+ cachedTokens: external_exports.number().int().nonnegative()
5102
+ });
5103
+ var InferenceUsageBreakdownSchema = external_exports.object({
5104
+ from: external_exports.string().datetime(),
5105
+ to: external_exports.string().datetime(),
5106
+ totals: InferenceUsageGroupSchema,
5107
+ bySurface: external_exports.array(InferenceUsageGroupSchema.extend({ surface: InferenceUsageSurfaceSchema })),
5108
+ byModel: external_exports.array(InferenceUsageGroupSchema.extend({ model: external_exports.string().min(1) }))
5109
+ });
5110
+
5111
+ // ../shared/src/schemas/product-health.ts
5112
+ var DEFAULT_PRODUCT_HEALTH_INTERVAL_SECONDS = 24 * 60 * 60;
5113
+ var ISO_DATE_STRING = external_exports.string().datetime({ offset: true }).describe("ISO-8601 timestamp with timezone offset.");
5114
+ var ProductHealthStatusSchema = external_exports.enum(["healthy", "degraded", "halted"]);
5115
+ var ProductHealthDetailsSchema = external_exports.record(external_exports.unknown()).superRefine((details, ctx) => {
5116
+ const credentialPath = findCredentialLikePath(details);
5117
+ if (!credentialPath) return;
5118
+ ctx.addIssue({
5119
+ code: external_exports.ZodIssueCode.custom,
5120
+ message: `Product health details must not contain credentials (${credentialPath}).`
5121
+ });
5122
+ });
5123
+ var ProductHealthReportInputSchema = external_exports.object({
5124
+ productId: external_exports.string().min(1).max(120),
5125
+ status: ProductHealthStatusSchema,
5126
+ lastActivityAt: ISO_DATE_STRING,
5127
+ summary: external_exports.string().min(1).max(1e3),
5128
+ details: ProductHealthDetailsSchema.optional(),
5129
+ reportedAt: ISO_DATE_STRING,
5130
+ expectedIntervalSeconds: external_exports.number().int().positive().optional()
5131
+ });
5132
+ var StoredProductHealthReportSchema = ProductHealthReportInputSchema.extend({
5133
+ expectedIntervalSeconds: external_exports.number().int().positive()
5134
+ });
5135
+ var ProductLivenessStateSchema = external_exports.enum([
5136
+ "healthy",
5137
+ "degraded",
5138
+ "halted",
5139
+ "stale",
5140
+ "unknown"
5141
+ ]);
5142
+ var ProductLivenessSnapshotEntrySchema = external_exports.object({
5143
+ productId: external_exports.string().min(1),
5144
+ state: ProductLivenessStateSchema,
5145
+ flagged: external_exports.boolean(),
5146
+ status: ProductHealthStatusSchema.optional(),
5147
+ lastActivityAt: ISO_DATE_STRING.optional(),
5148
+ reportedAt: ISO_DATE_STRING.optional(),
5149
+ expectedIntervalSeconds: external_exports.number().int().positive(),
5150
+ ageSeconds: external_exports.number().int().nonnegative().nullable(),
5151
+ summary: external_exports.string()
5152
+ });
5153
+ function findCredentialLikePath(value, path = []) {
5154
+ if (!value || typeof value !== "object") return null;
5155
+ if (Array.isArray(value)) {
5156
+ for (const [index, item] of value.entries()) {
5157
+ const match = findCredentialLikePath(item, [...path, String(index)]);
5158
+ if (match) return match;
5159
+ }
5160
+ return null;
5161
+ }
5162
+ for (const [key, nested] of Object.entries(value)) {
5163
+ const nextPath = [...path, key];
5164
+ if (/(?:secret|token|password|credential|api[-_]?key|private[-_]?key)/i.test(key)) {
5165
+ return nextPath.join(".");
5166
+ }
5167
+ const match = findCredentialLikePath(nested, nextPath);
5168
+ if (match) return match;
5169
+ }
5170
+ return null;
5171
+ }
5172
+
5173
+ // ../shared/src/schemas/interaction-trace.ts
5174
+ var InteractionTraceVerificationSignalSchema = external_exports.enum([
5175
+ "no_signal",
5176
+ "human_accepted_output",
5177
+ "human_rejected_output",
5178
+ "ci_pr_succeeded",
5179
+ "ci_pr_failed",
5180
+ "brief_accepted",
5181
+ "brief_rejected",
5182
+ "standup_completed",
5183
+ "standup_failed"
5184
+ ]);
5185
+ var InteractionTraceVerificationSchema = external_exports.object({
5186
+ success: external_exports.boolean(),
5187
+ signal: InteractionTraceVerificationSignalSchema,
5188
+ confidence: external_exports.number().min(0).max(1),
5189
+ reason: external_exports.string().min(1).max(1e3)
5190
+ });
5191
+ var InteractionTraceActorSchema = external_exports.object({
5192
+ type: external_exports.enum(["human", "agent", "system"]),
5193
+ id: external_exports.string().min(1).max(200),
5194
+ name: external_exports.string().min(1).max(200).optional()
5195
+ });
5196
+ var RecordInteractionTraceInputSchema = external_exports.object({
5197
+ product: external_exports.string().min(1).max(120),
5198
+ intent: external_exports.string().min(1).max(500),
5199
+ actionSummary: external_exports.string().min(1).max(4e3),
5200
+ outcomeSummary: external_exports.string().min(1).max(4e3),
5201
+ model: external_exports.string().min(1).max(200).nullable().optional(),
5202
+ actor: InteractionTraceActorSchema,
5203
+ occurredAt: external_exports.string().datetime().optional(),
5204
+ verification: InteractionTraceVerificationSchema.optional(),
5205
+ metadata: external_exports.record(external_exports.unknown()).optional()
5206
+ });
5207
+ var StoredInteractionTraceSchema = RecordInteractionTraceInputSchema.extend({
5208
+ id: external_exports.string().uuid(),
5209
+ occurredAt: external_exports.string().datetime(),
5210
+ createdAt: external_exports.string().datetime(),
5211
+ verification: InteractionTraceVerificationSchema
5212
+ });
5213
+ var InteractionTraceQualityScoreSchema = external_exports.number().min(0).max(1);
5214
+ var RetrieveRelevantTracesQuerySchema = external_exports.object({
5215
+ product: external_exports.string().min(1).max(120),
5216
+ intent: external_exports.string().min(1).max(500),
5217
+ limit: external_exports.number().int().positive().max(10).optional()
5218
+ });
5219
+ var RetrievedInteractionTraceSchema = StoredInteractionTraceSchema.extend({
5220
+ score: external_exports.number().min(0).max(1),
5221
+ qualityScore: InteractionTraceQualityScoreSchema
5222
+ });
5223
+
5224
+ // ../shared/src/schemas/maeve-lesson.ts
5225
+ var MaeveLessonStatusSchema = external_exports.enum(["candidate", "verified", "retired"]);
5226
+ var MaeveLessonEvidenceSchema = external_exports.object({
5227
+ source: external_exports.enum(["interaction_trace", "artifact"]),
5228
+ traceId: external_exports.string().uuid().optional(),
5229
+ artifact: external_exports.string().min(1).max(1e3).optional(),
5230
+ summary: external_exports.string().min(1).max(1e3),
5231
+ hash: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/)
5232
+ });
5233
+ var MaeveLessonSchema = external_exports.object({
5234
+ id: external_exports.string().uuid(),
5235
+ product: external_exports.string().min(1).max(120),
5236
+ statement: external_exports.string().min(1).max(1e3),
5237
+ scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5238
+ tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5239
+ evidence: external_exports.array(MaeveLessonEvidenceSchema),
5240
+ status: MaeveLessonStatusSchema,
5241
+ createdAt: external_exports.string().datetime(),
5242
+ lastSeenAt: external_exports.string().datetime()
5243
+ });
5244
+ var CreateMaeveLessonInputSchema = external_exports.object({
5245
+ product: external_exports.string().min(1).max(120),
5246
+ statement: external_exports.string().min(1).max(1e3),
5247
+ scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5248
+ tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5249
+ evidence: external_exports.array(MaeveLessonEvidenceSchema).default([]),
5250
+ status: MaeveLessonStatusSchema.default("candidate"),
5251
+ lastSeenAt: external_exports.string().datetime().optional()
5252
+ });
5253
+ var PromoteMaeveLessonInputSchema = external_exports.object({
5254
+ id: external_exports.string().uuid(),
5255
+ status: MaeveLessonStatusSchema,
5256
+ appendEvidence: external_exports.array(MaeveLessonEvidenceSchema).optional()
5257
+ });
5258
+ var RecallMaeveLessonsQuerySchema = external_exports.object({
5259
+ product: external_exports.string().min(1).max(120).optional(),
5260
+ taskType: external_exports.string().min(1).max(120).optional(),
5261
+ tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5262
+ limit: external_exports.number().int().positive().max(10).default(5),
5263
+ /**
5264
+ * Free-text query for semantic (pgvector cosine) recall. When set and an
5265
+ * EmbeddingProvider is configured, recallMaeveLessons embeds this text and
5266
+ * retrieves by cosine similarity, with exact-tag matches as a boost.
5267
+ * Falls back to exact-class matching when the provider is NoOp.
5268
+ */
5269
+ semanticQuery: external_exports.string().min(1).max(500).optional()
5270
+ });
5271
+ var MaeveLessonSeedAnchorSchema = external_exports.object({
5272
+ commit: external_exports.string().regex(/^[0-9a-f]{40}$/i, "commit must be a full 40-character git SHA"),
5273
+ pr: external_exports.number().int().positive().nullable(),
5274
+ summary: external_exports.string().min(1).max(1e3)
5275
+ });
5276
+ var MaeveLessonSeedSchema = external_exports.object({
5277
+ statement: external_exports.string().min(1).max(1e3),
5278
+ scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5279
+ tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5280
+ anchors: external_exports.array(MaeveLessonSeedAnchorSchema).min(1),
5281
+ lastSeenAt: external_exports.string().datetime()
5282
+ });
5283
+ var ReviewFindingSeveritySchema = external_exports.enum(["critical", "high", "medium", "low"]);
5284
+ var ReviewFindingLessonInputSchema = external_exports.object({
5285
+ studioId: external_exports.string().min(1),
5286
+ findingStudioId: external_exports.string().min(1),
5287
+ product: external_exports.string().min(1).max(120),
5288
+ repository: external_exports.string().min(1).max(240),
5289
+ pullRequestNumber: external_exports.number().int().positive(),
5290
+ findingText: external_exports.string().min(1).max(4e3),
5291
+ severity: ReviewFindingSeveritySchema,
5292
+ reviewer: external_exports.string().min(1).max(120),
5293
+ remediatingCommitSha: external_exports.string().min(4).max(64),
5294
+ /** The durable, reusable rule distilled from the finding — NOT the finding text verbatim. */
5295
+ lessonStatement: external_exports.string().min(1).max(1e3),
5296
+ scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5297
+ tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
5298
+ occurredAt: external_exports.string().datetime()
5299
+ });
5300
+
5301
+ // ../shared/src/schemas/operator-trace.ts
5302
+ var TRACE_ACTORS = [
5303
+ "human",
5304
+ "cowork",
5305
+ "claude-code",
5306
+ "codex",
5307
+ "goal-runner",
5308
+ "ci"
5309
+ ];
5310
+ var TraceActorSchema = external_exports.enum(TRACE_ACTORS);
5311
+ var TRACE_SOURCES = [
5312
+ "shell",
5313
+ "cowork",
5314
+ "claude-code",
5315
+ "codex",
5316
+ "goal-runner",
5317
+ "github"
5318
+ ];
5319
+ var TraceSourceSchema = external_exports.enum(TRACE_SOURCES);
5320
+ var TraceProvenanceSchema = external_exports.object({
5321
+ source: TraceSourceSchema,
5322
+ /** Absolute path of the source file/dir, or the gh query for CI events. */
5323
+ path: external_exports.string().min(1).max(1e3),
5324
+ /** Line number, session id, or PR number locating the row inside the source. */
5325
+ locator: external_exports.string().min(1).max(200).optional()
5326
+ });
5327
+ var TraceRecordSchema = external_exports.object({
5328
+ t: external_exports.string().datetime(),
5329
+ actor: TraceActorSchema,
5330
+ action: external_exports.string().min(1).max(2e3),
5331
+ target: external_exports.string().max(1e3).default(""),
5332
+ outcome: external_exports.string().max(2e3).default(""),
5333
+ product: external_exports.string().min(1).max(120).optional(),
5334
+ provenance: TraceProvenanceSchema
5335
+ });
5336
+ var ShellRedactionSchema = external_exports.enum(["none", "secret", "unclassified"]);
5337
+ var ShellTraceEntrySchema = external_exports.object({
5338
+ ts: external_exports.string().datetime(),
5339
+ cwd: external_exports.string().min(1).max(1e3),
5340
+ command: external_exports.string().min(1).max(4e3),
5341
+ exitCode: external_exports.number().int(),
5342
+ shellSessionId: external_exports.string().min(1).max(200),
5343
+ redaction: ShellRedactionSchema
5344
+ });
5345
+ var TraceSourceReportSchema = external_exports.discriminatedUnion("status", [
5346
+ external_exports.object({
5347
+ status: external_exports.literal("ok"),
5348
+ source: TraceSourceSchema,
5349
+ recordCount: external_exports.number().int().nonnegative(),
5350
+ /** Files/entries present but skipped (unparseable, filtered) — named, not silent. */
5351
+ skipped: external_exports.array(external_exports.string().min(1).max(500)).default([])
5352
+ }),
5353
+ external_exports.object({
5354
+ status: external_exports.literal("dark"),
5355
+ source: TraceSourceSchema,
5356
+ reason: external_exports.string().min(1).max(500)
5357
+ })
5358
+ ]);
5359
+ var OperatorTimelineSchema = external_exports.object({
5360
+ records: external_exports.array(TraceRecordSchema),
5361
+ sources: external_exports.array(TraceSourceReportSchema)
5362
+ });
5363
+
5364
+ // ../shared/src/schemas/witan.ts
4515
5365
  var WITAN_RUBRIC_VERSION_V1 = "witan-rubric-v1-2026-06-24";
4516
5366
  var WITAN_RUBRIC_VERSION_V2 = "witan-rubric-v2-2026-07-12";
4517
- var WITAN_RUBRIC_VERSION = WITAN_RUBRIC_VERSION_V2;
5367
+ var WITAN_RUBRIC_VERSION_V3 = "witan-rubric-v3-2026-07-13";
5368
+ var WITAN_RUBRIC_VERSION = WITAN_RUBRIC_VERSION_V3;
4518
5369
  var WITAN_TRADING_RUBRIC_VERSION_V0 = "witan-trading-rubric-v0-2026-07-01";
4519
5370
  var WITAN_CRITERION_IDS = [
4520
5371
  "A1",
@@ -4540,9 +5391,11 @@ var WITAN_TRADING_RUBRIC_V0_CRITERION_IDS = [
4540
5391
  "audit-completeness",
4541
5392
  "claim-reality"
4542
5393
  ];
5394
+ var WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS = ["quant-integrity"];
4543
5395
  var WitanCriterionIdSchema = external_exports.enum([
4544
5396
  ...WITAN_CRITERION_IDS,
4545
- ...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS
5397
+ ...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS,
5398
+ ...WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS
4546
5399
  ]);
4547
5400
  var WitanTradingCriterionIdSchema = external_exports.enum(WITAN_TRADING_RUBRIC_V0_CRITERION_IDS);
4548
5401
  var WitanCriterionCategorySchema = external_exports.enum([
@@ -4584,6 +5437,7 @@ var WITAN_REPO_ARCHETYPES = [
4584
5437
  "monorepo",
4585
5438
  "docs_only",
4586
5439
  "binary_only",
5440
+ "unrecognised_ecosystem",
4587
5441
  "empty"
4588
5442
  ];
4589
5443
  var WitanRepoArchetypeSchema = external_exports.enum(WITAN_REPO_ARCHETYPES);
@@ -4592,7 +5446,10 @@ var WitanEvidencePointerSchema = external_exports.object({
4592
5446
  label: external_exports.string().min(1).max(180),
4593
5447
  url: external_exports.string().url().optional(),
4594
5448
  path: external_exports.string().min(1).max(700).optional(),
4595
- line: external_exports.number().int().positive().optional(),
5449
+ // Explicit null means the finding is file-scoped and no real match position was measured —
5450
+ // never a fabricated line (e.g. `1`) standing in for a position the detector never found
5451
+ // (goal_cejel_a2_one_notion_of_production_code_2026-07-13).
5452
+ line: external_exports.number().int().positive().nullable().optional(),
4596
5453
  contentHash: external_exports.string().min(8).max(160).optional(),
4597
5454
  capturedAt: external_exports.string().datetime({ offset: true }).optional()
4598
5455
  }).strict().refine((value) => Boolean(value.url ?? value.path ?? value.contentHash), {
@@ -4697,91 +5554,1144 @@ var WitanReportSchema = external_exports.object({
4697
5554
  categoryScores: external_exports.record(external_exports.string(), external_exports.number().min(0).max(4)).optional(),
4698
5555
  // Repo-archetype metadata (see WitanRepoArchetypeSchema above). Both fields are omitted for
4699
5556
  // callers that don't classify an archetype (e.g. the trading rubric). insufficientSourceReason
4700
- // is present only for the non-source archetypes ('docs_only' | 'binary_only' | 'empty') — its
4701
- // presence is what presentation layers (badge/terminal/verdict) key off to show an explicit
4702
- // insufficient-source verdict instead of a confident numeric score.
5557
+ // is present only for the non-source archetypes ('docs_only' | 'binary_only' |
5558
+ // 'unrecognised_ecosystem' | 'empty') — its presence is what presentation layers
5559
+ // (badge/terminal/verdict) key off to show an explicit insufficient-source verdict instead of
5560
+ // a confident numeric score.
4703
5561
  archetype: WitanRepoArchetypeSchema.optional(),
4704
5562
  insufficientSourceReason: external_exports.string().min(1).max(2e3).optional()
4705
5563
  }).strict();
4706
5564
 
4707
- // src/witan/repo-signals.ts
4708
- import { execFileSync } from "child_process";
4709
- import { createHash } from "crypto";
4710
- import { readFileSync, readdirSync, realpathSync, statSync } from "fs";
4711
- import { basename, join, relative, resolve, sep } from "path";
5565
+ // ../shared/src/schemas/work-item.ts
5566
+ var WorkItemTypeSchema = external_exports.enum(["feature", "bug"]);
5567
+ var WorkItemPrioritySchema = external_exports.enum(["low", "normal", "high", "urgent"]);
5568
+ var WorkItemStatusSchema = external_exports.enum([
5569
+ "submitted",
5570
+ "scoped",
5571
+ "dispatched",
5572
+ "pr_open",
5573
+ "done",
5574
+ "declined"
5575
+ ]);
5576
+ var CreateWorkItemInputSchema = external_exports.object({
5577
+ productId: external_exports.string().uuid(),
5578
+ type: WorkItemTypeSchema,
5579
+ title: external_exports.string().min(3).max(180),
5580
+ description: external_exports.string().min(8).max(2e4),
5581
+ acceptanceCriteria: external_exports.string().max(2e4).optional(),
5582
+ priority: WorkItemPrioritySchema.default("normal")
5583
+ }).strict();
5584
+ var ScopeWorkItemInputSchema = external_exports.object({
5585
+ scopedTask: external_exports.string().min(8).max(2e4).optional()
5586
+ }).strict();
5587
+ var ListWorkItemsQuerySchema = external_exports.object({
5588
+ productId: external_exports.string().uuid().optional(),
5589
+ status: WorkItemStatusSchema.optional()
5590
+ }).strict();
5591
+ var DispatchWorkItemInputSchema = external_exports.object({
5592
+ executor: external_exports.enum(["claude-code", "codex"]).default("codex"),
5593
+ mode: external_exports.enum(["dry-run", "execute"]).default("dry-run")
5594
+ }).strict();
4712
5595
 
4713
- // src/witan/json-safe.ts
4714
- function stripBom(text) {
4715
- return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
4716
- }
5596
+ // ../shared/src/schemas/goal-frontmatter.ts
5597
+ var GoalStreamKindSchema = external_exports.enum(["code", "process"]);
5598
+ var GoalPrioritySchema = external_exports.enum(["p0", "p1", "p2"]);
5599
+ var GoalFrontmatterExtrasSchema = external_exports.object({
5600
+ stream: external_exports.string().min(1).nullable().default(null),
5601
+ order: external_exports.number().int().nullable().default(null),
5602
+ dependsOn: external_exports.array(external_exports.string().min(1)).default([]),
5603
+ priority: GoalPrioritySchema.nullable().default(null),
5604
+ kind: GoalStreamKindSchema.default("code")
5605
+ });
4717
5606
 
4718
- // src/witan/repo-signals.ts
4719
- function buildWitanInputFromRepo(options) {
4720
- assertRepoPathExists(options.repoPath);
4721
- const generatedAt = options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
4722
- const headSha = readGitHead(options.repoPath);
4723
- const repoFiles = listRepoFiles(options.repoPath);
4724
- const archetype = classifyRepoArchetype(repoFiles);
5607
+ // ../shared/src/schemas/stream.ts
5608
+ var StreamSchema = external_exports.object({
5609
+ id: external_exports.string().uuid(),
5610
+ studioId: external_exports.string().uuid(),
5611
+ name: external_exports.string().min(1).max(120),
5612
+ tag: external_exports.string().max(60).nullable(),
5613
+ kind: GoalStreamKindSchema,
5614
+ orderIndex: external_exports.number().int(),
5615
+ createdAt: external_exports.coerce.date(),
5616
+ updatedAt: external_exports.coerce.date()
5617
+ });
5618
+ var StreamItemSchema = external_exports.object({
5619
+ id: external_exports.string().uuid(),
5620
+ studioId: external_exports.string().uuid(),
5621
+ streamId: external_exports.string().uuid(),
5622
+ orderIndex: external_exports.number().int(),
5623
+ title: external_exports.string().min(1).max(200),
5624
+ /** docs/orchestration/goal_*.md filename (no extension) for code items; null for process items. */
5625
+ goalName: external_exports.string().min(1).nullable(),
5626
+ refLabel: external_exports.string().max(60).nullable(),
5627
+ /** Free-form governed-run prompt text (mirrors the prototype's per-item `run` string). Null = no run control shown. */
5628
+ runPrompt: external_exports.string().min(1).nullable(),
5629
+ createdAt: external_exports.coerce.date(),
5630
+ updatedAt: external_exports.coerce.date()
5631
+ });
5632
+ var StreamItemDisplayStatusSchema = external_exports.enum([
5633
+ "done",
5634
+ "in-review",
5635
+ "running",
5636
+ "queued",
5637
+ "blocked",
5638
+ "local-unknown"
5639
+ ]);
5640
+
5641
+ // ../shared/src/schemas/runner-dispatch.ts
5642
+ var RUNNER_DISPATCH_MODES = ["dry-run", "execute"];
5643
+ var RunnerDispatchModeSchema = external_exports.enum(RUNNER_DISPATCH_MODES);
5644
+ var RUNNER_DISPATCH_STATUSES = ["queued", "claimed", "running", "done", "failed"];
5645
+ var RunnerDispatchStatusSchema = external_exports.enum(RUNNER_DISPATCH_STATUSES);
5646
+ var GOAL_CARD_PATTERN = /^docs\/orchestration\/[A-Za-z0-9_./-]+\.md$/;
5647
+ function isAllowedGoalCardPath(goalCard) {
5648
+ if (!GOAL_CARD_PATTERN.test(goalCard)) return false;
5649
+ return goalCard.split("/").every((segment) => segment !== "." && segment !== "..");
5650
+ }
5651
+ var GoalCardPathSchema = external_exports.string().min(1).max(300).refine(isAllowedGoalCardPath, { message: "goal_card_invalid" });
5652
+ var RunnerDispatchRequestSchema = external_exports.object({
5653
+ goalCard: GoalCardPathSchema,
5654
+ stream: external_exports.string().min(1).max(120).optional(),
5655
+ mode: RunnerDispatchModeSchema
5656
+ });
5657
+
5658
+ // ../shared/src/schemas/witan-metrics-manifest.ts
5659
+ var WITAN_METRICS_MANIFEST_SCHEMA_VERSION = "witan-metrics-manifest-v0";
5660
+ var WitanMetricsManifestReturnsFrequencySchema = external_exports.enum([
5661
+ "daily",
5662
+ "weekly",
5663
+ "monthly",
5664
+ "annual"
5665
+ ]);
5666
+ var WitanMetricsManifestFoldSchema = external_exports.object({
5667
+ foldId: external_exports.string().min(1).max(80),
5668
+ inSampleSharpe: external_exports.number().optional(),
5669
+ outOfSampleSharpe: external_exports.number().optional()
5670
+ }).strict();
5671
+ var WitanMetricsManifestCscvTrialSchema = external_exports.object({
5672
+ trialId: external_exports.string().min(1).max(80),
5673
+ blockReturns: external_exports.array(external_exports.number()).min(2)
5674
+ }).strict();
5675
+ var WitanMetricsManifestCscvSchema = external_exports.object({
5676
+ // Must be even (split into IS/OOS halves) — enforced by the grader, not the schema.
5677
+ blocks: external_exports.number().int().min(4).max(16),
5678
+ trials: external_exports.array(WitanMetricsManifestCscvTrialSchema).min(2).max(200)
5679
+ }).strict();
5680
+ var WitanMetricsManifestCostModelSchema = external_exports.object({
5681
+ feeBps: external_exports.number().min(0).optional(),
5682
+ slippageBps: external_exports.number().min(0).optional(),
5683
+ borrowBps: external_exports.number().min(0).optional(),
5684
+ notes: external_exports.string().min(1).max(300).optional()
5685
+ }).strict();
5686
+ var WitanMetricsManifestParameterPointSchema = external_exports.object({
5687
+ // Human-readable label for this point (e.g. "72" or "72 bars") — evidence/display only.
5688
+ paramLabel: external_exports.string().min(1).max(80),
5689
+ // The point's position on its swept axis, used to find its nearest neighbors by distance.
5690
+ paramValue: external_exports.number(),
5691
+ outOfSampleSharpe: external_exports.number()
5692
+ }).strict();
5693
+ var WitanMetricsManifestParameterSweepSchema = external_exports.object({
5694
+ // Name of the swept parameter (e.g. "lookback_bars") — evidence/display only.
5695
+ paramName: external_exports.string().min(1).max(80),
5696
+ points: external_exports.array(WitanMetricsManifestParameterPointSchema).min(3).max(500)
5697
+ }).strict();
5698
+ var WitanMetricsManifestLabelSourceSchema = external_exports.enum([
5699
+ "real_forward_returns",
5700
+ "synthetic",
5701
+ "unknown"
5702
+ ]);
5703
+ var WitanMetricsManifestSchema = external_exports.object({
5704
+ schemaVersion: external_exports.literal(WITAN_METRICS_MANIFEST_SCHEMA_VERSION),
5705
+ strategyName: external_exports.string().min(1).max(200).optional(),
5706
+ // The headline reported Sharpe ratio the target repo is claiming.
5707
+ reportedSharpe: external_exports.number(),
5708
+ // How many trials/backtests were run in the search that produced reportedSharpe (the
5709
+ // "1-of-42" count) — required so the grader can correct for selection bias.
5710
+ trialCount: external_exports.number().int().positive(),
5711
+ // Track-record length in return observations (e.g. 252 for a year of daily returns) —
5712
+ // the `n` in the Probabilistic/Deflated Sharpe Ratio formula.
5713
+ trackRecordObservations: external_exports.number().int().positive(),
5714
+ returnsFrequency: WitanMetricsManifestReturnsFrequencySchema.default("daily"),
5715
+ // Skew/kurtosis of the returns distribution; default to the normal-distribution values
5716
+ // (0 skew, kurtosis 3) when the repo does not report them.
5717
+ skewness: external_exports.number().default(0),
5718
+ kurtosis: external_exports.number().min(0).default(3),
5719
+ // Whether reportedSharpe is net of trading costs (fees/slippage/borrow/roll).
5720
+ netOfCosts: external_exports.boolean(),
5721
+ costModel: WitanMetricsManifestCostModelSchema.optional(),
5722
+ // Per-fold in-sample vs out-of-sample breakdown, when the repo reports one.
5723
+ folds: external_exports.array(WitanMetricsManifestFoldSchema).default([]),
5724
+ // Per-trial, per-block performance matrix for the CSCV/PBO computation, when available.
5725
+ cscv: WitanMetricsManifestCscvSchema.optional(),
5726
+ // Parameter-sweep breakdown for the run-tier (L3b) parameter-neighborhood robustness
5727
+ // grader, when the run swept a parameter (e.g. a lookback window) and recorded OOS
5728
+ // performance at each swept value.
5729
+ parameterSweep: WitanMetricsManifestParameterSweepSchema.optional(),
5730
+ // Provenance of the labels behind reportedSharpe (labelling-integrity, L1+artifact tier).
5731
+ labelSource: WitanMetricsManifestLabelSourceSchema.optional()
5732
+ }).strict();
5733
+
5734
+ // ../shared/src/schemas/witan-strategy-adapter.ts
5735
+ var WITAN_STRATEGY_ADAPTER_CONFIG_SCHEMA_VERSION = "witan-strategy-adapter-v0";
5736
+ var WitanStrategyAdapterConfigSchema = external_exports.object({
5737
+ schemaVersion: external_exports.literal(WITAN_STRATEGY_ADAPTER_CONFIG_SCHEMA_VERSION),
5738
+ // Argv for the strategy entrypoint, e.g. ["python3", "strategy.py"] or ["node", "run.mjs"].
5739
+ // Command-argv (not a language enum) is what keeps the adapter language-agnostic — most
5740
+ // real targets are Python, but the contract does not assume it.
5741
+ command: external_exports.array(external_exports.string().min(1).max(300)).min(1).max(20),
5742
+ // Relative path (within the target repo) to the data the strategy should backtest against.
5743
+ dataPath: external_exports.string().min(1).max(500).optional(),
5744
+ // Backtest window, as the target repo defines its own date strings (ISO-8601 recommended).
5745
+ // Optional — a strategy may declare its own default window instead.
5746
+ windowStart: external_exports.string().min(1).max(40).optional(),
5747
+ windowEnd: external_exports.string().min(1).max(40).optional(),
5748
+ // Relative path (within the sandboxed workspace) the entrypoint must write its raw result
5749
+ // to — see WitanStrategyRunResultSchema below.
5750
+ outputPath: external_exports.string().min(1).max(300).default("witan-run-result.json"),
5751
+ timeoutMs: external_exports.number().int().positive().max(30 * 60 * 1e3).default(2 * 60 * 1e3),
5752
+ // Explicit opt-in egress allowlist. Empty by default — no network from the sandboxed run
5753
+ // unless the target repo explicitly whitelists hosts here.
5754
+ allowedHosts: external_exports.array(external_exports.string().min(1).max(255)).max(20).default([])
5755
+ }).strict();
5756
+ var WitanStrategyRunResultSchema = WitanMetricsManifestSchema.omit({
5757
+ schemaVersion: true
5758
+ });
5759
+
5760
+ // ../shared/src/types/tactical-action.ts
5761
+ var TacticalActionTypeSchema = external_exports.enum([
5762
+ "merge_pr_auto_merge_safe",
5763
+ "deploy_staging",
5764
+ "acknowledge_canary_alert",
5765
+ "update_status_md",
5766
+ "provision_product",
5767
+ "dispatch_dev_task"
5768
+ ]);
5769
+ var TacticalActionStatusSchema = external_exports.enum(["executed", "blocked", "dry_run"]);
5770
+ var TacticalActionPolicySchema = external_exports.object({
5771
+ studioId: external_exports.string().uuid(),
5772
+ productId: external_exports.string().uuid(),
5773
+ actionType: TacticalActionTypeSchema,
5774
+ allowed: external_exports.boolean(),
5775
+ dryRun: external_exports.boolean(),
5776
+ promotedAt: external_exports.coerce.date().nullable(),
5777
+ forceEnableReason: external_exports.string().nullable()
5778
+ });
5779
+ var BaseActionSchema = external_exports.object({
5780
+ actionType: TacticalActionTypeSchema,
5781
+ productId: external_exports.string().uuid(),
5782
+ coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
5783
+ customerFacingProduction: external_exports.boolean().default(false)
5784
+ });
5785
+ var MergePrTacticalActionSchema = BaseActionSchema.extend({
5786
+ actionType: external_exports.literal("merge_pr_auto_merge_safe"),
5787
+ repository: external_exports.string().min(1),
5788
+ pullRequestNumber: external_exports.number().int().positive(),
5789
+ labels: external_exports.array(external_exports.string()),
5790
+ ciStatus: external_exports.enum(["green", "red", "unknown"]),
5791
+ humanApprovals: external_exports.number().int().nonnegative(),
5792
+ coworkClaudeApprovedStatus: external_exports.enum(["green", "red", "unknown"]),
5793
+ // The PR head SHA captured at the SAME live precondition snapshot that
5794
+ // verified the label/CI/approvals/cowork-claude-approved gates. Threaded
5795
+ // through to the GitHub merge call as the conditional `sha` parameter so a
5796
+ // commit that lands between the snapshot and the merge (a fast follow-up
5797
+ // push, or a re-triggered CI run resetting status) can never be
5798
+ // squash-merged unverified — GitHub rejects the merge with 409 instead.
5799
+ headSha: external_exports.string().min(1)
5800
+ });
5801
+ var DeployStagingTacticalActionSchema = BaseActionSchema.extend({
5802
+ actionType: external_exports.literal("deploy_staging"),
5803
+ environment: external_exports.literal("staging"),
5804
+ mainStatus: external_exports.enum(["green", "red", "unknown"]),
5805
+ stagingStatus: external_exports.enum(["green", "red", "unknown"])
5806
+ });
5807
+ var AcknowledgeCanaryAlertTacticalActionSchema = BaseActionSchema.extend({
5808
+ actionType: external_exports.literal("acknowledge_canary_alert"),
5809
+ alertId: external_exports.string().min(1),
5810
+ fingerprint: external_exports.string().min(1),
5811
+ knownFalsePositiveFingerprints: external_exports.array(external_exports.string()).default([])
5812
+ });
5813
+ var UpdateStatusMdTacticalActionSchema = BaseActionSchema.extend({
5814
+ actionType: external_exports.literal("update_status_md"),
5815
+ source: external_exports.literal("daily_brief_synthesis"),
5816
+ statusMarkdown: external_exports.string().min(1).max(2e4)
5817
+ });
5818
+ var ProvisionProductTacticalActionSchema = BaseActionSchema.extend({
5819
+ actionType: external_exports.literal("provision_product"),
5820
+ productName: external_exports.string().min(1).max(80),
5821
+ vertical: external_exports.string().min(1).max(80),
5822
+ repoTarget: external_exports.string().min(1),
5823
+ templateRef: external_exports.string().min(1),
5824
+ scopeNotes: external_exports.string().max(2e3).optional()
5825
+ });
5826
+ var DispatchDevTaskTacticalActionSchema = BaseActionSchema.extend({
5827
+ actionType: external_exports.literal("dispatch_dev_task"),
5828
+ repo: RepoRefSchema,
5829
+ task: external_exports.string().min(1).max(2e4),
5830
+ executor: CodingAgentExecutorSchema
5831
+ });
5832
+ var TacticalActionSchema = external_exports.discriminatedUnion("actionType", [
5833
+ MergePrTacticalActionSchema,
5834
+ DeployStagingTacticalActionSchema,
5835
+ AcknowledgeCanaryAlertTacticalActionSchema,
5836
+ UpdateStatusMdTacticalActionSchema,
5837
+ ProvisionProductTacticalActionSchema,
5838
+ DispatchDevTaskTacticalActionSchema
5839
+ ]);
5840
+ var TacticalActionContextSchema = external_exports.object({
5841
+ studioId: external_exports.string().uuid(),
5842
+ actorUserId: external_exports.string().uuid().nullable().optional(),
5843
+ requestedAt: external_exports.coerce.date().optional()
5844
+ });
5845
+ var TacticalActionPermitResultSchema = external_exports.discriminatedUnion("status", [
5846
+ external_exports.object({
5847
+ status: external_exports.literal("executed"),
5848
+ auditLogId: external_exports.string().uuid(),
5849
+ reason: external_exports.literal("permit_allowed")
5850
+ }),
5851
+ external_exports.object({
5852
+ status: external_exports.literal("blocked"),
5853
+ auditLogId: external_exports.string().uuid().optional(),
5854
+ reason: external_exports.string().min(1)
5855
+ }),
5856
+ external_exports.object({
5857
+ status: external_exports.literal("dry_run"),
5858
+ auditLogId: external_exports.string().uuid(),
5859
+ reason: external_exports.literal("dry_run_mode"),
5860
+ wouldHaveDone: external_exports.record(external_exports.unknown())
5861
+ })
5862
+ ]);
5863
+ var TacticalActionLogEntrySchema = external_exports.object({
5864
+ id: external_exports.string().uuid(),
5865
+ studioId: external_exports.string().uuid(),
5866
+ productId: external_exports.string().uuid(),
5867
+ product: external_exports.string().nullable().optional(),
5868
+ coordinatorSessionId: external_exports.string().uuid().nullable(),
5869
+ actionType: TacticalActionTypeSchema.or(external_exports.string()),
5870
+ context: external_exports.record(external_exports.unknown()),
5871
+ permitResult: external_exports.record(external_exports.unknown()),
5872
+ status: TacticalActionStatusSchema,
5873
+ outcome: external_exports.string().nullable(),
5874
+ wouldHaveDone: external_exports.record(external_exports.unknown()).nullable(),
5875
+ attemptedAt: external_exports.string(),
5876
+ executedAt: external_exports.string().nullable()
5877
+ });
5878
+
5879
+ // ../shared/src/schemas/index.ts
5880
+ var StudioSchema = external_exports.object({
5881
+ id: external_exports.string().uuid(),
5882
+ name: external_exports.string().min(1).max(100),
5883
+ billingStatus: external_exports.enum(["trial", "active", "past_due", "cancelled"]),
5884
+ planTier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
5885
+ onPrem: external_exports.boolean().default(false),
5886
+ createdAt: external_exports.coerce.date()
5887
+ });
5888
+ var HumanSchema = external_exports.object({
5889
+ id: external_exports.string().uuid(),
5890
+ studioId: external_exports.string().uuid(),
5891
+ email: external_exports.string().email(),
5892
+ name: external_exports.string().min(1).max(120),
5893
+ oauthProviders: external_exports.array(external_exports.enum(["google", "microsoft", "apple"])).default([]),
5894
+ role: external_exports.enum(["owner", "member", "advisor", "per_product"]),
5895
+ timezone: external_exports.string(),
5896
+ briefTime: external_exports.string().regex(/^\d{2}:\d{2}$/),
5897
+ createdAt: external_exports.coerce.date()
5898
+ });
5899
+ var ProductSchema = external_exports.object({
5900
+ id: external_exports.string().uuid(),
5901
+ studioId: external_exports.string().uuid(),
5902
+ name: external_exports.string().min(1).max(80),
5903
+ slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
5904
+ status: external_exports.enum(["active", "snoozed", "wound_down", "deleted"]),
5905
+ description: external_exports.string().max(280).optional(),
5906
+ repoUrl: external_exports.string().url().optional(),
5907
+ calendarTag: external_exports.string().optional(),
5908
+ emailLabelPrefix: external_exports.string().optional(),
5909
+ colorHex: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
5910
+ scheduleBriefTime: external_exports.string().regex(/^\d{2}:\d{2}$/).optional(),
5911
+ briefTemplateId: external_exports.string().uuid().optional(),
5912
+ regulated: external_exports.boolean().default(false),
5913
+ createdAt: external_exports.coerce.date(),
5914
+ lastTouchedAt: external_exports.coerce.date()
5915
+ });
5916
+ var AgentSchema = external_exports.object({
5917
+ id: external_exports.string().uuid(),
5918
+ studioId: external_exports.string().uuid(),
5919
+ productId: external_exports.string().uuid(),
5920
+ agentType: external_exports.enum(["codex", "claude-code", "cowork", "cursor", "cline", "aider", "other"]),
5921
+ sessionId: external_exports.string().optional(),
5922
+ status: external_exports.enum(["active", "idle", "registered", "archived"]),
5923
+ registeredAt: external_exports.coerce.date(),
5924
+ lastActiveAt: external_exports.coerce.date().optional(),
5925
+ totalCostCentsLifetime: external_exports.number().int().nonnegative().default(0)
5926
+ });
5927
+ var AgentRunSchema = external_exports.object({
5928
+ id: external_exports.string().uuid(),
5929
+ agentId: external_exports.string().uuid(),
5930
+ coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
5931
+ startedAt: external_exports.coerce.date(),
5932
+ completedAt: external_exports.coerce.date().optional(),
5933
+ actionType: external_exports.string(),
5934
+ toolName: external_exports.string().optional(),
5935
+ toolInputSummary: external_exports.string().optional(),
5936
+ toolOutputSummary: external_exports.string().optional(),
5937
+ tokensUsedInput: external_exports.number().int().nonnegative().default(0),
5938
+ tokensUsedOutput: external_exports.number().int().nonnegative().default(0),
5939
+ costCents: external_exports.number().int().nonnegative().default(0),
5940
+ durationMs: external_exports.number().int().nonnegative().default(0),
5941
+ resultStatus: external_exports.enum(["success", "failure", "partial", "timeout"]).optional(),
5942
+ resultSummary: external_exports.string().optional(),
5943
+ filesTouched: external_exports.array(external_exports.string()).default([])
5944
+ });
5945
+ var CoordinatorStatusSchema = external_exports.enum([
5946
+ "draft",
5947
+ "spawned",
5948
+ "in_progress",
5949
+ "reporting",
5950
+ "closed"
5951
+ ]);
5952
+ var CoordinatorEscalationPolicySchema = external_exports.object({
5953
+ stuck_after_hours: external_exports.number().int().positive(),
5954
+ method: external_exports.literal("flag_for_human"),
5955
+ urgency: external_exports.enum(["low", "medium", "high", "critical"]).optional()
5956
+ });
5957
+ var CoordinatorSessionSchema = external_exports.object({
5958
+ id: external_exports.string().uuid(),
5959
+ studioId: external_exports.string().uuid(),
5960
+ productId: external_exports.string().uuid(),
5961
+ promptId: external_exports.string().uuid().nullable(),
5962
+ objective: external_exports.string(),
5963
+ status: CoordinatorStatusSchema,
5964
+ spawnedAt: external_exports.coerce.date().nullable(),
5965
+ closedAt: external_exports.coerce.date().nullable(),
5966
+ escalationPolicy: CoordinatorEscalationPolicySchema.nullable(),
5967
+ outcomeSummary: external_exports.string().nullable(),
5968
+ createdAt: external_exports.coerce.date()
5969
+ });
5970
+ var AgentActivityWindowSchema = external_exports.enum(["24h", "7d", "30d"]);
5971
+ var AgentCostBucketSchema = external_exports.object({
5972
+ key: external_exports.string(),
5973
+ name: external_exports.string(),
5974
+ runCount: external_exports.number().int().nonnegative(),
5975
+ costUsd: external_exports.number().nonnegative()
5976
+ });
5977
+ var AgentCostRollupSchema = external_exports.object({
5978
+ window: AgentActivityWindowSchema,
5979
+ studioTotalUsd: external_exports.number().nonnegative(),
5980
+ runCount: external_exports.number().int().nonnegative(),
5981
+ byAgent: external_exports.array(AgentCostBucketSchema),
5982
+ byProduct: external_exports.array(AgentCostBucketSchema)
5983
+ });
5984
+ var AgentConflictRecordSchema = external_exports.object({
5985
+ file: external_exports.string(),
5986
+ agents: external_exports.array(external_exports.string()).min(2),
5987
+ references: external_exports.array(
5988
+ external_exports.object({
5989
+ runId: external_exports.string(),
5990
+ agent: external_exports.string(),
5991
+ product: external_exports.string().nullable(),
5992
+ startedAt: external_exports.string(),
5993
+ sessionRef: external_exports.string().nullable(),
5994
+ prUrl: external_exports.string().nullable()
5995
+ })
5996
+ )
5997
+ });
5998
+ var AgentLeaderboardEntrySchema = external_exports.object({
5999
+ agent: external_exports.string(),
6000
+ product: external_exports.string().nullable(),
6001
+ runCount: external_exports.number().int().nonnegative(),
6002
+ completedRuns: external_exports.number().int().nonnegative(),
6003
+ failedRuns: external_exports.number().int().nonnegative(),
6004
+ costUsd: external_exports.number().nonnegative(),
6005
+ filesTouched: external_exports.number().int().nonnegative(),
6006
+ conflicts: external_exports.number().int().nonnegative(),
6007
+ state: external_exports.enum(["productive", "idle", "duplicating"]),
6008
+ lastActiveAt: external_exports.string().nullable()
6009
+ });
6010
+ var ModelCostEstimateInputSchema = external_exports.object({
6011
+ model: external_exports.string().optional(),
6012
+ inputTokens: external_exports.number().int().nonnegative().default(0),
6013
+ outputTokens: external_exports.number().int().nonnegative().default(0)
6014
+ });
6015
+ var ModelCostEstimateSchema = external_exports.object({
6016
+ costUsd: external_exports.number().nonnegative(),
6017
+ method: external_exports.enum(["estimated_from_model_rate", "unknown_model_rate"]),
6018
+ rateModel: external_exports.enum(["claude-haiku", "claude-sonnet", "claude-opus", "unknown"])
6019
+ });
6020
+ var IntegrationSchema = external_exports.object({
6021
+ id: external_exports.string().uuid(),
6022
+ studioId: external_exports.string().uuid(),
6023
+ productId: external_exports.string().uuid().nullable(),
6024
+ kind: external_exports.string(),
6025
+ oauthTokenEncrypted: external_exports.string().optional(),
6026
+ refreshTokenEncrypted: external_exports.string().optional(),
6027
+ status: external_exports.enum(["active", "broken", "revoked"]),
6028
+ lastSyncAt: external_exports.coerce.date().optional(),
6029
+ errorCount: external_exports.number().int().nonnegative().default(0)
6030
+ });
6031
+ var EmailAccountSchema = external_exports.object({
6032
+ id: external_exports.string().uuid(),
6033
+ studioId: external_exports.string().uuid(),
6034
+ provider: external_exports.enum(["gmail", "m365", "imap"]),
6035
+ oauthTokenEncrypted: external_exports.string().optional(),
6036
+ defaultLabelPrefix: external_exports.string().optional(),
6037
+ triageCadenceMins: external_exports.number().int().positive().default(240)
6038
+ });
6039
+ var RoutineSchema = external_exports.object({
6040
+ id: external_exports.string().uuid(),
6041
+ productId: external_exports.string().uuid().nullable(),
6042
+ name: external_exports.string(),
6043
+ cronExpression: external_exports.string(),
6044
+ promptTemplate: external_exports.string(),
6045
+ model: external_exports.enum(["sonnet", "opus", "haiku"]).default("sonnet"),
6046
+ lastRunAt: external_exports.coerce.date().optional(),
6047
+ nextRunAt: external_exports.coerce.date().optional(),
6048
+ enabled: external_exports.boolean().default(true),
6049
+ retryCount: external_exports.number().int().nonnegative().default(0)
6050
+ });
6051
+ var RoutineRunSchema = external_exports.object({
6052
+ id: external_exports.string().uuid(),
6053
+ routineId: external_exports.string().uuid(),
6054
+ startedAt: external_exports.coerce.date(),
6055
+ completedAt: external_exports.coerce.date().optional(),
6056
+ status: external_exports.enum(["success", "failed", "retried"]),
6057
+ outputBriefId: external_exports.string().uuid().optional(),
6058
+ errorMessage: external_exports.string().optional(),
6059
+ inferenceCostCents: external_exports.number().int().nonnegative().default(0)
6060
+ });
6061
+ var BriefSchema = external_exports.object({
6062
+ id: external_exports.string().uuid(),
6063
+ studioId: external_exports.string().uuid(),
6064
+ generatedAt: external_exports.coerce.date(),
6065
+ type: external_exports.enum(["daily", "weekly", "on_demand"]),
6066
+ html: external_exports.string().optional(),
6067
+ markdown: external_exports.string(),
6068
+ sourceLinks: external_exports.array(external_exports.object({ label: external_exports.string(), url: external_exports.string() })).default([]),
6069
+ shared: external_exports.boolean().default(false),
6070
+ shareToken: external_exports.string().optional(),
6071
+ shareExpiresAt: external_exports.coerce.date().optional(),
6072
+ inferenceCostCents: external_exports.number().int().nonnegative().default(0)
6073
+ });
6074
+ var MemoryEntrySchema = external_exports.object({
6075
+ id: external_exports.string().uuid(),
6076
+ productId: external_exports.string().uuid(),
6077
+ kind: external_exports.enum(["decision", "fact", "customer", "status", "pattern", "thread"]),
6078
+ content: external_exports.string(),
6079
+ // embedding stored separately in pgvector; not modelled in API layer
6080
+ createdAt: external_exports.coerce.date(),
6081
+ lastReferencedAt: external_exports.coerce.date().optional(),
6082
+ referenceCount: external_exports.number().int().nonnegative().default(0),
6083
+ pinned: external_exports.boolean().default(false)
6084
+ });
6085
+ var InboxClassificationSchema = external_exports.object({
6086
+ id: external_exports.string().uuid(),
6087
+ emailAccountId: external_exports.string().uuid(),
6088
+ productId: external_exports.string().uuid().nullable(),
6089
+ messageId: external_exports.string(),
6090
+ sender: external_exports.string(),
6091
+ labelApplied: external_exports.string(),
6092
+ urgency: external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]),
6093
+ confidence: external_exports.number().min(0).max(1),
6094
+ action: external_exports.enum(["labelled", "archived", "drafted_reply"]),
6095
+ userCorrected: external_exports.boolean().default(false),
6096
+ correctedTo: external_exports.string().optional()
6097
+ });
6098
+ var DraftReplySchema = external_exports.object({
6099
+ id: external_exports.string().uuid(),
6100
+ classificationId: external_exports.string().uuid(),
6101
+ draftText: external_exports.string(),
6102
+ confidence: external_exports.number().min(0).max(1),
6103
+ sentAt: external_exports.coerce.date().optional(),
6104
+ sentVia: external_exports.string().optional()
6105
+ });
6106
+ var AlwaysAlertRuleSchema = external_exports.object({
6107
+ id: external_exports.string().uuid(),
6108
+ studioId: external_exports.string().uuid(),
6109
+ ruleType: external_exports.enum(["sender", "subject", "domain"]),
6110
+ value: external_exports.string(),
6111
+ escalationMethod: external_exports.enum(["push", "slack", "email", "brief_pin"]).default("brief_pin")
6112
+ });
6113
+ var AuditEventSchema = external_exports.object({
6114
+ id: external_exports.string().uuid(),
6115
+ studioId: external_exports.string().uuid(),
6116
+ actor: external_exports.enum(["user", "agent", "system"]),
6117
+ action: external_exports.string(),
6118
+ integrationId: external_exports.string().uuid().optional(),
6119
+ productId: external_exports.string().uuid().optional(),
6120
+ timestamp: external_exports.coerce.date(),
6121
+ metadata: external_exports.record(external_exports.unknown()).default({})
6122
+ });
6123
+ var SubscriptionSchema = external_exports.object({
6124
+ id: external_exports.string().uuid(),
6125
+ studioId: external_exports.string().uuid(),
6126
+ stripeSubscriptionId: external_exports.string().optional(),
6127
+ tier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
6128
+ seats: external_exports.number().int().positive(),
6129
+ status: external_exports.string(),
6130
+ currentPeriodEnd: external_exports.coerce.date(),
6131
+ cancelAt: external_exports.coerce.date().optional()
6132
+ });
6133
+ var ProductMembershipSchema = external_exports.object({
6134
+ humanId: external_exports.string().uuid(),
6135
+ productId: external_exports.string().uuid(),
6136
+ role: external_exports.enum(["lead", "contributor", "observer"])
6137
+ });
6138
+
6139
+ // ../witan/src/batch.ts
6140
+ import { execFileSync as execFileSync3 } from "child_process";
6141
+ import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
6142
+ import { basename as basename2, join as join5 } from "path";
6143
+
6144
+ // ../witan/src/public-scan.ts
6145
+ import { resolve as resolve2 } from "path";
6146
+
6147
+ // ../witan/src/ingest.ts
6148
+ import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
6149
+ import { join as join2 } from "path";
6150
+
6151
+ // ../witan/src/finding-limits.ts
6152
+ var RULE_ID_MAX = 200;
6153
+ var MESSAGE_MAX = 500;
6154
+ var LOCATION_MAX = 700;
6155
+ function clamp(value, max) {
6156
+ if (value.length <= max) return value;
6157
+ const ellipsis = "...";
6158
+ return `${value.slice(0, Math.max(max - ellipsis.length, 0))}${ellipsis}`;
6159
+ }
6160
+ function clampFinding(finding) {
4725
6161
  return {
4726
- productSlug: options.productSlug,
4727
- productDisplayName: options.productDisplayName,
4728
- repo: {
4729
- path: options.repoPath,
4730
- ...headSha ? { headSha } : {}
4731
- },
4732
- generatedAt,
4733
- ...options.rubricVersion ? { rubricVersion: options.rubricVersion } : {},
4734
- archetype: archetype.archetype,
4735
- ...archetype.insufficientSourceReason ? { insufficientSourceReason: archetype.insufficientSourceReason } : {},
4736
- signals: [
4737
- ...collectRepoSignals(options.repoPath, generatedAt, repoFiles),
4738
- ...(options.domainCollectors ?? []).map((collect) => collect(options.repoPath, repoFiles)),
4739
- ...options.additionalSignals ?? []
4740
- ]
6162
+ ...finding,
6163
+ ruleId: clamp(finding.ruleId, RULE_ID_MAX),
6164
+ message: clamp(finding.message, MESSAGE_MAX),
6165
+ ...finding.location ? { location: clamp(finding.location, LOCATION_MAX) } : {}
4741
6166
  };
4742
6167
  }
4743
- var SOURCE_EXTENSION_PATTERN = /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs|py|go|rs|java|kt|kts|rb|php|swift|cpp|cc|cxx|c|h|hpp|cs|scala|dart|ex|exs)$/i;
4744
- var BUNDLED_BINARY_EXTENSION_PATTERN = /\.(vsix|zip|tgz|whl|exe|dmg|pkg|msi|jar|war|apk|ipa|dll|dylib)$/i;
4745
- var DOCS_OR_MEDIA_EXTENSION_PATTERN = /\.(md|mdx|rst|png|jpe?g|gif|svg|webp|ico|pdf)$/i;
4746
- var INGEST_POINTER = "To assess a closed/bundled tool, ingest its scanner output via --ingest <sarif|scorecard>.";
4747
- function classifyRepoArchetype(repoFiles) {
4748
- const totalFileCount = repoFiles.length;
4749
- const sourceFileCount = repoFiles.filter((file) => SOURCE_EXTENSION_PATTERN.test(file)).length;
4750
- if (totalFileCount === 0) {
4751
- return {
4752
- archetype: "empty",
4753
- sourceFileCount: 0,
4754
- totalFileCount: 0,
4755
- insufficientSourceReason: "Repository has no tracked files \u2014 there is nothing to certify."
4756
- };
4757
- }
4758
- if (sourceFileCount > 0) {
4759
- return {
4760
- archetype: isLikelyMonorepo(repoFiles) ? "monorepo" : "source",
4761
- sourceFileCount,
4762
- totalFileCount
4763
- };
4764
- }
4765
- const binaryFiles = repoFiles.filter((file) => BUNDLED_BINARY_EXTENSION_PATTERN.test(file));
4766
- if (binaryFiles.length > 0) {
4767
- const sample = binaryFiles[0];
4768
- return {
4769
- archetype: "binary_only",
4770
- sourceFileCount,
4771
- totalFileCount,
4772
- insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a binary/bundled-distribution tree (e.g. ${sample ? basename(sample) : "a packaged artifact"}) \u2014 cejel rates source, not binaries. ${INGEST_POINTER}`
6168
+
6169
+ // ../witan/src/generic-adapter.ts
6170
+ import { readFileSync as readFileSync2 } from "fs";
6171
+
6172
+ // ../witan/src/json-safe.ts
6173
+ function stripBom(text) {
6174
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
6175
+ }
6176
+
6177
+ // ../witan/src/generic-adapter.ts
6178
+ var VALID_DIMENSIONS = /* @__PURE__ */ new Set([
6179
+ "A1",
6180
+ "A2",
6181
+ "A3",
6182
+ "A4",
6183
+ "A5",
6184
+ "B1",
6185
+ "B2",
6186
+ "B3",
6187
+ "B4",
6188
+ "B5",
6189
+ "B6"
6190
+ ]);
6191
+ var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
6192
+ function isGenericSignalDocument(raw) {
6193
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
6194
+ const doc = raw;
6195
+ return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
6196
+ }
6197
+ function parseGenericJson(raw) {
6198
+ if (!isGenericSignalDocument(raw)) return [];
6199
+ const source = raw.tool ?? "unknown";
6200
+ const signals = [];
6201
+ for (const signal of raw.signals ?? []) {
6202
+ const dimension = signal.dimension;
6203
+ if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
6204
+ const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
6205
+ const findings = [];
6206
+ for (const finding of signal.findings ?? []) {
6207
+ const severity = finding.severity;
6208
+ if (!severity || !VALID_SEVERITIES.has(severity)) continue;
6209
+ const ruleId = finding.ruleId ?? "unknown";
6210
+ findings.push({
6211
+ ruleId,
6212
+ severity,
6213
+ message: finding.message ?? ruleId,
6214
+ ...finding.location ? { location: finding.location } : {}
6215
+ });
6216
+ }
6217
+ if (findings.length === 0) continue;
6218
+ signals.push({ source, dimension, weight, findings });
6219
+ }
6220
+ return signals;
6221
+ }
6222
+
6223
+ // ../witan/src/sarif-adapter.ts
6224
+ import { readFileSync as readFileSync3 } from "fs";
6225
+ var DIMENSION_RULES = [
6226
+ // A2 — injection / secrets / auth (high weight)
6227
+ {
6228
+ pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
6229
+ dimension: "A2",
6230
+ weight: 0.9
6231
+ },
6232
+ {
6233
+ pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
6234
+ dimension: "A2",
6235
+ weight: 0.9
6236
+ },
6237
+ {
6238
+ pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
6239
+ dimension: "A2",
6240
+ weight: 0.8
6241
+ },
6242
+ {
6243
+ pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
6244
+ dimension: "A2",
6245
+ weight: 0.8
6246
+ },
6247
+ {
6248
+ pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
6249
+ dimension: "A2",
6250
+ weight: 0.8
6251
+ },
6252
+ {
6253
+ pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
6254
+ dimension: "A2",
6255
+ weight: 0.7
6256
+ },
6257
+ {
6258
+ pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
6259
+ dimension: "A2",
6260
+ weight: 0.6
6261
+ },
6262
+ // A4 — dependency vulnerabilities
6263
+ {
6264
+ pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
6265
+ dimension: "A4",
6266
+ weight: 0.8
6267
+ },
6268
+ {
6269
+ pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
6270
+ dimension: "A4",
6271
+ weight: 0.7
6272
+ },
6273
+ // A3 — production readiness / insecure config
6274
+ {
6275
+ pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
6276
+ dimension: "A3",
6277
+ weight: 0.5
6278
+ },
6279
+ {
6280
+ pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
6281
+ dimension: "A3",
6282
+ weight: 0.4
6283
+ },
6284
+ {
6285
+ pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
6286
+ dimension: "A3",
6287
+ weight: 0.4
6288
+ },
6289
+ // A1 — test integrity (low weight; SARIF rarely surfaces this)
6290
+ {
6291
+ pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
6292
+ dimension: "A1",
6293
+ weight: 0.2
6294
+ }
6295
+ ];
6296
+ var DEFAULT_DIMENSION = "A2";
6297
+ var DEFAULT_WEIGHT = 0.3;
6298
+ var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
6299
+ function mapLevel(level) {
6300
+ if (!level || DROP_LEVEL.has(level)) return null;
6301
+ if (level === "error") return "critical";
6302
+ if (level === "warning") return "warning";
6303
+ return "info";
6304
+ }
6305
+ function mapRuleToDimension(ruleId, rules) {
6306
+ for (const rule of rules) {
6307
+ if (rule.pattern.test(ruleId)) {
6308
+ return { dimension: rule.dimension, weight: rule.weight };
6309
+ }
6310
+ }
6311
+ return { dimension: DEFAULT_DIMENSION, weight: DEFAULT_WEIGHT };
6312
+ }
6313
+ function renderLocation(result) {
6314
+ const loc = result.locations?.[0]?.physicalLocation;
6315
+ if (!loc) return void 0;
6316
+ const uri = loc.artifactLocation?.uri;
6317
+ const line = loc.region?.startLine;
6318
+ if (!uri) return void 0;
6319
+ return line != null ? `${uri}:${line}` : uri;
6320
+ }
6321
+ function dedupeFindings(findings) {
6322
+ const seen = /* @__PURE__ */ new Set();
6323
+ return findings.filter((f) => {
6324
+ const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
6325
+ if (seen.has(key)) return false;
6326
+ seen.add(key);
6327
+ return true;
6328
+ });
6329
+ }
6330
+ function parseSarifJson(raw, extraDimensionRules) {
6331
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
6332
+ const dimensionRules = extraDimensionRules ? [...DIMENSION_RULES, ...extraDimensionRules] : DIMENSION_RULES;
6333
+ const doc = raw;
6334
+ if (!Array.isArray(doc.runs)) return [];
6335
+ const buckets = /* @__PURE__ */ new Map();
6336
+ for (const run of doc.runs) {
6337
+ const driverName = run.tool?.driver?.name ?? "unknown";
6338
+ const source = `sarif:${driverName}`;
6339
+ const ruleDefaultLevels = /* @__PURE__ */ new Map();
6340
+ for (const rule of run.tool?.driver?.rules ?? []) {
6341
+ if (rule.id && rule.defaultConfiguration?.level) {
6342
+ ruleDefaultLevels.set(rule.id, rule.defaultConfiguration.level);
6343
+ }
6344
+ }
6345
+ for (const result of run.results ?? []) {
6346
+ const ruleId = result.ruleId ?? "unknown";
6347
+ const effectiveLevel = result.level ?? ruleDefaultLevels.get(ruleId) ?? "warning";
6348
+ const severity = mapLevel(effectiveLevel);
6349
+ if (!severity) continue;
6350
+ const message = result.message?.text ?? ruleId;
6351
+ const location = renderLocation(result);
6352
+ const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
6353
+ const bucketKey = `${source}|${dimension}`;
6354
+ if (!buckets.has(bucketKey)) {
6355
+ buckets.set(bucketKey, { source, dimension, weight, findings: [] });
6356
+ }
6357
+ buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
6358
+ }
6359
+ }
6360
+ return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
6361
+ source,
6362
+ dimension,
6363
+ weight,
6364
+ findings: dedupeFindings(findings)
6365
+ }));
6366
+ }
6367
+
6368
+ // ../witan/src/scorecard-adapter.ts
6369
+ import { readFileSync as readFileSync4 } from "fs";
6370
+ var CHECK_RULES = {
6371
+ // B2 — PR outcome traceability
6372
+ "Branch-Protection": { dimension: "B2", weight: 0.8 },
6373
+ "Code-Review": { dimension: "B2", weight: 0.7 },
6374
+ // B3 — CI and QA discipline
6375
+ "Dangerous-Workflow": { dimension: "B3", weight: 0.9 },
6376
+ "Token-Permissions": { dimension: "B3", weight: 0.8 },
6377
+ "CI-Tests": { dimension: "B3", weight: 0.7 },
6378
+ Maintained: { dimension: "B3", weight: 0.3 },
6379
+ // B4 — audit trail / release integrity
6380
+ "Signed-Releases": { dimension: "B4", weight: 0.7 },
6381
+ Packaging: { dimension: "B4", weight: 0.4 },
6382
+ "Security-Policy": { dimension: "B4", weight: 0.4 },
6383
+ // A4 — dependency hygiene
6384
+ Vulnerabilities: { dimension: "A4", weight: 0.9 },
6385
+ "Pinned-Dependencies": { dimension: "A4", weight: 0.8 },
6386
+ "Dependency-Update-Tool": { dimension: "A4", weight: 0.6 },
6387
+ // A2 — data-layer / static analysis
6388
+ SAST: { dimension: "A2", weight: 0.7 },
6389
+ "Binary-Artifacts": { dimension: "A2", weight: 0.6 },
6390
+ // A1 — test integrity
6391
+ Fuzzing: { dimension: "A1", weight: 0.3 }
6392
+ };
6393
+ function mapScoreToSeverity(score) {
6394
+ if (score == null || Number.isNaN(score)) return null;
6395
+ if (score < 0) return null;
6396
+ if (score >= 10) return null;
6397
+ if (score <= 3) return "critical";
6398
+ if (score <= 6) return "warning";
6399
+ return "info";
6400
+ }
6401
+ function dedupeFindings2(findings) {
6402
+ const seen = /* @__PURE__ */ new Set();
6403
+ return findings.filter((f) => {
6404
+ const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
6405
+ if (seen.has(key)) return false;
6406
+ seen.add(key);
6407
+ return true;
6408
+ });
6409
+ }
6410
+ function parseScorecardJson(raw) {
6411
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
6412
+ const doc = raw;
6413
+ if (!Array.isArray(doc.checks)) return [];
6414
+ const buckets = /* @__PURE__ */ new Map();
6415
+ for (const check of doc.checks) {
6416
+ const name = check.name;
6417
+ if (!name) continue;
6418
+ const rule = CHECK_RULES[name];
6419
+ if (!rule) continue;
6420
+ const severity = mapScoreToSeverity(check.score);
6421
+ if (!severity) continue;
6422
+ const scoreText = typeof check.score === "number" ? `${check.score}/10` : "n/a";
6423
+ const message = `${name} (Scorecard ${scoreText}): ${check.reason ?? "weakness detected"}`.slice(0, 500);
6424
+ const location = check.documentation?.url;
6425
+ const bucket = buckets.get(rule.dimension) ?? { weight: 0, findings: [] };
6426
+ bucket.weight = Math.max(bucket.weight, rule.weight);
6427
+ bucket.findings.push({
6428
+ ruleId: `scorecard:${name}`,
6429
+ severity,
6430
+ message,
6431
+ ...location ? { location } : {}
6432
+ });
6433
+ buckets.set(rule.dimension, bucket);
6434
+ }
6435
+ return Array.from(buckets.entries()).map(([dimension, { weight, findings }]) => ({
6436
+ source: "scorecard",
6437
+ dimension,
6438
+ weight,
6439
+ findings: dedupeFindings2(findings)
6440
+ }));
6441
+ }
6442
+
6443
+ // ../witan/src/ingest.ts
6444
+ function looksLikeSarif(raw) {
6445
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
6446
+ return Array.isArray(raw.runs);
6447
+ }
6448
+ function looksLikeScorecard(raw) {
6449
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
6450
+ return Array.isArray(raw.checks);
6451
+ }
6452
+ function countRawEntries(raw) {
6453
+ const obj = raw;
6454
+ if (Array.isArray(obj.runs)) {
6455
+ return obj.runs.reduce((sum, run) => {
6456
+ const results = run.results;
6457
+ return sum + (Array.isArray(results) ? results.length : 0);
6458
+ }, 0);
6459
+ }
6460
+ if (Array.isArray(obj.checks)) return obj.checks.length;
6461
+ if (Array.isArray(obj.signals)) {
6462
+ return obj.signals.reduce((sum, signal) => {
6463
+ const findings = signal.findings;
6464
+ return sum + (Array.isArray(findings) ? findings.length : 0);
6465
+ }, 0);
6466
+ }
6467
+ return 0;
6468
+ }
6469
+ function rawToolName(raw) {
6470
+ const obj = raw;
6471
+ if (Array.isArray(obj.runs)) {
6472
+ const firstRun = obj.runs[0];
6473
+ return firstRun?.tool?.driver?.name ?? "unknown";
6474
+ }
6475
+ if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
6476
+ return "scorecard";
6477
+ }
6478
+ function parseIngestFile(filePath) {
6479
+ let raw;
6480
+ try {
6481
+ raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
6482
+ } catch (error) {
6483
+ const message = error instanceof Error ? error.message : String(error);
6484
+ throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
6485
+ }
6486
+ let signals;
6487
+ if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
6488
+ else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
6489
+ else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
6490
+ if (!signals) {
6491
+ throw new Error(
6492
+ `Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
6493
+ );
6494
+ }
6495
+ const rawCount = countRawEntries(raw);
6496
+ const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
6497
+ if (rawCount > 0 && mappedCount === 0) {
6498
+ process.stderr.write(
6499
+ `Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
6500
+ `
6501
+ );
6502
+ }
6503
+ return signals.map((signal) => ({
6504
+ ...signal,
6505
+ findings: signal.findings.map(clampFinding)
6506
+ }));
6507
+ }
6508
+ function expandIngestPattern(pattern) {
6509
+ if (!pattern.includes("*")) return [pattern];
6510
+ const lastSlash = pattern.lastIndexOf("/");
6511
+ const dir = lastSlash === -1 ? "." : pattern.slice(0, lastSlash);
6512
+ const filePattern = lastSlash === -1 ? pattern : pattern.slice(lastSlash + 1);
6513
+ const regexSource = filePattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
6514
+ const regex = new RegExp(`^${regexSource}$`);
6515
+ let entries;
6516
+ try {
6517
+ entries = readdirSync2(dir);
6518
+ } catch {
6519
+ return [];
6520
+ }
6521
+ return entries.filter((name) => regex.test(name)).sort().map((name) => join2(dir, name));
6522
+ }
6523
+ function discoverIngestInputs(repoPath) {
6524
+ const inputsDir = join2(repoPath, ".cejel", "inputs");
6525
+ let entries;
6526
+ try {
6527
+ entries = readdirSync2(inputsDir);
6528
+ } catch {
6529
+ return [];
6530
+ }
6531
+ return entries.filter((name) => /\.(sarif|json)$/i.test(name)).sort().map((name) => join2(inputsDir, name));
6532
+ }
6533
+
6534
+ // ../witan/src/repo-signals.ts
6535
+ import { execFileSync } from "child_process";
6536
+ import { createHash } from "crypto";
6537
+ import { readFileSync as readFileSync6, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "fs";
6538
+ import { basename, join as join3, relative, resolve, sep } from "path";
6539
+ function buildWitanInputFromRepo(options) {
6540
+ assertRepoPathExists(options.repoPath);
6541
+ const generatedAt = options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
6542
+ const headSha = readGitHead(options.repoPath);
6543
+ const repoFiles = listRepoFiles(options.repoPath);
6544
+ const archetype = classifyRepoArchetype(repoFiles);
6545
+ return {
6546
+ productSlug: options.productSlug,
6547
+ productDisplayName: options.productDisplayName,
6548
+ repo: {
6549
+ path: options.repoPath,
6550
+ ...headSha ? { headSha } : {}
6551
+ },
6552
+ generatedAt,
6553
+ ...options.rubricVersion ? { rubricVersion: options.rubricVersion } : {},
6554
+ archetype: archetype.archetype,
6555
+ ...archetype.insufficientSourceReason ? { insufficientSourceReason: archetype.insufficientSourceReason } : {},
6556
+ signals: [
6557
+ ...collectRepoSignals(options.repoPath, generatedAt, repoFiles),
6558
+ ...(options.domainCollectors ?? []).map((collect) => collect(options.repoPath, repoFiles)),
6559
+ ...options.additionalSignals ?? []
6560
+ ]
6561
+ };
6562
+ }
6563
+ var SOURCE_LANGUAGES = [
6564
+ {
6565
+ name: "JS/TS",
6566
+ tier: "deep",
6567
+ extensions: ["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs"]
6568
+ },
6569
+ { name: "Python", tier: "deep", extensions: ["py"] },
6570
+ { name: "Go", tier: "partial", extensions: ["go"] },
6571
+ { name: "Rust", tier: "partial", extensions: ["rs"] },
6572
+ { name: "Java", tier: "partial", extensions: ["java"] },
6573
+ { name: "Ruby", tier: "partial", extensions: ["rb"] },
6574
+ { name: "PHP", tier: "partial", extensions: ["php"] },
6575
+ { name: "C#", tier: "partial", extensions: ["cs"] },
6576
+ { name: "C/C++", tier: "partial", extensions: ["cpp", "cc", "cxx", "c", "h", "hpp"] },
6577
+ { name: "Swift", tier: "partial", extensions: ["swift"] },
6578
+ { name: "Kotlin", tier: "partial", extensions: ["kt", "kts"] },
6579
+ { name: "Dart", tier: "partial", extensions: ["dart"] },
6580
+ { name: "Elixir", tier: "partial", extensions: ["ex", "exs"] },
6581
+ { name: "Scala", tier: "partial", extensions: ["scala"] },
6582
+ { name: "shell", tier: "unmodelled", extensions: ["sh", "bash", "zsh"] },
6583
+ { name: "R", tier: "unmodelled", extensions: ["r"] },
6584
+ { name: "Lua", tier: "unmodelled", extensions: ["lua"] },
6585
+ { name: "Julia", tier: "unmodelled", extensions: ["jl"] },
6586
+ { name: "Haskell", tier: "unmodelled", extensions: ["hs"] },
6587
+ { name: "Terraform", tier: "unmodelled", extensions: ["tf", "tfvars"] },
6588
+ { name: "SQL", tier: "unmodelled", extensions: ["sql"] },
6589
+ { name: "Perl", tier: "unmodelled", extensions: ["pl", "pm"] },
6590
+ { name: "OCaml", tier: "unmodelled", extensions: ["ml", "mli"] },
6591
+ { name: "Clojure", tier: "unmodelled", extensions: ["clj", "cljs", "cljc"] },
6592
+ { name: "Erlang", tier: "unmodelled", extensions: ["erl", "hrl"] },
6593
+ { name: "Nim", tier: "unmodelled", extensions: ["nim"] },
6594
+ { name: "Zig", tier: "unmodelled", extensions: ["zig"] },
6595
+ { name: "F#", tier: "unmodelled", extensions: ["fs", "fsx"] },
6596
+ { name: "Groovy", tier: "unmodelled", extensions: ["groovy", "gvy"] }
6597
+ ];
6598
+ var SOURCE_EXTENSION_PATTERN = new RegExp(
6599
+ `\\.(${SOURCE_LANGUAGES.flatMap((language) => language.extensions).join("|")})$`,
6600
+ "i"
6601
+ );
6602
+ var BUNDLED_BINARY_EXTENSION_PATTERN = /\.(vsix|zip|tgz|whl|exe|dmg|pkg|msi|jar|war|apk|ipa|dll|dylib)$/i;
6603
+ var DOCS_OR_MEDIA_EXTENSION_PATTERN = /\.(md|mdx|rst|png|jpe?g|gif|svg|webp|ico|pdf)$/i;
6604
+ var KNOWN_NON_SOURCE_EXTENSION_PATTERN = /\.(json|jsonc|json5|ya?ml|toml|txt|lock|xml|csv|tsv|ini|cfg|conf|properties|env|sum|mod|graphql|gql|proto|editorconfig|gitignore|gitattributes|npmrc|nvmrc|dockerignore|log|txt\.license)$/i;
6605
+ var INGEST_POINTER = "To assess a closed/bundled tool, ingest its scanner output via --ingest <sarif|scorecard>.";
6606
+ var SOURCE_DOMINANCE_RATIO_THRESHOLD = 0.2;
6607
+ function classifyRepoArchetype(repoFiles) {
6608
+ const totalFileCount = repoFiles.length;
6609
+ const sourceFileCount = repoFiles.filter((file) => SOURCE_EXTENSION_PATTERN.test(file)).length;
6610
+ if (totalFileCount === 0) {
6611
+ return {
6612
+ archetype: "empty",
6613
+ sourceFileCount: 0,
6614
+ totalFileCount: 0,
6615
+ insufficientSourceReason: "Repository has no tracked files \u2014 there is nothing to certify."
4773
6616
  };
4774
6617
  }
4775
- const docsFiles = repoFiles.filter((file) => DOCS_OR_MEDIA_EXTENSION_PATTERN.test(file));
4776
- if (docsFiles.length > 0 && docsFiles.length === totalFileCount) {
6618
+ const unrecognisedSourceFiles = collectUnrecognisedSourceFiles(repoFiles);
6619
+ if (sourceFileCount === 0) {
6620
+ const binaryFiles = repoFiles.filter((file) => BUNDLED_BINARY_EXTENSION_PATTERN.test(file));
6621
+ if (binaryFiles.length > 0) {
6622
+ const sample = binaryFiles[0];
6623
+ return {
6624
+ archetype: "binary_only",
6625
+ sourceFileCount,
6626
+ totalFileCount,
6627
+ insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a binary/bundled-distribution tree (e.g. ${sample ? basename(sample) : "a packaged artifact"}) \u2014 cejel rates source, not binaries. ${INGEST_POINTER}`
6628
+ };
6629
+ }
6630
+ const docsFiles = repoFiles.filter((file) => DOCS_OR_MEDIA_EXTENSION_PATTERN.test(file));
6631
+ if (docsFiles.length > 0 && docsFiles.length === totalFileCount) {
6632
+ return {
6633
+ archetype: "docs_only",
6634
+ sourceFileCount,
6635
+ totalFileCount,
6636
+ insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a docs/distribution tree (README/markdown/media), not a source tree \u2014 cejel rates source, not docs. ${INGEST_POINTER}`
6637
+ };
6638
+ }
6639
+ if (unrecognisedSourceFiles.length > 0) {
6640
+ return unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles);
6641
+ }
6642
+ return { archetype: "source", sourceFileCount, totalFileCount };
6643
+ }
6644
+ if (unrecognisedSourceFiles.length === 0) {
4777
6645
  return {
4778
- archetype: "docs_only",
6646
+ archetype: isLikelyMonorepo(repoFiles) ? "monorepo" : "source",
4779
6647
  sourceFileCount,
4780
- totalFileCount,
4781
- insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a docs/distribution tree (README/markdown/media), not a source tree \u2014 cejel rates source, not docs. ${INGEST_POINTER}`
6648
+ totalFileCount
4782
6649
  };
4783
6650
  }
4784
- return { archetype: "source", sourceFileCount, totalFileCount };
6651
+ const dominanceRatio = sourceFileCount / (sourceFileCount + unrecognisedSourceFiles.length);
6652
+ if (dominanceRatio >= SOURCE_DOMINANCE_RATIO_THRESHOLD) {
6653
+ return {
6654
+ archetype: isLikelyMonorepo(repoFiles) ? "monorepo" : "source",
6655
+ sourceFileCount,
6656
+ totalFileCount
6657
+ };
6658
+ }
6659
+ return unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles);
6660
+ }
6661
+ function collectUnrecognisedSourceFiles(repoFiles) {
6662
+ return repoFiles.filter((file) => {
6663
+ const base = basename(file);
6664
+ if (!/\.([a-zA-Z0-9_]+)$/.test(base)) return false;
6665
+ if (KNOWN_NON_SOURCE_EXTENSION_PATTERN.test(base)) return false;
6666
+ if (DOCS_OR_MEDIA_EXTENSION_PATTERN.test(base)) return false;
6667
+ if (BUNDLED_BINARY_EXTENSION_PATTERN.test(base)) return false;
6668
+ if (SOURCE_EXTENSION_PATTERN.test(base)) return false;
6669
+ return true;
6670
+ });
6671
+ }
6672
+ function extensionsByFileCountDescending(files) {
6673
+ const counts = /* @__PURE__ */ new Map();
6674
+ for (const file of files) {
6675
+ const match = /\.([a-zA-Z0-9_]+)$/.exec(basename(file));
6676
+ const ext = match?.[1];
6677
+ if (!ext) continue;
6678
+ const key = `.${ext.toLowerCase()}`;
6679
+ counts.set(key, (counts.get(key) ?? 0) + 1);
6680
+ }
6681
+ return [...counts.entries()].sort(([extA, countA], [extB, countB]) => countB - countA || extA.localeCompare(extB)).map(([ext]) => ext);
6682
+ }
6683
+ function unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles) {
6684
+ const sample = extensionsByFileCountDescending(unrecognisedSourceFiles).slice(0, 6).join(", ");
6685
+ const candidateCount = sourceFileCount + unrecognisedSourceFiles.length;
6686
+ const dominancePct = candidateCount > 0 ? (sourceFileCount / candidateCount * 100).toFixed(1) : "0.0";
6687
+ const thresholdPct = (SOURCE_DOMINANCE_RATIO_THRESHOLD * 100).toFixed(0);
6688
+ const measuredClause = sourceFileCount > 0 ? `${sourceFileCount} of ${candidateCount} source-shaped file(s) (${dominancePct}%) are in a language Cejel reads \u2014 below the ${thresholdPct}% dominance threshold a score would need to be meaningful (${totalFileCount} tracked files in total; manifests, lockfiles, docs, media and bundled binaries are excluded from both sides of the ratio)` : `0 of ${totalFileCount} tracked file(s) matched a recognised source extension`;
6689
+ return {
6690
+ archetype: "unrecognised_ecosystem",
6691
+ sourceFileCount,
6692
+ totalFileCount,
6693
+ insufficientSourceReason: `Cejel does not yet read this repository's dominant source language(s) (${sample}) \u2014 ${measuredClause}. Cejel abstains from a verdict rather than score a repository whose recognised source is incidental rather than dominant; the Criterion Profile and Measured coverage below show exactly which dimensions were and were not measured. ${INGEST_POINTER}`
6694
+ };
4785
6695
  }
4786
6696
  function isLikelyMonorepo(repoFiles) {
4787
6697
  const packageRoots = new Set(
@@ -4792,7 +6702,7 @@ function isLikelyMonorepo(repoFiles) {
4792
6702
  function assertRepoPathExists(repoPath) {
4793
6703
  let stats;
4794
6704
  try {
4795
- stats = statSync(repoPath);
6705
+ stats = statSync2(repoPath);
4796
6706
  } catch {
4797
6707
  throw new Error(`Cejel: path not found: ${repoPath}`);
4798
6708
  }
@@ -4820,14 +6730,14 @@ function collectRepoSignals(repoPath, generatedAt, repoFiles) {
4820
6730
  const a5Signal = collectA5ClaimRealityEvidence(repoPath, repoFiles);
4821
6731
  const b1Signal = buildNotApplicableSignal(
4822
6732
  "B1",
4823
- "Dispatch-trace process signal is not evaluated for external repos."
6733
+ "Repository scans do not evaluate the dispatch-trace process dimension."
4824
6734
  );
4825
6735
  const b2Signal = collectB2PrTraceEvidence(repoPath, repoFiles);
4826
6736
  const b3Signal = collectB3CiDisciplineEvidence(repoPath, repoFiles, mono);
4827
6737
  const b4Signal = collectB4AuditEvidence(repoPath, repoFiles, generatedAt);
4828
6738
  const b5Signal = buildNotApplicableSignal(
4829
6739
  "B5",
4830
- "Learning-trace process signal is not evaluated for external repos."
6740
+ "Repository scans do not evaluate the learning-trace process dimension."
4831
6741
  );
4832
6742
  const b6Signal = collectB6PrivilegedOpsGatingEvidence(repoPath, repoFiles);
4833
6743
  for (const signal of [
@@ -4860,7 +6770,7 @@ function collectA1TestIntegrityEvidence(repoPath, repoFiles) {
4860
6770
  const runnerFiles = repoFiles.filter(isTestRunnerConfig).slice(0, 6);
4861
6771
  const coverageFiles = repoFiles.filter(isCoverageConfig).slice(0, 4);
4862
6772
  const packageJson = findRootPackageJson(repoFiles);
4863
- const packageScripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
6773
+ const packageScripts = packageJson ? readPackageScripts(join3(repoPath, packageJson)) : /* @__PURE__ */ new Map();
4864
6774
  const coveragePercent = readCoveragePercent(repoPath, coverageFiles);
4865
6775
  const ciWorkflows = repoFiles.filter(isCiWorkflow);
4866
6776
  const ciTestWorkflow = ciWorkflows.find(
@@ -5014,8 +6924,7 @@ function collectA1TestIntegrityEvidence(repoPath, repoFiles) {
5014
6924
  };
5015
6925
  }
5016
6926
  function collectA2IsolationEvidence(repoPath, repoFiles) {
5017
- const alfredEvidence = [];
5018
- const evidence = [...alfredEvidence];
6927
+ const evidence = [];
5019
6928
  const findings = [];
5020
6929
  const gitignore = repoFiles.find((file) => basename(file) === ".gitignore");
5021
6930
  const envExamples = repoFiles.filter((file) => isEnvTemplatePath(file));
@@ -5031,47 +6940,43 @@ function collectA2IsolationEvidence(repoPath, repoFiles) {
5031
6940
  repoPath,
5032
6941
  repoFiles.filter(isImplementationFile).slice(0, 60)
5033
6942
  );
5034
- if (alfredEvidence.length === 0) {
5035
- const implFiles = repoFiles.filter(isImplementationFile);
5036
- const gitignoreHasEnvRule = gitignore != null && fileContains(repoPath, gitignore, /^\.env(\*|\b)|\.env\./m);
5037
- const committedEnvFilePath = repoFiles.find(
5038
- (f) => /(?:^|\/)\.env(?:\.|$)/i.test(f) && !isEnvTemplatePath(f)
6943
+ const implFiles = repoFiles.filter(isImplementationFile);
6944
+ const gitignoreHasEnvRule = gitignore != null && fileContains(repoPath, gitignore, /^\.env(\*|\b)|\.env\./m);
6945
+ const committedEnvFilePath = repoFiles.find(
6946
+ (f) => /(?:^|\/)\.env(?:\.|$)/i.test(f) && !isEnvTemplatePath(f)
6947
+ );
6948
+ const hasEnvInHistory = committedEnvFilePath === void 0 && hasEnvPathInGitHistory(repoPath);
6949
+ const dbLayerImportFile = migrationFiles.length === 0 ? implFiles.slice(0, 30).find((f) => fileContains(repoPath, f, DB_CLIENT_PATTERN)) : void 0;
6950
+ const hasDataLayer = migrationFiles.length > 0 || dbLayerImportFile !== void 0;
6951
+ const hasSecretsSurface = envExamples.length > 0 || committedEnvFilePath !== void 0 || gitignoreHasEnvRule || hasEnvInHistory;
6952
+ if (!hasDataLayer && !hasSecretsSurface && !hasConfirmedSecretFinding && !cryptoHygiene.hasSurface) {
6953
+ return buildNotApplicableSignal(
6954
+ "A2",
6955
+ "No data layer (DB/ORM/migrations) or ratable secrets surface detected \u2014 A2 not applicable to this repo archetype. A ratable surface requires .env* files, .gitignore .env rule, committed/history .env path, or detected signing/HMAC/secret-comparison code; bare env reads (process.env / os.environ / std::env::) do not qualify."
5039
6956
  );
5040
- const hasEnvInHistory = committedEnvFilePath === void 0 && hasEnvPathInGitHistory(repoPath);
5041
- const dbLayerImportFile = migrationFiles.length === 0 ? implFiles.slice(0, 30).find((f) => fileContains(repoPath, f, DB_CLIENT_PATTERN)) : void 0;
5042
- const hasDataLayer = migrationFiles.length > 0 || dbLayerImportFile !== void 0;
5043
- const hasSecretsSurface = envExamples.length > 0 || committedEnvFilePath !== void 0 || gitignoreHasEnvRule || hasEnvInHistory;
5044
- if (!hasDataLayer && !hasSecretsSurface && !hasConfirmedSecretFinding && !cryptoHygiene.hasSurface) {
5045
- return buildNotApplicableSignal(
5046
- "A2",
5047
- "No data layer (DB/ORM/migrations) or ratable secrets surface detected \u2014 A2 not applicable to this repo archetype. A ratable surface requires .env* files, .gitignore .env rule, committed/history .env path, or detected signing/HMAC/secret-comparison code; bare env reads (process.env / os.environ / std::env::) do not qualify."
5048
- );
5049
- }
5050
- if (committedEnvFilePath) {
5051
- evidence.push(
5052
- evidenceForRelative(
5053
- repoPath,
5054
- committedEnvFilePath,
5055
- "secret_scan",
5056
- "Committed .env file in repository tree"
5057
- )
5058
- );
5059
- } else if (hasEnvInHistory) {
5060
- evidence.push({
5061
- kind: "secret_scan",
5062
- label: ".env path detected in git history",
5063
- path: ".git",
5064
- contentHash: readGitHead(repoPath) ?? "env-history-scan"
5065
- });
5066
- } else if (migrationFiles[0] != null) {
5067
- evidence.push(
5068
- evidenceForRelative(repoPath, migrationFiles[0], "artifact", "Data layer migration")
5069
- );
5070
- } else if (dbLayerImportFile != null) {
5071
- evidence.push(
5072
- evidenceForRelative(repoPath, dbLayerImportFile, "artifact", "DB client import")
5073
- );
5074
- }
6957
+ }
6958
+ if (committedEnvFilePath) {
6959
+ evidence.push(
6960
+ evidenceForRelative(
6961
+ repoPath,
6962
+ committedEnvFilePath,
6963
+ "secret_scan",
6964
+ "Committed .env file in repository tree"
6965
+ )
6966
+ );
6967
+ } else if (hasEnvInHistory) {
6968
+ evidence.push({
6969
+ kind: "secret_scan",
6970
+ label: ".env path detected in git history",
6971
+ path: ".git",
6972
+ contentHash: readGitHead(repoPath) ?? "env-history-scan"
6973
+ });
6974
+ } else if (migrationFiles[0] != null) {
6975
+ evidence.push(
6976
+ evidenceForRelative(repoPath, migrationFiles[0], "artifact", "Data layer migration")
6977
+ );
6978
+ } else if (dbLayerImportFile != null) {
6979
+ evidence.push(evidenceForRelative(repoPath, dbLayerImportFile, "artifact", "DB client import"));
5075
6980
  }
5076
6981
  const rlsMigration = migrationFiles.find((file) => fileContains(repoPath, file, RLS_PATTERN));
5077
6982
  const tenantScopedFile = migrationFiles.find(
@@ -5231,7 +7136,8 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
5231
7136
  const findings = [];
5232
7137
  let hasSurface = false;
5233
7138
  let insecureFound = false;
5234
- const timingSafeFile = implFiles.find(
7139
+ const productionImplFiles = implFiles.filter(isProductionSourcePath);
7140
+ const timingSafeFile = productionImplFiles.find(
5235
7141
  (file) => fileContains(repoPath, file, TIMING_SAFE_COMPARE_PATTERN)
5236
7142
  );
5237
7143
  if (timingSafeFile) {
@@ -5245,7 +7151,7 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
5245
7151
  )
5246
7152
  );
5247
7153
  }
5248
- const canonicalSignFile = implFiles.find(
7154
+ const canonicalSignFile = productionImplFiles.find(
5249
7155
  (file) => fileContains(repoPath, file, CANONICAL_SERIALIZE_PATTERN) && fileContains(repoPath, file, SIGN_OR_HMAC_CALL_PATTERN)
5250
7156
  );
5251
7157
  if (canonicalSignFile) {
@@ -5259,20 +7165,31 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
5259
7165
  )
5260
7166
  );
5261
7167
  }
5262
- const insecureCompareFile = implFiles.find(
5263
- (file) => fileContains(repoPath, file, INSECURE_SECRET_COMPARE_PATTERN)
5264
- );
7168
+ let insecureCompareFile = null;
7169
+ let insecureCompareLine = null;
7170
+ for (const file of implFiles) {
7171
+ const line = findInsecureSecretCompareLine(repoPath, file);
7172
+ if (line != null) {
7173
+ insecureCompareFile = file;
7174
+ insecureCompareLine = line;
7175
+ break;
7176
+ }
7177
+ }
5265
7178
  if (insecureCompareFile) {
5266
- hasSurface = true;
5267
- insecureFound = true;
7179
+ const isTestPath = isTestOrFixturePath(insecureCompareFile);
7180
+ if (!isTestPath) {
7181
+ hasSurface = true;
7182
+ insecureFound = true;
7183
+ }
5268
7184
  findings.push({
5269
- severity: "warning",
5270
- summary: "A secret/HMAC/signature value appears compared with a plain equality operator instead of a constant-time comparison \u2014 potential timing side-channel.",
5271
- evidence: evidenceForRelative(
7185
+ severity: isTestPath ? "info" : "warning",
7186
+ summary: isTestPath ? `A secret/HMAC/signature comparison via plain equality appears in a test/fixture file (${insecureCompareFile}) \u2014 likely a test assertion, not a production timing leak; verify.` : "A secret/HMAC/signature value appears compared with a plain equality operator instead of a constant-time comparison \u2014 potential timing side-channel.",
7187
+ evidence: evidenceForRelativeAtLine(
5272
7188
  repoPath,
5273
7189
  insecureCompareFile,
5274
7190
  "artifact",
5275
- "Non-constant-time secret comparison"
7191
+ "Non-constant-time secret comparison",
7192
+ insecureCompareLine
5276
7193
  )
5277
7194
  });
5278
7195
  }
@@ -5280,16 +7197,25 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
5280
7197
  (file) => fileContains(repoPath, file, UNSORTED_JSON_SIGN_PATTERN) && !fileContains(repoPath, file, CANONICAL_SERIALIZE_PATTERN)
5281
7198
  );
5282
7199
  if (unsortedSignFile) {
5283
- hasSurface = true;
5284
- insecureFound = true;
7200
+ const isTestPath = isTestOrFixturePath(unsortedSignFile);
7201
+ if (!isTestPath) {
7202
+ hasSurface = true;
7203
+ insecureFound = true;
7204
+ }
7205
+ const unsortedSignLine = findFirstMatchingLine(
7206
+ repoPath,
7207
+ unsortedSignFile,
7208
+ UNSORTED_JSON_SIGN_PATTERN
7209
+ );
5285
7210
  findings.push({
5286
- severity: "warning",
5287
- summary: "A signature/HMAC appears computed directly over JSON.stringify output with no canonical key ordering in the same file \u2014 signatures may not verify across equivalent payloads.",
5288
- evidence: evidenceForRelative(
7211
+ severity: isTestPath ? "info" : "warning",
7212
+ summary: isTestPath ? `Signing over unsorted JSON serialization appears in a test/fixture file (${unsortedSignFile}) \u2014 likely a test assertion, not a production signing gap; verify.` : "A signature/HMAC appears computed directly over JSON.stringify output with no canonical key ordering in the same file \u2014 signatures may not verify across equivalent payloads.",
7213
+ evidence: evidenceForRelativeAtLine(
5289
7214
  repoPath,
5290
7215
  unsortedSignFile,
5291
7216
  "artifact",
5292
- "Signing over unsorted JSON serialization"
7217
+ "Signing over unsorted JSON serialization",
7218
+ unsortedSignLine
5293
7219
  )
5294
7220
  });
5295
7221
  }
@@ -5305,7 +7231,7 @@ function collectA3ProdReadinessEvidence(repoPath, repoFiles) {
5305
7231
  const evidence = [];
5306
7232
  const findings = [];
5307
7233
  const packageJson = findRootPackageJson(repoFiles);
5308
- const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
7234
+ const scripts = packageJson ? readPackageScripts(join3(repoPath, packageJson)) : /* @__PURE__ */ new Map();
5309
7235
  const workflows = repoFiles.filter(isCiWorkflow);
5310
7236
  const workflow = workflows[0];
5311
7237
  const deployConfigs = repoFiles.filter(isDeployConfig);
@@ -5579,45 +7505,6 @@ function hasDeclaredVersionConstraint(dependency) {
5579
7505
  return /^v?\d/.test(trimmed);
5580
7506
  }
5581
7507
  function collectA5ClaimRealityEvidence(repoPath, repoFiles) {
5582
- const alfredEvidence = [];
5583
- if (alfredEvidence.length > 0) {
5584
- const claimStats = readClaimRealityStats(repoPath);
5585
- return {
5586
- criterionId: "A5",
5587
- positiveEvidence: alfredEvidence,
5588
- findings: [],
5589
- metrics: [
5590
- metric(
5591
- "claim_match_rate",
5592
- "Claim match rate",
5593
- claimStats?.matchRate ?? 0,
5594
- 1,
5595
- 0.6,
5596
- "ratio",
5597
- "Measures supported and partially supported claims in the structured reconciliation artifact."
5598
- ),
5599
- metric(
5600
- "claim_registry_depth",
5601
- "Claim registry depth",
5602
- claimStats?.claimCount ?? 0,
5603
- Math.max(claimStats?.claimCount ?? 0, 8),
5604
- 0.25,
5605
- "claims",
5606
- "Credits the number of concrete claims reconciled without giving unlimited credit for one artifact."
5607
- ),
5608
- metric(
5609
- "reconciliation_artifact_depth",
5610
- "Reconciliation artifact depth",
5611
- alfredEvidence.length,
5612
- 3,
5613
- 0.15,
5614
- "artifacts",
5615
- "Credits implementation, Markdown, and structured reconciliation artifacts."
5616
- )
5617
- ],
5618
- notes: "A5 is evidenced by deterministic claim-vs-reality implementation and report artifacts, not a model-opinion verdict."
5619
- };
5620
- }
5621
7508
  const claimDoc = repoFiles.find((file) => /(^|\/)(README|readme)\.md$/.test(file)) ?? repoFiles.find((file) => /(^|\/)docs\/.*\.(md|mdx)$/.test(file));
5622
7509
  if (!claimDoc) {
5623
7510
  return buildNotApplicableSignal(
@@ -5778,7 +7665,7 @@ function collectB2PrTraceEvidence(repoPath, repoFiles) {
5778
7665
  function collectB3CiDisciplineEvidence(repoPath, repoFiles, mono) {
5779
7666
  const evidence = [];
5780
7667
  const packageJson = findRootPackageJson(repoFiles);
5781
- const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
7668
+ const scripts = packageJson ? readPackageScripts(join3(repoPath, packageJson)) : /* @__PURE__ */ new Map();
5782
7669
  const workflows = repoFiles.filter(isCiWorkflow);
5783
7670
  const workflow = workflows[0];
5784
7671
  const rootWorkflows = mono ? mono.sharedFiles.filter(isCiWorkflow) : [];
@@ -6044,11 +7931,20 @@ function collectB6PrivilegedOpsGatingEvidence(repoPath, repoFiles) {
6044
7931
  var CPP_TEST_FRAMEWORK_PATTERN = /<gtest\/gtest\.h>|<catch2\/|<doctest\/|<boost\/test\/|"gtest\/gtest\.h"|"catch2\//;
6045
7932
  var CPP_TEST_MACRO_PATTERN = /\bTEST\s*\(|\bTEST_F\s*\(|\bTEST_CASE\s*\(|\bSECTION\s*\(|\bCATCH_|BOOST_AUTO_TEST_CASE\b|BOOST_FIXTURE_TEST_CASE\b/;
6046
7933
  var CPP_CONTENT_SCAN_LIMIT = 150;
6047
- var TEST_OR_FIXTURE_DIR_PATTERN = /(^|\/)(__tests__|__mocks__|__fixtures__|tests|test|fixtures|testdata|e2e|cypress)(\/|$)/i;
6048
- var TEST_OR_FIXTURE_FILE_PATTERN = /\.(test|spec|stories)\.[^/]+$/i;
7934
+ var NON_PRODUCTION_DIR_PATTERN = /(^|\/)(__tests__|__mocks__|__fixtures__|tests?|fixtures?|testdata|e2e|cypress|examples?|samples?|demos?)(\/|$)/i;
7935
+ var NON_PRODUCTION_FILE_SUFFIX_PATTERN = /\.(test|spec|stories)\.[^/]+$/i;
6049
7936
  function isTestOrFixturePath(path) {
6050
- return TEST_OR_FIXTURE_DIR_PATTERN.test(path) || TEST_OR_FIXTURE_FILE_PATTERN.test(path);
7937
+ return NON_PRODUCTION_DIR_PATTERN.test(path) || NON_PRODUCTION_FILE_SUFFIX_PATTERN.test(path);
7938
+ }
7939
+ function isProductionSourcePath(path) {
7940
+ return !isTestOrFixturePath(path);
7941
+ }
7942
+ function isTestFile(file) {
7943
+ return /(^|\/)(__tests__|test|tests|spec)\/.*\.(?:[cm]?[jt]sx?|py|go|rs|java|rb|cpp|cc|cxx)$/.test(
7944
+ file
7945
+ ) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(file) || /(^|\/)test_.*\.py$/.test(file) || /_test\.go$/.test(file) || /(^|\/)test_.*\.(cpp|cc|cxx)$/.test(file) || /_(test|tests)\.(cpp|cc|cxx)$/.test(file) || /Tests?\.(java|kt)$/.test(file) || /(_test|_spec)\.(rs|rb|php|swift|kt)$/.test(file);
6051
7946
  }
7947
+ var NAME_SHAPED_TEST_FILE_PATTERN = /\.(test|spec)\.[cm]?[jt]sx?$|(^|\/)__tests__\/|(^|\/)test_[^/]*\.py$|(^|\/)tests?\.py$|_test\.go$|(^|\/)test_[^/]*\.(cpp|cc|cxx)$|_(test|tests)\.(cpp|cc|cxx)$|Tests?\.(java|kt)$|(_test|_spec)\.(rs|rb|php|swift|kt)$/;
6052
7948
  var TEST_RUNNER_PATTERN = /\b(vitest|jest|mocha|ava|tap|pytest|go test|cargo test|rspec|phpunit|gradle test|mvn test)\b/i;
6053
7949
  var CI_TEST_COMMAND_PATTERN = /\b(pytest|go\s+test|cargo\s+test|mvn\s+test|gradle\s+test|ctest|make\s+test|jest|vitest|mocha|rspec|phpunit|pnpm\s+test|npm\s+test|yarn\s+test|node\s+--test|node:test)\b/i;
6054
7950
  var CI_LINT_COMMAND_PATTERN = /\b(eslint|pylint|flake8|black|ruff)\b/i;
@@ -6081,7 +7977,28 @@ var HEAVY_TEST_DEPENDENCY_NAME_PATTERN = /^(?:jest|mocha|ava|tape|jasmine|karma)
6081
7977
  var TIMING_SAFE_COMPARE_PATTERN = /\btiming[-_]?safe[-_]?(?:equal|compare)\b|crypto\.timingSafeEqual\s*\(/i;
6082
7978
  var CANONICAL_SERIALIZE_PATTERN = /\bcanonicalize\s*\(|\bcanonicalJson\b|\bstableStringify\s*\(|json-stable-stringify|safe-stable-stringify|\bsortKeys\s*\(/i;
6083
7979
  var SIGN_OR_HMAC_CALL_PATTERN = /\bcreateHmac\s*\(|\bcreateSign\s*\(|\.sign\s*\(/;
6084
- var INSECURE_SECRET_COMPARE_PATTERN = /\b\w*(?:hmac|signature|\bmac|digest)\w*\s*(?:===|!==)\s*(?!['"`]|undefined\b|null\b)\w/i;
7980
+ var INSECURE_SECRET_COMPARE_LINE_PATTERN = /\b\w*(?:hmac|signature|\bmac|digest)\w*\s*(===|!==)\s*(?!['"`]|undefined\b|null\b)([\w.]+(?:\s*[-+]\s*\d+)?)/i;
7981
+ var NUMERIC_SHAPED_OPERAND_PATTERN = /^-?\d+$|\.(?:length|len|size|count)\b|(?:length|index|idx|offset|count|size|len)$/i;
7982
+ function lineHasInsecureSecretCompare(line) {
7983
+ const match = INSECURE_SECRET_COMPARE_LINE_PATTERN.exec(line);
7984
+ const operand = match?.[2];
7985
+ if (!operand) return false;
7986
+ return !NUMERIC_SHAPED_OPERAND_PATTERN.test(operand.trim());
7987
+ }
7988
+ function findInsecureSecretCompareLine(repoPath, file) {
7989
+ const fullPath = join3(repoPath, file);
7990
+ if (!isRegularFile(fullPath)) return null;
7991
+ const lines = readFileSync6(fullPath, "utf8").split("\n");
7992
+ const index = lines.findIndex((line) => lineHasInsecureSecretCompare(line));
7993
+ return index === -1 ? null : index + 1;
7994
+ }
7995
+ function findFirstMatchingLine(repoPath, file, pattern) {
7996
+ const fullPath = join3(repoPath, file);
7997
+ if (!isRegularFile(fullPath)) return null;
7998
+ const lines = readFileSync6(fullPath, "utf8").split("\n");
7999
+ const index = lines.findIndex((line) => pattern.test(line));
8000
+ return index === -1 ? null : index + 1;
8001
+ }
6085
8002
  var UNSORTED_JSON_SIGN_PATTERN = /\.update\s*\(\s*JSON\.stringify\s*\(|\.sign\s*\([^)]*JSON\.stringify\s*\(/;
6086
8003
  var KILL_SWITCH_NAME_FRAGMENT = "kill[_-]?switch|emergency[_-]?stop|circuit[_-]?breaker|safety[_-]?(?:toggle|gate|switch)|governance[_-]?(?:toggle|gate)";
6087
8004
  var KILL_SWITCH_NAME_PATTERN = new RegExp(`\\b(?:${KILL_SWITCH_NAME_FRAGMENT})\\b`, "i");
@@ -6193,13 +8110,13 @@ function listGitTrackedFiles(repoPath) {
6193
8110
  function visitRepoDir(repoPath, dirPath, files) {
6194
8111
  let entries;
6195
8112
  try {
6196
- entries = readdirSync(dirPath, { withFileTypes: true });
8113
+ entries = readdirSync3(dirPath, { withFileTypes: true });
6197
8114
  } catch {
6198
8115
  return;
6199
8116
  }
6200
8117
  for (const entry of entries) {
6201
8118
  if (shouldSkipDir(entry.name)) continue;
6202
- const fullPath = join(dirPath, entry.name);
8119
+ const fullPath = join3(dirPath, entry.name);
6203
8120
  if (entry.isDirectory()) {
6204
8121
  visitRepoDir(repoPath, fullPath, files);
6205
8122
  continue;
@@ -6207,7 +8124,7 @@ function visitRepoDir(repoPath, dirPath, files) {
6207
8124
  if (!entry.isFile()) continue;
6208
8125
  let size;
6209
8126
  try {
6210
- size = statSync(fullPath).size;
8127
+ size = statSync2(fullPath).size;
6211
8128
  } catch {
6212
8129
  continue;
6213
8130
  }
@@ -6235,17 +8152,12 @@ function shouldSkipDir(name) {
6235
8152
  function isHardExcludedPath(path) {
6236
8153
  return HARD_EXCLUDED_PATH_PATTERN.test(path);
6237
8154
  }
6238
- function isTestFile(file) {
6239
- return /(^|\/)(__tests__|test|tests|spec)\/.*\.(?:[cm]?[jt]sx?|py|go|rs|java|rb|cpp|cc|cxx)$/.test(
6240
- file
6241
- ) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(file) || /(^|\/)test_.*\.py$/.test(file) || /_test\.go$/.test(file) || /(^|\/)test_.*\.(cpp|cc|cxx)$/.test(file) || /_(test|tests)\.(cpp|cc|cxx)$/.test(file) || /Tests?\.(java|kt)$/.test(file) || /(_test|_spec)\.(rs|rb|php|swift|kt)$/.test(file);
6242
- }
6243
8155
  function collectContentBasedCppTestFiles(repoPath, repoFiles) {
6244
8156
  const candidates = repoFiles.filter((file) => /\.(cpp|cc|cxx)$/.test(file) && !isTestFile(file)).slice(0, CPP_CONTENT_SCAN_LIMIT);
6245
8157
  return candidates.filter((file) => {
6246
- const fullPath = join(repoPath, file);
8158
+ const fullPath = join3(repoPath, file);
6247
8159
  if (!isRegularFile(fullPath)) return false;
6248
- const contents = readFileSync(fullPath, "utf8");
8160
+ const contents = readFileSync6(fullPath, "utf8");
6249
8161
  return CPP_TEST_FRAMEWORK_PATTERN.test(contents) || CPP_TEST_MACRO_PATTERN.test(contents);
6250
8162
  });
6251
8163
  }
@@ -6259,14 +8171,13 @@ var JS_TEST_ASSERTION_PATTERN = /(expect\(|assert\.|should\.|toEqual\(|toBe\(|as
6259
8171
  var CPP_TEST_ASSERTION_PATTERN = /\bEXPECT_|ASSERT_EQ\b|ASSERT_TRUE\b|ASSERT_FALSE\b|\bREQUIRE\s*\(|\bCHECK\s*\(|\bTEST\s*\(|\bTEST_F\s*\(|\bTEST_CASE\s*\(|\bSECTION\s*\(/;
6260
8172
  var MULTI_ECOSYSTEM_TEST_ASSERTION_PATTERN = /\.assert[A-Z_]\w*\s*\(|\bassert[A-Z]\w*\s*\(|\bpytest\.raises\b|\bself\.fail\s*\(|\bt\.(?:Error|Errorf|Fatal|Fatalf|Fail|FailNow)\b|\brequire\.[A-Z]\w*\s*\(|\b(?:debug_)?assert(?:_eq|_ne)?!\s*\(|\bassert_\w+\b|\$this->assert\w+\s*\(/;
6261
8173
  var SUITE_LEVEL_SKIP_PATTERN = /\b(?:describe|suite|context)\.skip\s*\(/;
6262
- var NAME_SHAPED_TEST_FILE_PATTERN = /\.(test|spec)\.[cm]?[jt]sx?$|(^|\/)__tests__\/|(^|\/)test_[^/]*\.py$|(^|\/)tests?\.py$|_test\.go$|(^|\/)test_[^/]*\.(cpp|cc|cxx)$|_(test|tests)\.(cpp|cc|cxx)$|Tests?\.(java|kt)$|(_test|_spec)\.(rs|rb|php|swift|kt)$/;
6263
8174
  function measureNonHollowTestShare(repoPath, files) {
6264
8175
  let nonHollowCount = 0;
6265
8176
  let ratedCount = 0;
6266
8177
  for (const file of files) {
6267
- const fullPath = join(repoPath, file);
8178
+ const fullPath = join3(repoPath, file);
6268
8179
  if (!isRegularFile(fullPath)) continue;
6269
- const contents = readFileSync(fullPath, "utf8");
8180
+ const contents = readFileSync6(fullPath, "utf8");
6270
8181
  const nonHollow = (JS_TEST_ASSERTION_PATTERN.test(contents) || CPP_TEST_ASSERTION_PATTERN.test(contents) || MULTI_ECOSYSTEM_TEST_ASSERTION_PATTERN.test(contents)) && !SUITE_LEVEL_SKIP_PATTERN.test(contents);
6271
8182
  if (nonHollow) {
6272
8183
  nonHollowCount += 1;
@@ -6285,17 +8196,17 @@ function countPatternMatches(repoPath, files, pattern) {
6285
8196
  const matcher = new RegExp(pattern.source, flags);
6286
8197
  let count = 0;
6287
8198
  for (const file of files) {
6288
- const fullPath = join(repoPath, file);
8199
+ const fullPath = join3(repoPath, file);
6289
8200
  if (!isRegularFile(fullPath)) continue;
6290
- count += [...readFileSync(fullPath, "utf8").matchAll(matcher)].length;
8201
+ count += [...readFileSync6(fullPath, "utf8").matchAll(matcher)].length;
6291
8202
  }
6292
8203
  return count;
6293
8204
  }
6294
8205
  function readCoveragePercent(repoPath, files) {
6295
8206
  for (const file of files) {
6296
- const fullPath = join(repoPath, file);
8207
+ const fullPath = join3(repoPath, file);
6297
8208
  if (!isRegularFile(fullPath)) continue;
6298
- const contents = readFileSync(fullPath, "utf8");
8209
+ const contents = readFileSync6(fullPath, "utf8");
6299
8210
  const summaryPercent = parseCoverageSummaryPercent(contents);
6300
8211
  if (summaryPercent !== null) return summaryPercent;
6301
8212
  const thresholdPercent = parseCoverageThresholdPercent(contents);
@@ -6339,7 +8250,7 @@ function pickPrimaryDependencyManifest(repoPath, manifests) {
6339
8250
  function readDependencySpecs(repoPath, manifests) {
6340
8251
  const specs = [];
6341
8252
  for (const manifest of manifests) {
6342
- const fullPath = join(repoPath, manifest);
8253
+ const fullPath = join3(repoPath, manifest);
6343
8254
  if (!isRegularFile(fullPath)) continue;
6344
8255
  if (manifest.endsWith("package.json")) {
6345
8256
  specs.push(...readPackageJsonDependencySpecs(fullPath));
@@ -6385,7 +8296,7 @@ function readDependencySpecs(repoPath, manifests) {
6385
8296
  }
6386
8297
  function readGoModDependencySpecs(path) {
6387
8298
  const specs = [];
6388
- const contents = readFileSync(path, "utf8");
8299
+ const contents = readFileSync6(path, "utf8");
6389
8300
  const blockPattern = /require\s*\(([^)]+)\)/gs;
6390
8301
  const singlePattern = /^require\s+(\S+)\s+(\S+)/gm;
6391
8302
  for (const blockMatch of contents.matchAll(blockPattern)) {
@@ -6406,7 +8317,7 @@ function readGoModDependencySpecs(path) {
6406
8317
  }
6407
8318
  function readCargoTomlDependencySpecs(path) {
6408
8319
  const specs = [];
6409
- const contents = readFileSync(path, "utf8");
8320
+ const contents = readFileSync6(path, "utf8");
6410
8321
  const depSectionPattern = /^\[(?:dependencies|dev-dependencies|build-dependencies)\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
6411
8322
  for (const sectionMatch of contents.matchAll(depSectionPattern)) {
6412
8323
  const section = sectionMatch[1] ?? "";
@@ -6428,7 +8339,7 @@ function readCargoTomlDependencySpecs(path) {
6428
8339
  }
6429
8340
  function readPyprojectDependencySpecs(path) {
6430
8341
  const specs = [];
6431
- const contents = readFileSync(path, "utf8");
8342
+ const contents = readFileSync6(path, "utf8");
6432
8343
  const poetrySectionPattern = /^\[tool\.poetry\.dependencies\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
6433
8344
  for (const sectionMatch of contents.matchAll(poetrySectionPattern)) {
6434
8345
  const section = sectionMatch[1] ?? "";
@@ -6462,7 +8373,7 @@ function readPyprojectDependencySpecs(path) {
6462
8373
  }
6463
8374
  function readPipfileDependencySpecs(path) {
6464
8375
  const specs = [];
6465
- const contents = readFileSync(path, "utf8");
8376
+ const contents = readFileSync6(path, "utf8");
6466
8377
  const sectionPattern = /^\[(?:packages|dev-packages)\]([\s\S]*?)(?=^\[|$(?![\s\S]))/gm;
6467
8378
  for (const sectionMatch of contents.matchAll(sectionPattern)) {
6468
8379
  for (const line of (sectionMatch[1] ?? "").split("\n")) {
@@ -6475,7 +8386,7 @@ function readPipfileDependencySpecs(path) {
6475
8386
  return specs;
6476
8387
  }
6477
8388
  function readVcpkgJsonDependencySpecs(path) {
6478
- const parsed = parseJsonObject(readFileSync(path, "utf8"));
8389
+ const parsed = parseJsonObject(readFileSync6(path, "utf8"));
6479
8390
  if (!parsed) return [];
6480
8391
  const rawDeps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
6481
8392
  const specs = [];
@@ -6491,7 +8402,7 @@ function readVcpkgJsonDependencySpecs(path) {
6491
8402
  }
6492
8403
  function readConanfileTxtDependencySpecs(path) {
6493
8404
  const specs = [];
6494
- const contents = readFileSync(path, "utf8");
8405
+ const contents = readFileSync6(path, "utf8");
6495
8406
  const requiresMatch = /^\[requires\]([\s\S]*?)(?=^\[|$(?![\s\S]))/m.exec(contents);
6496
8407
  if (!requiresMatch) return specs;
6497
8408
  for (const line of (requiresMatch[1] ?? "").split("\n")) {
@@ -6504,7 +8415,7 @@ function readConanfileTxtDependencySpecs(path) {
6504
8415
  }
6505
8416
  function readConanfilePyDependencySpecs(path) {
6506
8417
  const specs = [];
6507
- const contents = readFileSync(path, "utf8");
8418
+ const contents = readFileSync6(path, "utf8");
6508
8419
  for (const match of contents.matchAll(/self\.requires\s*\(\s*["']([\w.\-]+)\/([\w.\-]+)["']/g)) {
6509
8420
  specs.push({ name: match[1] ?? "", version: match[2] ?? "" });
6510
8421
  }
@@ -6518,7 +8429,7 @@ function readConanfilePyDependencySpecs(path) {
6518
8429
  }
6519
8430
  function readCMakeDependencySpecs(path) {
6520
8431
  const specs = [];
6521
- const contents = readFileSync(path, "utf8");
8432
+ const contents = readFileSync6(path, "utf8");
6522
8433
  for (const match of contents.matchAll(/find_package\s*\(\s*([\w]+)(?:\s+([\d.]+))?/gi)) {
6523
8434
  const name = match[1];
6524
8435
  if (!name) continue;
@@ -6533,7 +8444,7 @@ function readCMakeDependencySpecs(path) {
6533
8444
  return specs;
6534
8445
  }
6535
8446
  function readPackageJsonDependencySpecs(packageJsonPath) {
6536
- const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
8447
+ const parsed = parseJsonObject(readFileSync6(packageJsonPath, "utf8"));
6537
8448
  if (!parsed) return [];
6538
8449
  const optionalPeerNames = /* @__PURE__ */ new Set();
6539
8450
  const peerDependenciesMeta = parsed.peerDependenciesMeta;
@@ -6560,7 +8471,7 @@ function readPackageJsonDependencySpecs(packageJsonPath) {
6560
8471
  return specs;
6561
8472
  }
6562
8473
  function readRequirementsDependencySpecs(path) {
6563
- return readFileSync(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
8474
+ return readFileSync6(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
6564
8475
  const [name = line, version = ""] = line.split(/[<>=~!]=?/, 2);
6565
8476
  return { name: name.trim(), version: line.includes("==") ? version.trim() : line };
6566
8477
  });
@@ -6575,33 +8486,10 @@ function isPinnedDependencyVersion(version) {
6575
8486
  if (trimmed === "find") return false;
6576
8487
  return /^\d+\.\d+(?:\.\d+)?(?:[-+][0-9A-Za-z.-]+)?$/.test(trimmed);
6577
8488
  }
6578
- function readClaimRealityStats(repoPath) {
6579
- const path = join(repoPath, "docs/witan/claim_reality_reconciliation.json");
6580
- if (!isRegularFile(path)) return null;
6581
- const parsed = parseJsonObject(readFileSync(path, "utf8"));
6582
- const claims = Array.isArray(parsed?.claims) ? parsed.claims : [];
6583
- if (claims.length === 0) return null;
6584
- const totalScore = claims.reduce((sum, claim) => {
6585
- if (!isRecord(claim) || typeof claim.status !== "string") return sum;
6586
- return sum + scoreClaimRealityStatus(claim.status);
6587
- }, 0);
6588
- return {
6589
- claimCount: claims.length,
6590
- matchRate: Math.round(totalScore / claims.length * 1e3) / 1e3
6591
- };
6592
- }
6593
- function scoreClaimRealityStatus(status) {
6594
- const normalized = status.toLowerCase();
6595
- if (/supported|verified|matched|true/.test(normalized) && !/unsupported/.test(normalized)) {
6596
- return 1;
6597
- }
6598
- if (/partial|mixed|needs[-_ ]?evidence/.test(normalized)) return 0.5;
6599
- return 0;
6600
- }
6601
8489
  function workflowTargetsDefaultBranch(repoPath, file) {
6602
- const fullPath = join(repoPath, file);
8490
+ const fullPath = join3(repoPath, file);
6603
8491
  if (!isRegularFile(fullPath)) return false;
6604
- const contents = readFileSync(fullPath, "utf8").toLowerCase();
8492
+ const contents = readFileSync6(fullPath, "utf8").toLowerCase();
6605
8493
  return /\bpull_request\b/.test(contents) || /\bbranches:\s*\[[^\]]*\b(main|master)\b[^\]]*\]/.test(contents) || /\bbranches:\s*\n\s*-\s*(main|master)\b/.test(contents);
6606
8494
  }
6607
8495
  function isPrMergeCommit(commit) {
@@ -6637,7 +8525,6 @@ function isExplicitDeployTarget(file) {
6637
8525
  return /^(vercel|netlify|fly|render|railway)\.(json|toml|ya?ml)$/.test(file) || /^docker-compose\.ya?ml$/.test(file) || /^Procfile$/.test(file) || /^app\.ya?ml$/.test(file) || /^serverless\.ya?ml$/.test(file) || /^(k8s|kubernetes|manifests?)\/.+\.ya?ml$/i.test(file) || /^(charts?|helm)\/.+\.ya?ml$/i.test(file);
6638
8526
  }
6639
8527
  var MAIN_ENTRYPOINT_FILE_PATTERN = /(^|\/)(main|server|app|wsgi|asgi|index|entry|start|run)\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs)$/i;
6640
- var EXAMPLE_OR_TEST_DIR_PATTERN = /(?:^|\/)(examples?|samples?|demos?|tests?|__tests__|spec|fixtures?)(?:\/|$)/i;
6641
8528
  var SERVER_ENTRYPOINT_PATTERN = /\bapp\.listen\s*\(|\bserver\.listen\s*\(\s*(?:PORT|port|\d+)|http\.ListenAndServe\s*\(|http\.ListenAndServeTLS\s*\(|axum::Server(?:::|\.)|actix_web::HttpServer(?:::|\.)|uvicorn\.run\s*\(/;
6642
8529
  var CI_DEPLOY_JOB_PATTERN = /(?:^\s{2,4}deploy\s*:|\b(?:fly|heroku|vercel|netlify|railway|render)\s+deploy\b|kubectl\s+apply\b|helm\s+(?:install|upgrade|deploy)\b|docker\s+push\b)/im;
6643
8530
  function isDeployableService(repoPath, repoFiles) {
@@ -6654,9 +8541,7 @@ function detectServerEntrypoint(repoPath, repoFiles) {
6654
8541
  return findServerEntrypointFile(repoPath, repoFiles) !== null;
6655
8542
  }
6656
8543
  function findServerEntrypointFile(repoPath, repoFiles) {
6657
- const candidates = repoFiles.filter(
6658
- (file) => MAIN_ENTRYPOINT_FILE_PATTERN.test(file) && !EXAMPLE_OR_TEST_DIR_PATTERN.test(file)
6659
- ).slice(0, 30);
8544
+ const candidates = repoFiles.filter((file) => MAIN_ENTRYPOINT_FILE_PATTERN.test(file) && isProductionSourcePath(file)).slice(0, 30);
6660
8545
  return candidates.find((file) => fileContains(repoPath, file, SERVER_ENTRYPOINT_PATTERN)) ?? null;
6661
8546
  }
6662
8547
  function isHealthCheckSignalFile(repoPath, file) {
@@ -6688,15 +8573,15 @@ function isDependencyUpdateConfig(file) {
6688
8573
  }
6689
8574
  function packageJsonHasAuditScript(repoPath, manifest) {
6690
8575
  if (!manifest.endsWith("package.json")) return false;
6691
- const scripts = readPackageScripts(join(repoPath, manifest));
8576
+ const scripts = readPackageScripts(join3(repoPath, manifest));
6692
8577
  return [...scripts.values()].some(
6693
8578
  (script) => /\b(audit|npm audit|pnpm audit|yarn audit)\b/i.test(script)
6694
8579
  );
6695
8580
  }
6696
8581
  function packageJsonHasHeavyTestDependency(repoPath, manifest) {
6697
- const fullPath = join(repoPath, manifest);
8582
+ const fullPath = join3(repoPath, manifest);
6698
8583
  if (!isRegularFile(fullPath)) return false;
6699
- const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
8584
+ const parsed = parseJsonObject(readFileSync6(fullPath, "utf8"));
6700
8585
  if (!parsed) return false;
6701
8586
  const names = [
6702
8587
  ...Object.keys(isRecord(parsed.dependencies) ? parsed.dependencies : {}),
@@ -6735,20 +8620,20 @@ function findRootPackageJson(repoFiles) {
6735
8620
  }
6736
8621
  function isRegularFile(path) {
6737
8622
  try {
6738
- return statSync(path).isFile();
8623
+ return statSync2(path).isFile();
6739
8624
  } catch {
6740
8625
  return false;
6741
8626
  }
6742
8627
  }
6743
8628
  function fileContains(repoPath, file, pattern) {
6744
- const fullPath = join(repoPath, file);
8629
+ const fullPath = join3(repoPath, file);
6745
8630
  if (!isRegularFile(fullPath)) return false;
6746
- return pattern.test(readFileSync(fullPath, "utf8"));
8631
+ return pattern.test(readFileSync6(fullPath, "utf8"));
6747
8632
  }
6748
8633
  function fileContainsCommittedSecret(repoPath, file) {
6749
- const fullPath = join(repoPath, file);
8634
+ const fullPath = join3(repoPath, file);
6750
8635
  if (!isRegularFile(fullPath)) return false;
6751
- return containsRealSecret(readFileSync(fullPath, "utf8"));
8636
+ return containsRealSecret(readFileSync6(fullPath, "utf8"));
6752
8637
  }
6753
8638
  function containsRealSecret(contents) {
6754
8639
  SECRET_ASSIGNMENT_PATTERN.lastIndex = 0;
@@ -6802,1015 +8687,749 @@ function readCredentialHistoryEntries(repoPath) {
6802
8687
  const key = `${entry.commit}:${entry.path}`;
6803
8688
  if (seen.has(key)) return;
6804
8689
  seen.add(key);
6805
- entries.push(entry);
6806
- };
6807
- try {
6808
- const commits = execFileSync("git", ["rev-list", "--all"], {
6809
- cwd: repoPath,
6810
- encoding: "utf8",
6811
- stdio: ["ignore", "pipe", "ignore"]
6812
- });
6813
- const output = execFileSync(
6814
- "git",
6815
- [
6816
- "diff-tree",
6817
- "--stdin",
6818
- "--root",
6819
- "--name-only",
6820
- "-r",
6821
- "--diff-filter=AM",
6822
- "--pretty=format:commit:%H"
6823
- ],
6824
- {
6825
- cwd: repoPath,
6826
- encoding: "utf8",
6827
- input: commits,
6828
- stdio: ["pipe", "pipe", "ignore"]
6829
- }
6830
- );
6831
- let currentCommit = null;
6832
- for (const line of output.split("\n")) {
6833
- if (line.startsWith("commit:")) {
6834
- currentCommit = line.slice("commit:".length);
6835
- continue;
6836
- }
6837
- const path = line.trim();
6838
- if (!currentCommit || !path) continue;
6839
- if (!isCredentialHistoryPath(path)) continue;
6840
- appendEntry({ commit: currentCommit, path });
6841
- }
6842
- } catch {
6843
- }
6844
- for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
6845
- appendEntry(entry);
6846
- }
6847
- return entries;
6848
- }
6849
- function readDeletedCredentialHistoryEntries(repoPath) {
6850
- const deletedPaths = readDeletedCredentialHistoryPaths(repoPath);
6851
- const entries = [];
6852
- const seen = /* @__PURE__ */ new Set();
6853
- for (const path of deletedPaths) {
6854
- for (const commit of readHistoryCommitsForPath(repoPath, path)) {
6855
- const key = `${commit}:${path}`;
6856
- if (seen.has(key)) continue;
6857
- seen.add(key);
6858
- entries.push({ commit, path });
6859
- }
6860
- }
6861
- return entries;
6862
- }
6863
- function readDeletedCredentialHistoryPaths(repoPath) {
6864
- try {
6865
- const output = execFileSync(
6866
- "git",
6867
- ["log", "--all", "--diff-filter=D", "--name-status", "--format=commit:%H"],
6868
- {
6869
- cwd: repoPath,
6870
- encoding: "utf8",
6871
- stdio: ["ignore", "pipe", "ignore"]
6872
- }
6873
- );
6874
- const paths = [];
6875
- const seen = /* @__PURE__ */ new Set();
6876
- for (const line of output.split("\n")) {
6877
- if (!line.startsWith("D ")) continue;
6878
- const path = line.slice(2).trim();
6879
- if (!path || seen.has(path)) continue;
6880
- if (!isCredentialHistoryPath(path)) continue;
6881
- seen.add(path);
6882
- paths.push(path);
6883
- }
6884
- return paths;
6885
- } catch {
6886
- return [];
6887
- }
6888
- }
6889
- function readHistoryCommitsForPath(repoPath, path) {
6890
- try {
6891
- const output = execFileSync(
6892
- "git",
6893
- ["log", "--all", "--diff-filter=AM", "--format=%H", "--", path],
6894
- {
6895
- cwd: repoPath,
6896
- encoding: "utf8",
6897
- stdio: ["ignore", "pipe", "ignore"]
6898
- }
6899
- );
6900
- return output.split("\n").map((line) => line.trim()).filter((line) => /^[0-9a-f]{40}$/i.test(line));
6901
- } catch {
6902
- return [];
6903
- }
6904
- }
6905
- function isCredentialHistoryPath(path) {
6906
- if (isHardExcludedPath(path)) return false;
6907
- const lowerPath = path.toLowerCase();
6908
- const basename3 = lowerPath.split("/").at(-1) ?? lowerPath;
6909
- if (/\.env(?:\.|$)/.test(basename3)) {
6910
- return true;
6911
- }
6912
- return lowerPath.includes("secret") || lowerPath.includes("credential") || basename3.endsWith(".pem") || basename3.endsWith(".key") || basename3 === "id_rsa" || basename3.endsWith(".p12") || basename3.endsWith(".pfx");
6913
- }
6914
- function isEnvHistoryPath(path) {
6915
- if (isEnvTemplatePath(path)) return false;
6916
- const basename3 = path.toLowerCase().split("/").at(-1) ?? path.toLowerCase();
6917
- return /\.env(?:\.|$)/.test(basename3);
6918
- }
6919
- function readGitBlob(repoPath, commit, path) {
6920
- try {
6921
- return execFileSync("git", ["show", `${commit}:${path}`], {
6922
- cwd: repoPath,
6923
- encoding: "utf8",
6924
- maxBuffer: 512e3,
6925
- stdio: ["ignore", "pipe", "ignore"]
6926
- });
6927
- } catch {
6928
- return null;
6929
- }
6930
- }
6931
- var ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/;
6932
- function isPlaceholderSecretValue(value) {
6933
- const normalized = value.trim().toLowerCase();
6934
- return PLACEHOLDER_SECRET_PATTERN.test(normalized) || normalized.includes("your-") || normalized.includes("example") || ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN.test(value.trim()) || isSyntheticFixtureSecretValue(normalized) || isFillerRunSecretValue(normalized);
6935
- }
6936
- function isFillerRunSecretValue(value) {
6937
- const candidates = [value];
6938
- const sepIdx = Math.max(value.lastIndexOf("_"), value.lastIndexOf("-"));
6939
- if (sepIdx > 0 && sepIdx < value.length - 1) {
6940
- candidates.push(value.slice(sepIdx + 1));
6941
- }
6942
- for (const body of candidates) {
6943
- if (body.length < 8) continue;
6944
- const counts = /* @__PURE__ */ new Map();
6945
- for (const ch of body) counts.set(ch, (counts.get(ch) ?? 0) + 1);
6946
- const distinct = counts.size;
6947
- const maxRun = Math.max(...counts.values());
6948
- if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
6949
- }
6950
- return false;
6951
- }
6952
- function isSyntheticFixtureSecretValue(value) {
6953
- return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
6954
- }
6955
- function hasSuspiciousDependencies(repoPath, manifest) {
6956
- if (!manifest.endsWith("package.json")) return false;
6957
- const fullPath = join(repoPath, manifest);
6958
- if (!isRegularFile(fullPath)) return false;
6959
- const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
6960
- if (!parsed) return false;
6961
- const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
6962
- const devDependencies = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
6963
- const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
6964
- return names.some(
6965
- (name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
6966
- );
6967
- }
6968
- function readRecentCommits(repoPath) {
6969
- try {
6970
- const output = execFileSync("git", ["log", "--max-count=12", "--format=%H%x00%s"], {
6971
- cwd: repoPath,
6972
- encoding: "utf8",
6973
- stdio: ["ignore", "pipe", "ignore"]
6974
- }).trim();
6975
- if (!output) return [];
6976
- return output.split("\n").map((line) => {
6977
- const [sha = "", subject = ""] = line.split("\0");
6978
- return { sha, subject };
6979
- }).filter((commit) => commit.sha.length >= 7);
6980
- } catch {
6981
- return [];
6982
- }
6983
- }
6984
- function readPackageScripts(packageJsonPath) {
6985
- if (!isRegularFile(packageJsonPath)) return /* @__PURE__ */ new Map();
6986
- const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
6987
- const scripts = parsed?.scripts;
6988
- if (!isRecord(scripts)) return /* @__PURE__ */ new Map();
6989
- return new Map(
6990
- Object.entries(scripts).filter(
6991
- (entry) => typeof entry[1] === "string"
6992
- )
6993
- );
6994
- }
6995
- function evidenceForRelative(repoPath, path, kind, label) {
6996
- const fullPath = join(repoPath, path);
6997
- const contents = isRegularFile(fullPath) ? readFileSync(fullPath, "utf8") : "";
6998
- return {
6999
- kind,
7000
- label,
7001
- path,
7002
- ...contents ? {
7003
- line: firstMeaningfulLine(contents),
7004
- contentHash: createHash("sha256").update(contents).digest("hex")
7005
- } : {}
7006
- };
7007
- }
7008
- function metric(name, label, value, max, weight, unit, description, kind) {
7009
- return {
7010
- name,
7011
- label,
7012
- value: Math.max(0, value),
7013
- max,
7014
- ...kind ? { kind } : {},
7015
- weight,
7016
- unit,
7017
- description
7018
- };
7019
- }
7020
- function firstMeaningfulLine(contents) {
7021
- const lines = contents.split("\n");
7022
- const index = lines.findIndex((line) => line.trim().length > 0);
7023
- return index === -1 ? 1 : index + 1;
7024
- }
7025
- function readGitHead(repoPath) {
8690
+ entries.push(entry);
8691
+ };
7026
8692
  try {
7027
- return execFileSync("git", ["rev-parse", "HEAD"], {
8693
+ const commits = execFileSync("git", ["rev-list", "--all"], {
7028
8694
  cwd: repoPath,
7029
8695
  encoding: "utf8",
7030
8696
  stdio: ["ignore", "pipe", "ignore"]
7031
- }).trim();
7032
- } catch {
7033
- return null;
7034
- }
7035
- }
7036
- function hasEnvPathInGitHistory(repoPath) {
7037
- try {
8697
+ });
7038
8698
  const output = execFileSync(
7039
8699
  "git",
7040
- ["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
8700
+ [
8701
+ "diff-tree",
8702
+ "--stdin",
8703
+ "--root",
8704
+ "--name-only",
8705
+ "-r",
8706
+ "--diff-filter=AM",
8707
+ "--pretty=format:commit:%H"
8708
+ ],
7041
8709
  {
7042
8710
  cwd: repoPath,
7043
8711
  encoding: "utf8",
7044
- stdio: ["ignore", "pipe", "ignore"],
7045
- maxBuffer: 512e3
8712
+ input: commits,
8713
+ stdio: ["pipe", "pipe", "ignore"]
7046
8714
  }
7047
- ).trim();
7048
- if (!output) return false;
7049
- return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
8715
+ );
8716
+ let currentCommit = null;
8717
+ for (const line of output.split("\n")) {
8718
+ if (line.startsWith("commit:")) {
8719
+ currentCommit = line.slice("commit:".length);
8720
+ continue;
8721
+ }
8722
+ const path = line.trim();
8723
+ if (!currentCommit || !path) continue;
8724
+ if (!isCredentialHistoryPath(path)) continue;
8725
+ appendEntry({ commit: currentCommit, path });
8726
+ }
7050
8727
  } catch {
7051
- return false;
7052
8728
  }
7053
- }
7054
-
7055
- // src/witan/rubric.ts
7056
- var WITAN_RUBRIC = [
7057
- {
7058
- id: "A1",
7059
- title: "Test integrity and regression signal",
7060
- category: "code_trust"
7061
- },
7062
- {
7063
- id: "A2",
7064
- title: "Data-layer isolation and secrets posture",
7065
- category: "code_trust"
7066
- },
7067
- {
7068
- id: "A3",
7069
- title: "Production readiness",
7070
- category: "code_trust"
7071
- },
7072
- {
7073
- id: "A4",
7074
- title: "Dependency hygiene",
7075
- category: "code_trust"
7076
- },
7077
- {
7078
- id: "A5",
7079
- title: "Claim-vs-reality reconciliation",
7080
- category: "code_trust"
7081
- },
7082
- {
7083
- id: "B1",
7084
- title: "Dispatch trace completeness",
7085
- category: "process_trust"
7086
- },
7087
- {
7088
- id: "B2",
7089
- title: "PR outcome traceability",
7090
- category: "process_trust"
7091
- },
7092
- {
7093
- id: "B3",
7094
- title: "CI and QA discipline",
7095
- category: "process_trust"
7096
- },
7097
- {
7098
- id: "B4",
7099
- title: "Audit trail and report-up completeness",
7100
- category: "process_trust"
7101
- },
7102
- {
7103
- id: "B5",
7104
- title: "Verified learning trace",
7105
- category: "process_trust"
7106
- },
7107
- {
7108
- id: "B6",
7109
- title: "Privileged-operation human gating",
7110
- category: "process_trust"
8729
+ for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
8730
+ appendEntry(entry);
7111
8731
  }
7112
- ];
7113
-
7114
- // src/witan/scoring.ts
7115
- var MAX_SIGNAL_ADJUSTMENT = 0.8;
7116
- function createWitanReport(input, inputSignals, rubric = WITAN_RUBRIC) {
7117
- const parsedInput = WitanReportInputSchema.parse(input);
7118
- const signalsByCriterion = mergeSignalsByCriterion(parsedInput.signals);
7119
- const hasInputSignals = inputSignals != null && inputSignals.length > 0;
7120
- const inputSignalsByDimension = /* @__PURE__ */ new Map();
7121
- if (hasInputSignals && inputSignals) {
7122
- for (const signal of inputSignals) {
7123
- const bucket = inputSignalsByDimension.get(signal.dimension) ?? [];
7124
- bucket.push(signal);
7125
- inputSignalsByDimension.set(signal.dimension, bucket);
8732
+ return entries;
8733
+ }
8734
+ function readDeletedCredentialHistoryEntries(repoPath) {
8735
+ const deletedPaths = readDeletedCredentialHistoryPaths(repoPath);
8736
+ const entries = [];
8737
+ const seen = /* @__PURE__ */ new Set();
8738
+ for (const path of deletedPaths) {
8739
+ for (const commit of readHistoryCommitsForPath(repoPath, path)) {
8740
+ const key = `${commit}:${path}`;
8741
+ if (seen.has(key)) continue;
8742
+ seen.add(key);
8743
+ entries.push({ commit, path });
7126
8744
  }
7127
8745
  }
7128
- const consumedSignals = [];
7129
- const criteria = rubric.map((rubricCriterion) => {
7130
- const id = rubricCriterion.id;
7131
- const signal = signalsByCriterion.get(id);
7132
- const scored = scoreCriterion(signal, parsedInput.rubricVersion);
7133
- const dimensionSignals = inputSignalsByDimension.get(id);
7134
- if (!dimensionSignals || dimensionSignals.length === 0) {
7135
- return {
7136
- id,
7137
- title: rubricCriterion.title,
7138
- category: rubricCriterion.category,
7139
- score: scored.score,
7140
- status: scored.status,
7141
- evidence: scored.evidence,
7142
- findings: scored.findings,
7143
- metrics: scored.metrics,
7144
- ...signal?.notes ? { notes: signal.notes } : {}
7145
- };
7146
- }
7147
- const { adjustedScore, adjustment, summaries } = applySignalAdjustment(
7148
- scored.score,
7149
- id,
7150
- dimensionSignals
8746
+ return entries;
8747
+ }
8748
+ function readDeletedCredentialHistoryPaths(repoPath) {
8749
+ try {
8750
+ const output = execFileSync(
8751
+ "git",
8752
+ ["log", "--all", "--diff-filter=D", "--name-status", "--format=commit:%H"],
8753
+ {
8754
+ cwd: repoPath,
8755
+ encoding: "utf8",
8756
+ stdio: ["ignore", "pipe", "ignore"]
8757
+ }
7151
8758
  );
7152
- consumedSignals.push(...summaries);
7153
- const finalScore = adjustment === 0 ? scored.score : adjustedScore;
7154
- const finalStatus = adjustment === 0 ? scored.status : statusForScore(finalScore);
7155
- return {
7156
- id,
7157
- title: rubricCriterion.title,
7158
- category: rubricCriterion.category,
7159
- score: finalScore,
7160
- ...adjustment !== 0 ? { nativeScore: scored.score } : {},
7161
- status: finalStatus,
7162
- evidence: scored.evidence,
7163
- findings: scored.findings,
7164
- metrics: scored.metrics,
7165
- ...signal?.notes ? { notes: signal.notes } : {}
7166
- };
7167
- });
7168
- const categoryOrder = [];
7169
- for (const rubricCriterion of rubric) {
7170
- if (!categoryOrder.includes(rubricCriterion.category)) {
7171
- categoryOrder.push(rubricCriterion.category);
8759
+ const paths = [];
8760
+ const seen = /* @__PURE__ */ new Set();
8761
+ for (const line of output.split("\n")) {
8762
+ if (!line.startsWith("D ")) continue;
8763
+ const path = line.slice(2).trim();
8764
+ if (!path || seen.has(path)) continue;
8765
+ if (!isCredentialHistoryPath(path)) continue;
8766
+ seen.add(path);
8767
+ paths.push(path);
7172
8768
  }
8769
+ return paths;
8770
+ } catch {
8771
+ return [];
7173
8772
  }
7174
- const categoryScoreMap = {};
7175
- for (const category of categoryOrder) {
7176
- categoryScoreMap[category] = averageScore(
7177
- criteria.filter((criterion) => criterion.category === category)
7178
- );
7179
- }
7180
- const firstCategory = categoryOrder[0];
7181
- const secondCategory = categoryOrder[1] ?? firstCategory;
7182
- const codeTrustScore = categoryScoreMap.code_trust ?? (firstCategory ? categoryScoreMap[firstCategory] : void 0) ?? 0;
7183
- const processTrustScore = categoryScoreMap.process_trust ?? (secondCategory ? categoryScoreMap[secondCategory] : void 0) ?? 0;
7184
- const overallScore = roundScore(
7185
- categoryOrder.reduce((sum, category) => sum + (categoryScoreMap[category] ?? 0), 0) / Math.max(categoryOrder.length, 1)
7186
- );
7187
- return WitanReportSchema.parse({
7188
- productSlug: parsedInput.productSlug,
7189
- productDisplayName: parsedInput.productDisplayName,
7190
- repo: parsedInput.repo,
7191
- generatedAt: parsedInput.generatedAt,
7192
- rubricVersion: parsedInput.rubricVersion,
7193
- codeTrustScore,
7194
- processTrustScore,
7195
- overallScore,
7196
- criteria,
7197
- ...consumedSignals.length > 0 ? { consumedSignals } : {},
7198
- // Only surface the full per-category map for rubrics with more than two buckets —
7199
- // the default two-category rubric is fully represented by codeTrustScore/processTrustScore.
7200
- ...categoryOrder.length > 2 ? { categoryScores: categoryScoreMap } : {},
7201
- // Pass through repo-archetype metadata verbatim — createWitanReport does not compute or
7202
- // alter it (see classifyRepoArchetype in repo-signals.ts); per-criterion scoring above is
7203
- // unaffected by archetype, only presentation layers (badge/terminal/verdict) key off it.
7204
- ...parsedInput.archetype ? { archetype: parsedInput.archetype } : {},
7205
- ...parsedInput.insufficientSourceReason ? { insufficientSourceReason: parsedInput.insufficientSourceReason } : {}
7206
- });
7207
8773
  }
7208
- function applySignalAdjustment(nativeScore, dimension, signals) {
7209
- const summaries = [];
7210
- let totalRawAdj = 0;
7211
- for (const signal of signals) {
7212
- const criticalCount = signal.findings.filter((f) => f.severity === "critical").length;
7213
- const warningCount = signal.findings.filter((f) => f.severity === "warning").length;
7214
- const infoCount = signal.findings.filter((f) => f.severity === "info").length;
7215
- const severityScore = Math.min(
7216
- criticalCount * 0.2 + warningCount * 0.1 + infoCount * 0.02,
7217
- 1
7218
- );
7219
- const signalAdj = signal.weight * severityScore * MAX_SIGNAL_ADJUSTMENT;
7220
- totalRawAdj += signalAdj;
7221
- summaries.push({
7222
- source: signal.source,
7223
- dimension,
7224
- findingCount: signal.findings.length,
7225
- severityBreakdown: { critical: criticalCount, warning: warningCount, info: infoCount },
7226
- nativeScore,
7227
- scoreAdjustment: -roundScore(Math.min(signalAdj, MAX_SIGNAL_ADJUSTMENT)),
7228
- adjustedScore: roundScore(
7229
- Math.max(0, nativeScore - Math.min(signalAdj, MAX_SIGNAL_ADJUSTMENT))
7230
- ),
7231
- findings: [...signal.findings]
7232
- });
8774
+ function readHistoryCommitsForPath(repoPath, path) {
8775
+ try {
8776
+ const output = execFileSync(
8777
+ "git",
8778
+ ["log", "--all", "--diff-filter=AM", "--format=%H", "--", path],
8779
+ {
8780
+ cwd: repoPath,
8781
+ encoding: "utf8",
8782
+ stdio: ["ignore", "pipe", "ignore"]
8783
+ }
8784
+ );
8785
+ return output.split("\n").map((line) => line.trim()).filter((line) => /^[0-9a-f]{40}$/i.test(line));
8786
+ } catch {
8787
+ return [];
7233
8788
  }
7234
- const totalAdj = Math.min(totalRawAdj, MAX_SIGNAL_ADJUSTMENT);
7235
- const adjustedScore = roundScore(Math.max(0, nativeScore - totalAdj));
7236
- for (const summary of summaries) {
7237
- summary.adjustedScore = adjustedScore;
7238
- summary.scoreAdjustment = -roundScore(totalAdj);
8789
+ }
8790
+ function isCredentialHistoryPath(path) {
8791
+ if (isHardExcludedPath(path)) return false;
8792
+ const lowerPath = path.toLowerCase();
8793
+ const basename4 = lowerPath.split("/").at(-1) ?? lowerPath;
8794
+ if (/\.env(?:\.|$)/.test(basename4)) {
8795
+ return true;
7239
8796
  }
7240
- return { adjustedScore, adjustment: roundScore(totalAdj), summaries };
8797
+ return lowerPath.includes("secret") || lowerPath.includes("credential") || basename4.endsWith(".pem") || basename4.endsWith(".key") || basename4 === "id_rsa" || basename4.endsWith(".p12") || basename4.endsWith(".pfx");
7241
8798
  }
7242
- function statusForScore(score) {
7243
- if (score >= 3.5) return "verified";
7244
- if (score >= 2.5) return "info";
7245
- if (score >= 1.5) return "warning";
7246
- if (score > 0) return "critical";
7247
- return "critical";
8799
+ function isEnvHistoryPath(path) {
8800
+ if (isEnvTemplatePath(path)) return false;
8801
+ const basename4 = path.toLowerCase().split("/").at(-1) ?? path.toLowerCase();
8802
+ return /\.env(?:\.|$)/.test(basename4);
7248
8803
  }
7249
- function mergeSignalsByCriterion(signals) {
7250
- const merged = /* @__PURE__ */ new Map();
7251
- for (const signal of signals) {
7252
- const existing = merged.get(signal.criterionId);
7253
- if (!existing) {
7254
- merged.set(signal.criterionId, signal);
7255
- continue;
7256
- }
7257
- merged.set(signal.criterionId, {
7258
- criterionId: signal.criterionId,
7259
- positiveEvidence: [...existing.positiveEvidence, ...signal.positiveEvidence],
7260
- findings: [...existing.findings, ...signal.findings],
7261
- metrics: [...existing.metrics ?? [], ...signal.metrics ?? []],
7262
- notes: signal.notes ?? existing.notes,
7263
- // N/A wins on merge: if either signal is N/A, the criterion is N/A.
7264
- ...existing.notApplicable === true || signal.notApplicable === true ? { notApplicable: true } : {}
8804
+ function readGitBlob(repoPath, commit, path) {
8805
+ try {
8806
+ return execFileSync("git", ["show", `${commit}:${path}`], {
8807
+ cwd: repoPath,
8808
+ encoding: "utf8",
8809
+ maxBuffer: 512e3,
8810
+ stdio: ["ignore", "pipe", "ignore"]
7265
8811
  });
8812
+ } catch {
8813
+ return null;
7266
8814
  }
7267
- return merged;
7268
- }
7269
- function usesMetricScoring(rubricVersion) {
7270
- return rubricVersion === WITAN_RUBRIC_VERSION_V1 || rubricVersion === WITAN_RUBRIC_VERSION_V2 || rubricVersion === WITAN_TRADING_RUBRIC_VERSION_V0;
7271
8815
  }
7272
- function unmeasuredStatus(rubricVersion) {
7273
- return rubricVersion === WITAN_TRADING_RUBRIC_VERSION_V0 ? "unverified" : "insufficient_data";
8816
+ var ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/;
8817
+ function isPlaceholderSecretValue(value) {
8818
+ const normalized = value.trim().toLowerCase();
8819
+ return PLACEHOLDER_SECRET_PATTERN.test(normalized) || normalized.includes("your-") || normalized.includes("example") || ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN.test(value.trim()) || isSyntheticFixtureSecretValue(normalized) || isFillerRunSecretValue(normalized);
7274
8820
  }
7275
- function scoreCriterion(signal, rubricVersion) {
7276
- if (!signal) {
7277
- return {
7278
- score: 0,
7279
- status: unmeasuredStatus(rubricVersion),
7280
- evidence: [],
7281
- findings: [],
7282
- metrics: []
7283
- };
7284
- }
7285
- if (signal.notApplicable === true) {
7286
- return {
7287
- score: 0,
7288
- status: "not_applicable",
7289
- evidence: [],
7290
- findings: [],
7291
- metrics: []
7292
- };
7293
- }
7294
- const evidence = signal.positiveEvidence;
7295
- const findings = signal.findings;
7296
- const metrics = signal.metrics ?? [];
7297
- const evidenceCount = evidence.length + findings.length;
7298
- if (evidenceCount === 0) {
7299
- if (!usesMetricScoring(rubricVersion) || metrics.length === 0) {
7300
- return {
7301
- score: 0,
7302
- status: unmeasuredStatus(rubricVersion),
7303
- evidence,
7304
- findings,
7305
- metrics
7306
- };
7307
- }
7308
- }
7309
- if (usesMetricScoring(rubricVersion)) {
7310
- const measuredMetrics = metrics.length > 0 ? metrics : fallbackMetricsForEvidence(evidence, findings);
7311
- const score = capScoreForFindings(scoreMetrics(measuredMetrics), findings);
7312
- const status = statusForScoreAndFindings(score, findings);
7313
- return {
7314
- score,
7315
- status,
7316
- evidence,
7317
- findings: ensureFindingsExplainStatus(signal.criterionId, score, status, findings, evidence),
7318
- metrics: measuredMetrics
7319
- };
7320
- }
7321
- if (findings.some((finding) => finding.severity === "critical")) {
7322
- return {
7323
- score: 1,
7324
- status: "critical",
7325
- evidence,
7326
- findings,
7327
- metrics
7328
- };
7329
- }
7330
- if (findings.some((finding) => finding.severity === "warning")) {
7331
- return {
7332
- score: 2,
7333
- status: "warning",
7334
- evidence,
7335
- findings,
7336
- metrics
7337
- };
8821
+ function isFillerRunSecretValue(value) {
8822
+ const candidates = [value];
8823
+ const sepIdx = Math.max(value.lastIndexOf("_"), value.lastIndexOf("-"));
8824
+ if (sepIdx > 0 && sepIdx < value.length - 1) {
8825
+ candidates.push(value.slice(sepIdx + 1));
7338
8826
  }
7339
- if (findings.some((finding) => finding.severity === "info")) {
7340
- return {
7341
- score: 3,
7342
- status: "info",
7343
- evidence,
7344
- findings,
7345
- metrics
7346
- };
8827
+ for (const body of candidates) {
8828
+ if (body.length < 8) continue;
8829
+ const counts = /* @__PURE__ */ new Map();
8830
+ for (const ch of body) counts.set(ch, (counts.get(ch) ?? 0) + 1);
8831
+ const distinct = counts.size;
8832
+ const maxRun = Math.max(...counts.values());
8833
+ if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
7347
8834
  }
7348
- return {
7349
- score: 4,
7350
- status: "verified",
7351
- evidence,
7352
- findings,
7353
- metrics
7354
- };
8835
+ return false;
7355
8836
  }
7356
- function fallbackMetricsForEvidence(evidence, findings) {
7357
- return [
7358
- {
7359
- name: "evidence_depth",
7360
- label: "Evidence depth",
7361
- value: Math.min(evidence.length + findings.length + 1, 4),
7362
- max: 4,
7363
- weight: 1,
7364
- unit: "signals",
7365
- description: "Conservative v1 fallback for externally supplied evidence that has not provided criterion-specific depth metrics."
7366
- }
7367
- ];
8837
+ function isSyntheticFixtureSecretValue(value) {
8838
+ return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
7368
8839
  }
7369
- function scoreMetrics(metrics) {
7370
- let weightedTotal = 0;
7371
- let totalWeight = 0;
7372
- for (const metric2 of metrics) {
7373
- const normalized = metric2.max ? Math.min(metric2.value / metric2.max, 1) : Math.min(metric2.value, 1);
7374
- weightedTotal += normalized * metric2.weight;
7375
- totalWeight += metric2.weight;
8840
+ function hasSuspiciousDependencies(repoPath, manifest) {
8841
+ if (!manifest.endsWith("package.json")) return false;
8842
+ const fullPath = join3(repoPath, manifest);
8843
+ if (!isRegularFile(fullPath)) return false;
8844
+ const parsed = parseJsonObject(readFileSync6(fullPath, "utf8"));
8845
+ if (!parsed) return false;
8846
+ const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
8847
+ const devDependencies = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
8848
+ const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
8849
+ return names.some(
8850
+ (name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
8851
+ );
8852
+ }
8853
+ function readRecentCommits(repoPath) {
8854
+ try {
8855
+ const output = execFileSync("git", ["log", "--max-count=12", "--format=%H%x00%s"], {
8856
+ cwd: repoPath,
8857
+ encoding: "utf8",
8858
+ stdio: ["ignore", "pipe", "ignore"]
8859
+ }).trim();
8860
+ if (!output) return [];
8861
+ return output.split("\n").map((line) => {
8862
+ const [sha = "", subject = ""] = line.split("\0");
8863
+ return { sha, subject };
8864
+ }).filter((commit) => commit.sha.length >= 7);
8865
+ } catch {
8866
+ return [];
7376
8867
  }
7377
- if (totalWeight === 0) return 0;
7378
- return roundScore(weightedTotal / totalWeight * 4);
7379
8868
  }
7380
- function capScoreForFindings(score, findings) {
7381
- if (findings.some((finding) => finding.severity === "critical")) return 1.4;
7382
- if (findings.some((finding) => finding.severity === "warning")) return Math.min(score, 2.4);
7383
- if (findings.some((finding) => finding.severity === "info")) return Math.min(score, 3.4);
7384
- return score;
8869
+ function readPackageScripts(packageJsonPath) {
8870
+ if (!isRegularFile(packageJsonPath)) return /* @__PURE__ */ new Map();
8871
+ const parsed = parseJsonObject(readFileSync6(packageJsonPath, "utf8"));
8872
+ const scripts = parsed?.scripts;
8873
+ if (!isRecord(scripts)) return /* @__PURE__ */ new Map();
8874
+ return new Map(
8875
+ Object.entries(scripts).filter(
8876
+ (entry) => typeof entry[1] === "string"
8877
+ )
8878
+ );
7385
8879
  }
7386
- function statusForScoreAndFindings(score, findings) {
7387
- if (findings.some((finding) => finding.severity === "critical")) return "critical";
7388
- if (findings.some((finding) => finding.severity === "warning")) return "warning";
7389
- if (score >= 3.5 && findings.length === 0) return "verified";
7390
- if (score >= 2.5) return "info";
7391
- if (score >= 1.5) return "warning";
7392
- return "critical";
8880
+ function evidenceForRelative(repoPath, path, kind, label) {
8881
+ const fullPath = join3(repoPath, path);
8882
+ const contents = isRegularFile(fullPath) ? readFileSync6(fullPath, "utf8") : "";
8883
+ return {
8884
+ kind,
8885
+ label,
8886
+ path,
8887
+ ...contents ? {
8888
+ line: firstMeaningfulLine(contents),
8889
+ contentHash: createHash("sha256").update(contents).digest("hex")
8890
+ } : {}
8891
+ };
7393
8892
  }
7394
- function ensureFindingsExplainStatus(criterionId, score, status, findings, evidence) {
7395
- if (findings.length > 0) return [...findings];
7396
- if (status !== "critical" && status !== "warning") return [...findings];
7397
- const anchor = evidence[0] ?? {
7398
- kind: "repository",
7399
- label: `${criterionId} metric-derived score`,
7400
- path: "."
8893
+ function evidenceForRelativeAtLine(repoPath, path, kind, label, line) {
8894
+ const fullPath = join3(repoPath, path);
8895
+ const contents = isRegularFile(fullPath) ? readFileSync6(fullPath, "utf8") : "";
8896
+ return {
8897
+ kind,
8898
+ label,
8899
+ path,
8900
+ line,
8901
+ ...contents ? { contentHash: createHash("sha256").update(contents).digest("hex") } : {}
8902
+ };
8903
+ }
8904
+ function metric(name, label, value, max, weight, unit, description, kind) {
8905
+ return {
8906
+ name,
8907
+ label,
8908
+ value: Math.max(0, value),
8909
+ max,
8910
+ ...kind ? { kind } : {},
8911
+ weight,
8912
+ unit,
8913
+ description
7401
8914
  };
7402
- return [
7403
- {
7404
- severity: status,
7405
- summary: `${criterionId} metric-derived score is ${score.toFixed(1)}/4.0, in the ${status} band \u2014 no single finding drove this; it reflects the combined metric weighting below.`,
7406
- evidence: anchor
7407
- }
7408
- ];
7409
8915
  }
7410
- function averageScore(criteria) {
7411
- const applicable = criteria.filter(
7412
- (criterion) => criterion.status !== "not_applicable" && criterion.status !== "insufficient_data"
7413
- );
7414
- if (applicable.length === 0) return 0;
7415
- const total = applicable.reduce((sum, criterion) => sum + criterion.score, 0);
7416
- return roundScore(total / applicable.length);
8916
+ function firstMeaningfulLine(contents) {
8917
+ const lines = contents.split("\n");
8918
+ const index = lines.findIndex((line) => line.trim().length > 0);
8919
+ return index === -1 ? 1 : index + 1;
7417
8920
  }
7418
- function roundScore(score) {
7419
- return Math.round(score * 10) / 10;
8921
+ function readGitHead(repoPath) {
8922
+ try {
8923
+ return execFileSync("git", ["rev-parse", "HEAD"], {
8924
+ cwd: repoPath,
8925
+ encoding: "utf8",
8926
+ stdio: ["ignore", "pipe", "ignore"]
8927
+ }).trim();
8928
+ } catch {
8929
+ return null;
8930
+ }
8931
+ }
8932
+ function hasEnvPathInGitHistory(repoPath) {
8933
+ try {
8934
+ const output = execFileSync(
8935
+ "git",
8936
+ ["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
8937
+ {
8938
+ cwd: repoPath,
8939
+ encoding: "utf8",
8940
+ stdio: ["ignore", "pipe", "ignore"],
8941
+ maxBuffer: 512e3
8942
+ }
8943
+ ).trim();
8944
+ if (!output) return false;
8945
+ return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
8946
+ } catch {
8947
+ return false;
8948
+ }
7420
8949
  }
7421
8950
 
7422
- // src/witan/sarif-adapter.ts
7423
- import { readFileSync as readFileSync2 } from "fs";
7424
- var DIMENSION_RULES = [
7425
- // A2 — injection / secrets / auth (high weight)
7426
- {
7427
- pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
7428
- dimension: "A2",
7429
- weight: 0.9
7430
- },
7431
- {
7432
- pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
7433
- dimension: "A2",
7434
- weight: 0.9
7435
- },
8951
+ // ../witan/src/rubric.ts
8952
+ var WITAN_RUBRIC = [
7436
8953
  {
7437
- pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
7438
- dimension: "A2",
7439
- weight: 0.8
8954
+ id: "A1",
8955
+ title: "Test integrity and regression signal",
8956
+ category: "code_trust"
7440
8957
  },
7441
8958
  {
7442
- pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
7443
- dimension: "A2",
7444
- weight: 0.8
8959
+ id: "A2",
8960
+ title: "Data-layer isolation and secrets posture",
8961
+ category: "code_trust"
7445
8962
  },
7446
8963
  {
7447
- pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
7448
- dimension: "A2",
7449
- weight: 0.8
8964
+ id: "A3",
8965
+ title: "Production readiness",
8966
+ category: "code_trust"
7450
8967
  },
7451
8968
  {
7452
- pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
7453
- dimension: "A2",
7454
- weight: 0.7
8969
+ id: "A4",
8970
+ title: "Dependency hygiene",
8971
+ category: "code_trust"
7455
8972
  },
7456
8973
  {
7457
- pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
7458
- dimension: "A2",
7459
- weight: 0.6
8974
+ id: "A5",
8975
+ title: "Claim-vs-reality reconciliation",
8976
+ category: "code_trust"
7460
8977
  },
7461
- // A4 — dependency vulnerabilities
7462
8978
  {
7463
- pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
7464
- dimension: "A4",
7465
- weight: 0.8
8979
+ id: "B1",
8980
+ title: "Dispatch trace completeness",
8981
+ category: "process_trust"
7466
8982
  },
7467
8983
  {
7468
- pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
7469
- dimension: "A4",
7470
- weight: 0.7
8984
+ id: "B2",
8985
+ title: "PR outcome traceability",
8986
+ category: "process_trust"
7471
8987
  },
7472
- // A3 — production readiness / insecure config
7473
8988
  {
7474
- pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
7475
- dimension: "A3",
7476
- weight: 0.5
8989
+ id: "B3",
8990
+ title: "CI and QA discipline",
8991
+ category: "process_trust"
7477
8992
  },
7478
8993
  {
7479
- pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
7480
- dimension: "A3",
7481
- weight: 0.4
8994
+ id: "B4",
8995
+ title: "Audit trail and report-up completeness",
8996
+ category: "process_trust"
7482
8997
  },
7483
8998
  {
7484
- pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
7485
- dimension: "A3",
7486
- weight: 0.4
8999
+ id: "B5",
9000
+ title: "Verified learning trace",
9001
+ category: "process_trust"
7487
9002
  },
7488
- // A1 — test integrity (low weight; SARIF rarely surfaces this)
7489
9003
  {
7490
- pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
7491
- dimension: "A1",
7492
- weight: 0.2
9004
+ id: "B6",
9005
+ title: "Privileged-operation human gating",
9006
+ category: "process_trust"
7493
9007
  }
7494
9008
  ];
7495
- var DEFAULT_DIMENSION = "A2";
7496
- var DEFAULT_WEIGHT = 0.3;
7497
- var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
7498
- function mapLevel(level) {
7499
- if (!level || DROP_LEVEL.has(level)) return null;
7500
- if (level === "error") return "critical";
7501
- if (level === "warning") return "warning";
7502
- return "info";
7503
- }
7504
- function mapRuleToDimension(ruleId, rules) {
7505
- for (const rule of rules) {
7506
- if (rule.pattern.test(ruleId)) {
7507
- return { dimension: rule.dimension, weight: rule.weight };
9009
+
9010
+ // ../witan/src/scoring.ts
9011
+ var MAX_SIGNAL_ADJUSTMENT = 0.8;
9012
+ function createWitanReport(input, inputSignals, rubric = WITAN_RUBRIC) {
9013
+ const parsedInput = WitanReportInputSchema.parse(input);
9014
+ const signalsByCriterion = mergeSignalsByCriterion(parsedInput.signals);
9015
+ const hasInputSignals = inputSignals != null && inputSignals.length > 0;
9016
+ const inputSignalsByDimension = /* @__PURE__ */ new Map();
9017
+ if (hasInputSignals && inputSignals) {
9018
+ for (const signal of inputSignals) {
9019
+ const bucket = inputSignalsByDimension.get(signal.dimension) ?? [];
9020
+ bucket.push(signal);
9021
+ inputSignalsByDimension.set(signal.dimension, bucket);
9022
+ }
9023
+ }
9024
+ const consumedSignals = [];
9025
+ const criteria = rubric.map((rubricCriterion) => {
9026
+ const id = rubricCriterion.id;
9027
+ const signal = signalsByCriterion.get(id);
9028
+ const scored = scoreCriterion(signal, parsedInput.rubricVersion);
9029
+ const dimensionSignals = inputSignalsByDimension.get(id);
9030
+ if (!dimensionSignals || dimensionSignals.length === 0) {
9031
+ return {
9032
+ id,
9033
+ title: rubricCriterion.title,
9034
+ category: rubricCriterion.category,
9035
+ score: scored.score,
9036
+ status: scored.status,
9037
+ evidence: scored.evidence,
9038
+ findings: scored.findings,
9039
+ metrics: scored.metrics,
9040
+ ...signal?.notes ? { notes: signal.notes } : {}
9041
+ };
9042
+ }
9043
+ const { adjustedScore, adjustment, summaries } = applySignalAdjustment(
9044
+ scored.score,
9045
+ id,
9046
+ dimensionSignals
9047
+ );
9048
+ consumedSignals.push(...summaries);
9049
+ const finalScore = adjustment === 0 ? scored.score : adjustedScore;
9050
+ const finalStatus = adjustment === 0 ? scored.status : statusForScore(finalScore);
9051
+ return {
9052
+ id,
9053
+ title: rubricCriterion.title,
9054
+ category: rubricCriterion.category,
9055
+ score: finalScore,
9056
+ ...adjustment !== 0 ? { nativeScore: scored.score } : {},
9057
+ status: finalStatus,
9058
+ evidence: scored.evidence,
9059
+ findings: scored.findings,
9060
+ metrics: scored.metrics,
9061
+ ...signal?.notes ? { notes: signal.notes } : {}
9062
+ };
9063
+ });
9064
+ const categoryOrder = [];
9065
+ for (const rubricCriterion of rubric) {
9066
+ if (!categoryOrder.includes(rubricCriterion.category)) {
9067
+ categoryOrder.push(rubricCriterion.category);
7508
9068
  }
7509
9069
  }
7510
- return { dimension: DEFAULT_DIMENSION, weight: DEFAULT_WEIGHT };
7511
- }
7512
- function renderLocation(result) {
7513
- const loc = result.locations?.[0]?.physicalLocation;
7514
- if (!loc) return void 0;
7515
- const uri = loc.artifactLocation?.uri;
7516
- const line = loc.region?.startLine;
7517
- if (!uri) return void 0;
7518
- return line != null ? `${uri}:${line}` : uri;
9070
+ const categoryScoreMap = {};
9071
+ for (const category of categoryOrder) {
9072
+ categoryScoreMap[category] = averageScore(
9073
+ criteria.filter((criterion) => criterion.category === category)
9074
+ );
9075
+ }
9076
+ const firstCategory = categoryOrder[0];
9077
+ const secondCategory = categoryOrder[1] ?? firstCategory;
9078
+ const codeTrustScore = categoryScoreMap.code_trust ?? (firstCategory ? categoryScoreMap[firstCategory] : void 0) ?? 0;
9079
+ const processTrustScore = categoryScoreMap.process_trust ?? (secondCategory ? categoryScoreMap[secondCategory] : void 0) ?? 0;
9080
+ const overallScore = roundScore(
9081
+ categoryOrder.reduce((sum, category) => sum + (categoryScoreMap[category] ?? 0), 0) / Math.max(categoryOrder.length, 1)
9082
+ );
9083
+ return WitanReportSchema.parse({
9084
+ productSlug: parsedInput.productSlug,
9085
+ productDisplayName: parsedInput.productDisplayName,
9086
+ repo: parsedInput.repo,
9087
+ generatedAt: parsedInput.generatedAt,
9088
+ rubricVersion: parsedInput.rubricVersion,
9089
+ codeTrustScore,
9090
+ processTrustScore,
9091
+ overallScore,
9092
+ criteria,
9093
+ ...consumedSignals.length > 0 ? { consumedSignals } : {},
9094
+ // Only surface the full per-category map for rubrics with more than two buckets —
9095
+ // the default two-category rubric is fully represented by codeTrustScore/processTrustScore.
9096
+ ...categoryOrder.length > 2 ? { categoryScores: categoryScoreMap } : {},
9097
+ // Pass through repo-archetype metadata verbatim — createWitanReport does not compute or
9098
+ // alter it (see classifyRepoArchetype in repo-signals.ts); per-criterion scoring above is
9099
+ // unaffected by archetype, only presentation layers (badge/terminal/verdict) key off it.
9100
+ ...parsedInput.archetype ? { archetype: parsedInput.archetype } : {},
9101
+ ...parsedInput.insufficientSourceReason ? { insufficientSourceReason: parsedInput.insufficientSourceReason } : {}
9102
+ });
9103
+ }
9104
+ function applySignalAdjustment(nativeScore, dimension, signals) {
9105
+ const summaries = [];
9106
+ let totalRawAdj = 0;
9107
+ for (const signal of signals) {
9108
+ const criticalCount = signal.findings.filter((f) => f.severity === "critical").length;
9109
+ const warningCount = signal.findings.filter((f) => f.severity === "warning").length;
9110
+ const infoCount = signal.findings.filter((f) => f.severity === "info").length;
9111
+ const severityScore = Math.min(
9112
+ criticalCount * 0.2 + warningCount * 0.1 + infoCount * 0.02,
9113
+ 1
9114
+ );
9115
+ const signalAdj = signal.weight * severityScore * MAX_SIGNAL_ADJUSTMENT;
9116
+ totalRawAdj += signalAdj;
9117
+ summaries.push({
9118
+ source: signal.source,
9119
+ dimension,
9120
+ findingCount: signal.findings.length,
9121
+ severityBreakdown: { critical: criticalCount, warning: warningCount, info: infoCount },
9122
+ nativeScore,
9123
+ scoreAdjustment: -roundScore(Math.min(signalAdj, MAX_SIGNAL_ADJUSTMENT)),
9124
+ adjustedScore: roundScore(
9125
+ Math.max(0, nativeScore - Math.min(signalAdj, MAX_SIGNAL_ADJUSTMENT))
9126
+ ),
9127
+ findings: [...signal.findings]
9128
+ });
9129
+ }
9130
+ const totalAdj = Math.min(totalRawAdj, MAX_SIGNAL_ADJUSTMENT);
9131
+ const adjustedScore = roundScore(Math.max(0, nativeScore - totalAdj));
9132
+ for (const summary of summaries) {
9133
+ summary.adjustedScore = adjustedScore;
9134
+ summary.scoreAdjustment = -roundScore(totalAdj);
9135
+ }
9136
+ return { adjustedScore, adjustment: roundScore(totalAdj), summaries };
7519
9137
  }
7520
- function dedupeFindings(findings) {
7521
- const seen = /* @__PURE__ */ new Set();
7522
- return findings.filter((f) => {
7523
- const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
7524
- if (seen.has(key)) return false;
7525
- seen.add(key);
7526
- return true;
7527
- });
9138
+ function statusForScore(score) {
9139
+ if (score >= 3.5) return "verified";
9140
+ if (score >= 2.5) return "info";
9141
+ if (score >= 1.5) return "warning";
9142
+ if (score > 0) return "critical";
9143
+ return "critical";
7528
9144
  }
7529
- function parseSarifJson(raw, extraDimensionRules) {
7530
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
7531
- const dimensionRules = extraDimensionRules ? [...DIMENSION_RULES, ...extraDimensionRules] : DIMENSION_RULES;
7532
- const doc = raw;
7533
- if (!Array.isArray(doc.runs)) return [];
7534
- const buckets = /* @__PURE__ */ new Map();
7535
- for (const run of doc.runs) {
7536
- const driverName = run.tool?.driver?.name ?? "unknown";
7537
- const source = `sarif:${driverName}`;
7538
- const ruleDefaultLevels = /* @__PURE__ */ new Map();
7539
- for (const rule of run.tool?.driver?.rules ?? []) {
7540
- if (rule.id && rule.defaultConfiguration?.level) {
7541
- ruleDefaultLevels.set(rule.id, rule.defaultConfiguration.level);
7542
- }
7543
- }
7544
- for (const result of run.results ?? []) {
7545
- const ruleId = result.ruleId ?? "unknown";
7546
- const effectiveLevel = result.level ?? ruleDefaultLevels.get(ruleId) ?? "warning";
7547
- const severity = mapLevel(effectiveLevel);
7548
- if (!severity) continue;
7549
- const message = result.message?.text ?? ruleId;
7550
- const location = renderLocation(result);
7551
- const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
7552
- const bucketKey = `${source}|${dimension}`;
7553
- if (!buckets.has(bucketKey)) {
7554
- buckets.set(bucketKey, { source, dimension, weight, findings: [] });
7555
- }
7556
- buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
9145
+ function mergeSignalsByCriterion(signals) {
9146
+ const merged = /* @__PURE__ */ new Map();
9147
+ for (const signal of signals) {
9148
+ const existing = merged.get(signal.criterionId);
9149
+ if (!existing) {
9150
+ merged.set(signal.criterionId, signal);
9151
+ continue;
7557
9152
  }
9153
+ merged.set(signal.criterionId, {
9154
+ criterionId: signal.criterionId,
9155
+ positiveEvidence: [...existing.positiveEvidence, ...signal.positiveEvidence],
9156
+ findings: [...existing.findings, ...signal.findings],
9157
+ metrics: [...existing.metrics ?? [], ...signal.metrics ?? []],
9158
+ notes: signal.notes ?? existing.notes,
9159
+ // N/A wins on merge: if either signal is N/A, the criterion is N/A.
9160
+ ...existing.notApplicable === true || signal.notApplicable === true ? { notApplicable: true } : {}
9161
+ });
7558
9162
  }
7559
- return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
7560
- source,
7561
- dimension,
7562
- weight,
7563
- findings: dedupeFindings(findings)
7564
- }));
9163
+ return merged;
7565
9164
  }
7566
-
7567
- // src/witan/scorecard-adapter.ts
7568
- import { readFileSync as readFileSync3 } from "fs";
7569
- var CHECK_RULES = {
7570
- // B2 — PR outcome traceability
7571
- "Branch-Protection": { dimension: "B2", weight: 0.8 },
7572
- "Code-Review": { dimension: "B2", weight: 0.7 },
7573
- // B3 — CI and QA discipline
7574
- "Dangerous-Workflow": { dimension: "B3", weight: 0.9 },
7575
- "Token-Permissions": { dimension: "B3", weight: 0.8 },
7576
- "CI-Tests": { dimension: "B3", weight: 0.7 },
7577
- Maintained: { dimension: "B3", weight: 0.3 },
7578
- // B4 — audit trail / release integrity
7579
- "Signed-Releases": { dimension: "B4", weight: 0.7 },
7580
- Packaging: { dimension: "B4", weight: 0.4 },
7581
- "Security-Policy": { dimension: "B4", weight: 0.4 },
7582
- // A4 — dependency hygiene
7583
- Vulnerabilities: { dimension: "A4", weight: 0.9 },
7584
- "Pinned-Dependencies": { dimension: "A4", weight: 0.8 },
7585
- "Dependency-Update-Tool": { dimension: "A4", weight: 0.6 },
7586
- // A2 — data-layer / static analysis
7587
- SAST: { dimension: "A2", weight: 0.7 },
7588
- "Binary-Artifacts": { dimension: "A2", weight: 0.6 },
7589
- // A1 — test integrity
7590
- Fuzzing: { dimension: "A1", weight: 0.3 }
7591
- };
7592
- function mapScoreToSeverity(score) {
7593
- if (score == null || Number.isNaN(score)) return null;
7594
- if (score < 0) return null;
7595
- if (score >= 10) return null;
7596
- if (score <= 3) return "critical";
7597
- if (score <= 6) return "warning";
7598
- return "info";
9165
+ function usesMetricScoring(rubricVersion) {
9166
+ return rubricVersion === WITAN_RUBRIC_VERSION_V1 || rubricVersion === WITAN_RUBRIC_VERSION_V2 || rubricVersion === WITAN_RUBRIC_VERSION_V3 || rubricVersion === WITAN_TRADING_RUBRIC_VERSION_V0;
7599
9167
  }
7600
- function dedupeFindings2(findings) {
7601
- const seen = /* @__PURE__ */ new Set();
7602
- return findings.filter((f) => {
7603
- const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
7604
- if (seen.has(key)) return false;
7605
- seen.add(key);
7606
- return true;
7607
- });
9168
+ function unmeasuredStatus(rubricVersion) {
9169
+ return rubricVersion === WITAN_TRADING_RUBRIC_VERSION_V0 ? "unverified" : "insufficient_data";
7608
9170
  }
7609
- function parseScorecardJson(raw) {
7610
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
7611
- const doc = raw;
7612
- if (!Array.isArray(doc.checks)) return [];
7613
- const buckets = /* @__PURE__ */ new Map();
7614
- for (const check of doc.checks) {
7615
- const name = check.name;
7616
- if (!name) continue;
7617
- const rule = CHECK_RULES[name];
7618
- if (!rule) continue;
7619
- const severity = mapScoreToSeverity(check.score);
7620
- if (!severity) continue;
7621
- const scoreText = typeof check.score === "number" ? `${check.score}/10` : "n/a";
7622
- const message = `${name} (Scorecard ${scoreText}): ${check.reason ?? "weakness detected"}`.slice(0, 500);
7623
- const location = check.documentation?.url;
7624
- const bucket = buckets.get(rule.dimension) ?? { weight: 0, findings: [] };
7625
- bucket.weight = Math.max(bucket.weight, rule.weight);
7626
- bucket.findings.push({
7627
- ruleId: `scorecard:${name}`,
7628
- severity,
7629
- message,
7630
- ...location ? { location } : {}
7631
- });
7632
- buckets.set(rule.dimension, bucket);
9171
+ function scoreCriterion(signal, rubricVersion) {
9172
+ if (!signal) {
9173
+ return {
9174
+ score: 0,
9175
+ status: unmeasuredStatus(rubricVersion),
9176
+ evidence: [],
9177
+ findings: [],
9178
+ metrics: []
9179
+ };
7633
9180
  }
7634
- return Array.from(buckets.entries()).map(([dimension, { weight, findings }]) => ({
7635
- source: "scorecard",
7636
- dimension,
7637
- weight,
7638
- findings: dedupeFindings2(findings)
7639
- }));
7640
- }
7641
-
7642
- // src/witan/generic-adapter.ts
7643
- import { readFileSync as readFileSync4 } from "fs";
7644
- var VALID_DIMENSIONS = /* @__PURE__ */ new Set([
7645
- "A1",
7646
- "A2",
7647
- "A3",
7648
- "A4",
7649
- "A5",
7650
- "B1",
7651
- "B2",
7652
- "B3",
7653
- "B4",
7654
- "B5",
7655
- "B6"
7656
- ]);
7657
- var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
7658
- function isGenericSignalDocument(raw) {
7659
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
7660
- const doc = raw;
7661
- return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
9181
+ if (signal.notApplicable === true) {
9182
+ return {
9183
+ score: 0,
9184
+ status: "not_applicable",
9185
+ evidence: [],
9186
+ findings: [],
9187
+ metrics: []
9188
+ };
9189
+ }
9190
+ const evidence = signal.positiveEvidence;
9191
+ const findings = signal.findings;
9192
+ const metrics = signal.metrics ?? [];
9193
+ const evidenceCount = evidence.length + findings.length;
9194
+ if (evidenceCount === 0) {
9195
+ if (!usesMetricScoring(rubricVersion) || metrics.length === 0) {
9196
+ return {
9197
+ score: 0,
9198
+ status: unmeasuredStatus(rubricVersion),
9199
+ evidence,
9200
+ findings,
9201
+ metrics
9202
+ };
9203
+ }
9204
+ }
9205
+ if (usesMetricScoring(rubricVersion)) {
9206
+ const measuredMetrics = metrics.length > 0 ? metrics : fallbackMetricsForEvidence(evidence, findings);
9207
+ const score = capScoreForFindings(scoreMetrics(measuredMetrics), findings);
9208
+ const status = statusForScoreAndFindings(score, findings);
9209
+ return {
9210
+ score,
9211
+ status,
9212
+ evidence,
9213
+ findings: ensureFindingsExplainStatus(signal.criterionId, score, status, findings, evidence),
9214
+ metrics: measuredMetrics
9215
+ };
9216
+ }
9217
+ if (findings.some((finding) => finding.severity === "critical")) {
9218
+ return {
9219
+ score: 1,
9220
+ status: "critical",
9221
+ evidence,
9222
+ findings,
9223
+ metrics
9224
+ };
9225
+ }
9226
+ if (findings.some((finding) => finding.severity === "warning")) {
9227
+ return {
9228
+ score: 2,
9229
+ status: "warning",
9230
+ evidence,
9231
+ findings,
9232
+ metrics
9233
+ };
9234
+ }
9235
+ if (findings.some((finding) => finding.severity === "info")) {
9236
+ return {
9237
+ score: 3,
9238
+ status: "info",
9239
+ evidence,
9240
+ findings,
9241
+ metrics
9242
+ };
9243
+ }
9244
+ return {
9245
+ score: 4,
9246
+ status: "verified",
9247
+ evidence,
9248
+ findings,
9249
+ metrics
9250
+ };
7662
9251
  }
7663
- function parseGenericJson(raw) {
7664
- if (!isGenericSignalDocument(raw)) return [];
7665
- const source = raw.tool ?? "unknown";
7666
- const signals = [];
7667
- for (const signal of raw.signals ?? []) {
7668
- const dimension = signal.dimension;
7669
- if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
7670
- const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
7671
- const findings = [];
7672
- for (const finding of signal.findings ?? []) {
7673
- const severity = finding.severity;
7674
- if (!severity || !VALID_SEVERITIES.has(severity)) continue;
7675
- const ruleId = finding.ruleId ?? "unknown";
7676
- findings.push({
7677
- ruleId,
7678
- severity,
7679
- message: finding.message ?? ruleId,
7680
- ...finding.location ? { location: finding.location } : {}
7681
- });
9252
+ function fallbackMetricsForEvidence(evidence, findings) {
9253
+ return [
9254
+ {
9255
+ name: "evidence_depth",
9256
+ label: "Evidence depth",
9257
+ value: Math.min(evidence.length + findings.length + 1, 4),
9258
+ max: 4,
9259
+ weight: 1,
9260
+ unit: "signals",
9261
+ description: "Conservative v1 fallback for externally supplied evidence that has not provided criterion-specific depth metrics."
7682
9262
  }
7683
- if (findings.length === 0) continue;
7684
- signals.push({ source, dimension, weight, findings });
7685
- }
7686
- return signals;
9263
+ ];
7687
9264
  }
7688
-
7689
- // src/witan/ingest.ts
7690
- import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
7691
- import { join as join2 } from "path";
7692
-
7693
- // src/witan/finding-limits.ts
7694
- var RULE_ID_MAX = 200;
7695
- var MESSAGE_MAX = 500;
7696
- var LOCATION_MAX = 700;
7697
- function clamp(value, max) {
7698
- if (value.length <= max) return value;
7699
- const ellipsis = "...";
7700
- return `${value.slice(0, Math.max(max - ellipsis.length, 0))}${ellipsis}`;
9265
+ function scoreMetrics(metrics) {
9266
+ let weightedTotal = 0;
9267
+ let totalWeight = 0;
9268
+ for (const metric2 of metrics) {
9269
+ const normalized = metric2.max ? Math.min(metric2.value / metric2.max, 1) : Math.min(metric2.value, 1);
9270
+ weightedTotal += normalized * metric2.weight;
9271
+ totalWeight += metric2.weight;
9272
+ }
9273
+ if (totalWeight === 0) return 0;
9274
+ return roundScore(weightedTotal / totalWeight * 4);
7701
9275
  }
7702
- function clampFinding(finding) {
7703
- return {
7704
- ...finding,
7705
- ruleId: clamp(finding.ruleId, RULE_ID_MAX),
7706
- message: clamp(finding.message, MESSAGE_MAX),
7707
- ...finding.location ? { location: clamp(finding.location, LOCATION_MAX) } : {}
7708
- };
9276
+ function capScoreForFindings(score, findings) {
9277
+ if (findings.some((finding) => finding.severity === "critical")) return 1.4;
9278
+ if (findings.some((finding) => finding.severity === "warning")) return Math.min(score, 2.4);
9279
+ if (findings.some((finding) => finding.severity === "info")) return Math.min(score, 3.4);
9280
+ return score;
7709
9281
  }
7710
-
7711
- // src/witan/ingest.ts
7712
- function looksLikeSarif(raw) {
7713
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
7714
- return Array.isArray(raw.runs);
9282
+ function statusForScoreAndFindings(score, findings) {
9283
+ if (findings.some((finding) => finding.severity === "critical")) return "critical";
9284
+ if (findings.some((finding) => finding.severity === "warning")) return "warning";
9285
+ if (score >= 3.5 && findings.length === 0) return "verified";
9286
+ if (score >= 2.5) return "info";
9287
+ if (score >= 1.5) return "warning";
9288
+ return "critical";
7715
9289
  }
7716
- function looksLikeScorecard(raw) {
7717
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
7718
- return Array.isArray(raw.checks);
9290
+ function ensureFindingsExplainStatus(criterionId, score, status, findings, evidence) {
9291
+ if (findings.length > 0) return [...findings];
9292
+ if (status !== "critical" && status !== "warning") return [...findings];
9293
+ const anchor = evidence[0] ?? {
9294
+ kind: "repository",
9295
+ label: `${criterionId} metric-derived score`,
9296
+ path: "."
9297
+ };
9298
+ return [
9299
+ {
9300
+ severity: status,
9301
+ summary: `${criterionId} metric-derived score is ${score.toFixed(1)}/4.0, in the ${status} band \u2014 no single finding drove this; it reflects the combined metric weighting below.`,
9302
+ evidence: anchor
9303
+ }
9304
+ ];
7719
9305
  }
7720
- function countRawEntries(raw) {
7721
- const obj = raw;
7722
- if (Array.isArray(obj.runs)) {
7723
- return obj.runs.reduce((sum, run) => {
7724
- const results = run.results;
7725
- return sum + (Array.isArray(results) ? results.length : 0);
7726
- }, 0);
7727
- }
7728
- if (Array.isArray(obj.checks)) return obj.checks.length;
7729
- if (Array.isArray(obj.signals)) {
7730
- return obj.signals.reduce((sum, signal) => {
7731
- const findings = signal.findings;
7732
- return sum + (Array.isArray(findings) ? findings.length : 0);
7733
- }, 0);
7734
- }
7735
- return 0;
9306
+ function averageScore(criteria) {
9307
+ const applicable = criteria.filter(
9308
+ (criterion) => criterion.status !== "not_applicable" && criterion.status !== "insufficient_data"
9309
+ );
9310
+ if (applicable.length === 0) return 0;
9311
+ const total = applicable.reduce((sum, criterion) => sum + criterion.score, 0);
9312
+ return roundScore(total / applicable.length);
7736
9313
  }
7737
- function rawToolName(raw) {
7738
- const obj = raw;
7739
- if (Array.isArray(obj.runs)) {
7740
- const firstRun = obj.runs[0];
7741
- return firstRun?.tool?.driver?.name ?? "unknown";
7742
- }
7743
- if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
7744
- return "scorecard";
9314
+ function roundScore(score) {
9315
+ return Math.round(score * 10) / 10;
7745
9316
  }
7746
- function parseIngestFile(filePath) {
7747
- let raw;
7748
- try {
7749
- raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
7750
- } catch (error) {
7751
- const message = error instanceof Error ? error.message : String(error);
7752
- throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
7753
- }
7754
- let signals;
7755
- if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
7756
- else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
7757
- else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
7758
- if (!signals) {
7759
- throw new Error(
7760
- `Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
7761
- );
7762
- }
7763
- const rawCount = countRawEntries(raw);
7764
- const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
7765
- if (rawCount > 0 && mappedCount === 0) {
7766
- process.stderr.write(
7767
- `Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
7768
- `
7769
- );
7770
- }
7771
- return signals.map((signal) => ({
7772
- ...signal,
7773
- findings: signal.findings.map(clampFinding)
7774
- }));
9317
+
9318
+ // ../witan/src/public-scan.ts
9319
+ function scoreRepoWithPublicCejel(options) {
9320
+ const input = buildWitanInputFromRepo({
9321
+ productSlug: options.productSlug,
9322
+ productDisplayName: options.productDisplayName,
9323
+ repoPath: options.repoPath,
9324
+ ...options.generatedAt ? { generatedAt: options.generatedAt } : {}
9325
+ });
9326
+ const inputSignals = resolvePublicIngestSignals(options);
9327
+ return createWitanReport(input, inputSignals.length > 0 ? inputSignals : void 0);
7775
9328
  }
7776
- function expandIngestPattern(pattern) {
7777
- if (!pattern.includes("*")) return [pattern];
7778
- const lastSlash = pattern.lastIndexOf("/");
7779
- const dir = lastSlash === -1 ? "." : pattern.slice(0, lastSlash);
7780
- const filePattern = lastSlash === -1 ? pattern : pattern.slice(lastSlash + 1);
7781
- const regexSource = filePattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
7782
- const regex = new RegExp(`^${regexSource}$`);
7783
- let entries;
7784
- try {
7785
- entries = readdirSync2(dir);
7786
- } catch {
7787
- return [];
9329
+ function resolvePublicIngestSignals(options) {
9330
+ const seen = /* @__PURE__ */ new Set();
9331
+ const files = [];
9332
+ for (const pattern of options.ingestPatterns ?? []) {
9333
+ const matches = expandIngestPattern(pattern);
9334
+ if (matches.length === 0 && options.warnOnEmptyIngestMatch) {
9335
+ process.stderr.write(`Cejel: --ingest pattern matched no files: ${pattern}
9336
+ `);
9337
+ }
9338
+ for (const match of matches) {
9339
+ const resolved = resolve2(match);
9340
+ if (seen.has(resolved)) continue;
9341
+ seen.add(resolved);
9342
+ files.push(match);
9343
+ }
7788
9344
  }
7789
- return entries.filter((name) => regex.test(name)).sort().map((name) => join2(dir, name));
7790
- }
7791
- function discoverIngestInputs(repoPath) {
7792
- const inputsDir = join2(repoPath, ".cejel", "inputs");
7793
- let entries;
7794
- try {
7795
- entries = readdirSync2(inputsDir);
7796
- } catch {
7797
- return [];
9345
+ for (const discovered of discoverIngestInputs(options.repoPath)) {
9346
+ const resolved = resolve2(discovered);
9347
+ if (seen.has(resolved)) continue;
9348
+ seen.add(resolved);
9349
+ files.push(discovered);
7798
9350
  }
7799
- return entries.filter((name) => /\.(sarif|json)$/i.test(name)).sort().map((name) => join2(inputsDir, name));
9351
+ return files.flatMap((file) => parseIngestFile(file));
7800
9352
  }
7801
9353
 
7802
- // src/scan.ts
7803
- import { resolve as resolve2 } from "path";
9354
+ // ../witan/src/repo-clone.ts
9355
+ import { execFileSync as execFileSync2 } from "child_process";
9356
+ import { mkdirSync, rmSync } from "fs";
9357
+ import { tmpdir } from "os";
9358
+ import { join as join4 } from "path";
9359
+
9360
+ // ../witan/src/cejel-package-name.ts
9361
+ import { readFileSync as readFileSync7 } from "fs";
9362
+ import { fileURLToPath } from "url";
9363
+
9364
+ // ../witan/src/leaderboard.ts
9365
+ var RESERVED_CORPUS_SLUGS = ["biome", "tsconfig", "package"];
9366
+ var LeaderboardCorpusEntrySchema = external_exports.object({
9367
+ // Also the evidence-report slug (reports/<name>.{json,md,svg}) — min length 3
9368
+ // to satisfy the WitanReport productSlug pattern.
9369
+ name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/).refine((value) => !RESERVED_CORPUS_SLUGS.includes(value), {
9370
+ message: "Corpus entry name collides with a tool config filename (reports/<name>.json would be discovered by that tool) \u2014 pick a different slug, e.g. biomejs."
9371
+ }),
9372
+ category: external_exports.string().min(1).max(80),
9373
+ expectedArchetype: external_exports.string().min(1).max(40),
9374
+ license: external_exports.string().min(1).max(80),
9375
+ /**
9376
+ * Repository visibility — the redaction policy's first-class input
9377
+ * (goal_cejel_redaction_policy_is_verifiability_2026-07-12): a path is
9378
+ * published exactly when the reader can check it (public), and withheld
9379
+ * entirely when they can't (private). FAIL CLOSED: absent or unrecognized
9380
+ * resolves to 'private' via `.catch` rather than throwing or defaulting
9381
+ * open, so a corpus entry can never accidentally publish paths by omission.
9382
+ */
9383
+ visibility: external_exports.enum(["public", "private"]).catch("private"),
9384
+ url: external_exports.string().url().optional(),
9385
+ /**
9386
+ * Immutable source snapshot for URL entries. A rubric rescore always uses
9387
+ * the same commits; changing one is a separate corpus update.
9388
+ */
9389
+ commit: external_exports.string().regex(/^[0-9a-f]{40}$/).optional(),
9390
+ self: external_exports.literal(true).optional(),
9391
+ /**
9392
+ * A directory inside THIS repository (relative to its root), for internal
9393
+ * entries that are a sub-package rather than the whole repo (e.g. the public
9394
+ * cejel CLI at packages/witan-cli). Scored locally like "self".
9395
+ */
9396
+ path: external_exports.string().min(1).max(200).regex(/^[A-Za-z0-9._/-]+$/).refine((value) => !value.startsWith("/") && !value.split("/").includes(".."), {
9397
+ message: 'Corpus entry "path" must be relative and must not traverse upward.'
9398
+ }).optional()
9399
+ }).strict().refine((entry) => (entry.url ? 1 : 0) + (entry.self ? 1 : 0) + (entry.path ? 1 : 0) === 1, {
9400
+ message: 'Corpus entry must have exactly one of "url", "self", or "path".'
9401
+ }).refine((entry) => entry.url ? entry.commit !== void 0 : entry.commit === void 0, {
9402
+ message: 'Every URL corpus entry must declare exactly one immutable 40-character "commit".'
9403
+ });
9404
+ var LeaderboardCorpusSchema = external_exports.object({
9405
+ comment: external_exports.string().min(1),
9406
+ entries: external_exports.array(LeaderboardCorpusEntrySchema).min(1)
9407
+ }).strict().refine(
9408
+ (corpus) => new Set(corpus.entries.map((entry) => entry.name)).size === corpus.entries.length,
9409
+ { message: "Corpus entry names must be unique." }
9410
+ );
9411
+
9412
+ // ../witan/src/quant-integrity.ts
9413
+ import { readFileSync as readFileSync10 } from "fs";
9414
+ import { join as join8 } from "path";
9415
+
9416
+ // ../witan/src/quant-metrics-grading.ts
9417
+ import { createHash as createHash2 } from "crypto";
9418
+ import { readFileSync as readFileSync9 } from "fs";
9419
+ import { join as join7 } from "path";
9420
+
9421
+ // ../witan/src/quant-run-tier-grading.ts
9422
+ import { createHash as createHash3 } from "crypto";
7804
9423
 
7805
9424
  // src/product-identity.ts
7806
- import { existsSync, readFileSync as readFileSync6 } from "fs";
7807
- import { basename as basename2, join as join3 } from "path";
9425
+ import { existsSync as existsSync3, readFileSync as readFileSync11 } from "fs";
9426
+ import { basename as basename3, join as join9 } from "path";
7808
9427
  var SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;
7809
9428
  var FALLBACK_SLUG = "repo";
7810
9429
  var FALLBACK_DISPLAY_NAME = "Repository";
7811
9430
  function deriveProductIdentity(repoPath) {
7812
- const packageJsonPath = join3(repoPath, "package.json");
7813
- const raw = readPackageName(packageJsonPath) ?? basename2(repoPath);
9431
+ const packageJsonPath = join9(repoPath, "package.json");
9432
+ const raw = readPackageName(packageJsonPath) ?? basename3(repoPath);
7814
9433
  const displayName = raw.trim().length > 0 ? raw.trim() : FALLBACK_DISPLAY_NAME;
7815
9434
  return {
7816
9435
  productSlug: slugify(raw),
@@ -7818,9 +9437,9 @@ function deriveProductIdentity(repoPath) {
7818
9437
  };
7819
9438
  }
7820
9439
  function readPackageName(packageJsonPath) {
7821
- if (!existsSync(packageJsonPath)) return void 0;
9440
+ if (!existsSync3(packageJsonPath)) return void 0;
7822
9441
  try {
7823
- const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
9442
+ const parsed = JSON.parse(readFileSync11(packageJsonPath, "utf8"));
7824
9443
  if (typeof parsed === "object" && parsed !== null && "name" in parsed) {
7825
9444
  const name = parsed.name;
7826
9445
  if (typeof name === "string" && name.trim().length > 0) return name;
@@ -7881,52 +9500,28 @@ function buildWitanCliSummary(report) {
7881
9500
  // src/scan.ts
7882
9501
  function runCejelScan(options) {
7883
9502
  const identity = deriveProductIdentity(options.repoPath);
7884
- const input = buildWitanInputFromRepo({
9503
+ const report = scoreRepoWithPublicCejel({
7885
9504
  productSlug: identity.productSlug,
7886
9505
  productDisplayName: identity.productDisplayName,
7887
- repoPath: options.repoPath
9506
+ repoPath: options.repoPath,
9507
+ ingestPatterns: options.ingestPatterns,
9508
+ warnOnEmptyIngestMatch: options.warnOnEmptyIngestMatch
7888
9509
  });
7889
- const inputSignals = resolveIngestSignals(options);
7890
- const report = createWitanReport(input, inputSignals.length > 0 ? inputSignals : void 0);
7891
9510
  const summary = buildWitanCliSummary(report);
7892
9511
  return { report, summary };
7893
9512
  }
7894
- function resolveIngestSignals(options) {
7895
- const seen = /* @__PURE__ */ new Set();
7896
- const files = [];
7897
- for (const pattern of options.ingestPatterns ?? []) {
7898
- const matches = expandIngestPattern(pattern);
7899
- if (matches.length === 0 && options.warnOnEmptyIngestMatch) {
7900
- process.stderr.write(`Cejel: --ingest pattern matched no files: ${pattern}
7901
- `);
7902
- }
7903
- for (const match of matches) {
7904
- const resolved = resolve2(match);
7905
- if (seen.has(resolved)) continue;
7906
- seen.add(resolved);
7907
- files.push(match);
7908
- }
7909
- }
7910
- for (const discovered of discoverIngestInputs(options.repoPath)) {
7911
- const resolved = resolve2(discovered);
7912
- if (seen.has(resolved)) continue;
7913
- seen.add(resolved);
7914
- files.push(discovered);
7915
- }
7916
- return files.flatMap((file) => parseIngestFile(file));
7917
- }
7918
9513
 
7919
9514
  export {
7920
9515
  __commonJS,
7921
9516
  __export,
7922
9517
  __toESM,
7923
- ZodOptional,
7924
- ZodFirstPartyTypeKind,
7925
- objectType,
7926
- external_exports,
7927
9518
  formatExternalSourceLine,
7928
9519
  renderWitanHtmlReport,
7929
9520
  renderWitanBadgeEndpoint,
7930
9521
  renderWitanBadgeSvg,
9522
+ ZodOptional,
9523
+ ZodFirstPartyTypeKind,
9524
+ objectType,
9525
+ external_exports,
7931
9526
  runCejelScan
7932
9527
  };