@abloh/cli 0.1.1 → 0.1.3-rc.1

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.
Files changed (2) hide show
  1. package/dist/index.js +77 -27
  2. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/index.ts
4
4
  import {
5
5
  writeFileSync as writeFileSync11,
6
- mkdirSync as mkdirSync9,
6
+ mkdirSync as mkdirSync10,
7
7
  mkdtempSync as mkdtempSync10,
8
8
  readFileSync as readFileSync23,
9
9
  readlinkSync as readlinkSync4,
@@ -11089,6 +11089,7 @@ async function diagnoseBaselineFailures(input) {
11089
11089
  import {
11090
11090
  existsSync as existsSync9,
11091
11091
  lstatSync as lstatSync12,
11092
+ mkdirSync as mkdirSync8,
11092
11093
  readFileSync as readFileSync18,
11093
11094
  readdirSync as readdirSync7,
11094
11095
  rmSync as rmSync9,
@@ -11182,8 +11183,9 @@ Overrides:
11182
11183
 
11183
11184
  --no-prepare skip the automatic vitest coverage-provider staging
11184
11185
 
11185
- Writes abloh.yml, or adds the environment block to one you already have \u2014 every line already in
11186
- that file is left alone, including the tier. It refuses only when the file already configures
11186
+ Writes abloh.yml and .github/workflows/abloh-check.yml. An abloh.yml you already have gets the
11187
+ environment block appended and every line already in it left alone; a workflow you already have is
11188
+ never touched. It refuses only when the policy file already configures
11187
11189
  environment. It never modifies the repository otherwise \u2014 no dependency, manifest, lockfile, or
11188
11190
  source changes, and it never runs tests. For a Vitest repository without @vitest/coverage-v8 it
11189
11191
  stages that provider into Abloh's own cache (the one registry access; disable with --no-prepare).
@@ -11493,13 +11495,6 @@ function standardInstallCommand(packageManager, version, hasLockfile) {
11493
11495
  }
11494
11496
  function renderPolicyDefaults() {
11495
11497
  return [
11496
- "# DATA TIER \u2014 what leaves your CI.",
11497
- "# 0 counts and locations only. No model calls.",
11498
- "# 1 the review model runs here, under your credentials. Abloh receives structure only.",
11499
- "# 2 Abloh also stores the mutated source span of each finding, the model's",
11500
- "# reasoning and any test it proves. Your code is retained by Abloh.",
11501
- "tier: 2",
11502
- "",
11503
11498
  "# THRESHOLD \u2014 the catch rate a run has to reach to pass. Abloh plants deliberate",
11504
11499
  "# changes in your diff and counts how many your tests notice; 70 means seven in ten.",
11505
11500
  "threshold: 70",
@@ -11554,6 +11549,45 @@ function renderPolicy(input) {
11554
11549
  function declaresTopLevelKey(document, key) {
11555
11550
  return new RegExp(String.raw`^${key}\s*:`, "mu").test(document);
11556
11551
  }
11552
+ var WORKFLOW_RELATIVE_PATH = ".github/workflows/abloh-check.yml";
11553
+ var PINNED_ACTION = "Vero-Technology/abloh-action@3f8f0058d1ed1fae11d33a109e7e598bd3450097";
11554
+ function renderWorkflow(input) {
11555
+ const build = input.installCommand === null ? [" # Your normal build and dependency steps go here."] : [
11556
+ ` - run: ${input.installCommand}`,
11557
+ ...input.installDirectory === "." ? [] : [` working-directory: ${input.installDirectory}`]
11558
+ ];
11559
+ return [
11560
+ "name: Abloh",
11561
+ "on:",
11562
+ " pull_request:",
11563
+ "",
11564
+ "jobs:",
11565
+ " abloh:",
11566
+ " runs-on: ubuntu-latest",
11567
+ " permissions:",
11568
+ " contents: read",
11569
+ " id-token: write # short-lived identity for the Abloh model gateway",
11570
+ " steps:",
11571
+ " - uses: actions/checkout@v4",
11572
+ " with:",
11573
+ " ref: ${{ github.event.pull_request.head.sha }}",
11574
+ " fetch-depth: 0 # Abloh diffs against the base ref",
11575
+ " persist-credentials: false",
11576
+ ...build,
11577
+ ` - uses: ${PINNED_ACTION}`,
11578
+ " with:",
11579
+ " base: ${{ github.event.pull_request.base.sha }}",
11580
+ ""
11581
+ ].join("\n");
11582
+ }
11583
+ function writeWorkflow(repoDir, input) {
11584
+ const path = join21(repoDir, WORKFLOW_RELATIVE_PATH);
11585
+ const legacy = join21(repoDir, ".github", "workflows", "abloh.yml");
11586
+ if (existsSync9(path) || existsSync9(legacy)) return "exists";
11587
+ mkdirSync8(dirname12(path), { recursive: true });
11588
+ writeFileSync7(path, renderWorkflow(input), { encoding: "utf8", mode: 420, flag: "wx" });
11589
+ return "created";
11590
+ }
11557
11591
  function writePolicy(policyPath, input) {
11558
11592
  if (!existsSync9(policyPath)) {
11559
11593
  writeFileSync7(policyPath, renderPolicy(input), { encoding: "utf8", mode: 420, flag: "wx" });
@@ -11646,9 +11680,19 @@ async function initRepository(options) {
11646
11680
  else writeFileSync7(policyPath, previous2, { encoding: "utf8", mode: 420 });
11647
11681
  throw error;
11648
11682
  }
11683
+ const pythonWorkflow = writeWorkflow(repoDir, {
11684
+ subdir: inferredSubdir,
11685
+ runtimeImage: image2.ref,
11686
+ testCommand: null,
11687
+ installCommand: installCommand2,
11688
+ installDirectory: installDirectory2,
11689
+ identityFiles: identities2
11690
+ });
11649
11691
  return {
11650
11692
  repoDir,
11651
11693
  policyPath,
11694
+ workflowPath: join21(repoDir, WORKFLOW_RELATIVE_PATH),
11695
+ workflowState: pythonWorkflow,
11652
11696
  subdir: inferredSubdir,
11653
11697
  language: "python",
11654
11698
  runner: "pytest",
@@ -11726,9 +11770,12 @@ async function initRepository(options) {
11726
11770
  else writeFileSync7(policyPath, previous, { encoding: "utf8", mode: 420 });
11727
11771
  throw error;
11728
11772
  }
11773
+ const workflowState = writeWorkflow(repoDir, policyInput);
11729
11774
  return {
11730
11775
  repoDir,
11731
11776
  policyPath,
11777
+ workflowPath: join21(repoDir, WORKFLOW_RELATIVE_PATH),
11778
+ workflowState,
11732
11779
  subdir: target.subdir,
11733
11780
  language: "javascript",
11734
11781
  runner: target.runner,
@@ -11754,7 +11801,10 @@ function renderInitResult(result) {
11754
11801
  `Layer 0 coverage: @vitest/coverage-v8${provider.vitestVersion === null ? "" : `@${provider.vitestVersion}`} is not available \u2014 after the repository's dependency install, run \`abloh prepare\` (or add it as an exact dev dependency); without it Layer 0 reports cannot-attest.`
11755
11802
  ],
11756
11803
  `Proof image: ${result.runtimeImage} (${result.runtimeImageSource})`,
11757
- "Next: review and commit abloh.yml, then add the Abloh GitHub Action."
11804
+ result.workflowState === "created" ? `Created ${result.workflowPath}` : `Left ${result.workflowPath} alone \u2014 a workflow is already there`,
11805
+ /* Both files, named, because "commit abloh.yml" was the whole instruction when the workflow
11806
+ was the customer's to write and is now half of it. */
11807
+ "Next: review and commit both files. Abloh runs on the pull request that adds them."
11758
11808
  ].join("\n") + "\n";
11759
11809
  }
11760
11810
 
@@ -11957,7 +12007,7 @@ import {
11957
12007
  fsyncSync as fsyncSync2,
11958
12008
  fstatSync as fstatSync5,
11959
12009
  lstatSync as lstatSync13,
11960
- mkdirSync as mkdirSync8,
12010
+ mkdirSync as mkdirSync9,
11961
12011
  mkdtempSync as mkdtempSync8,
11962
12012
  openSync as openSync6,
11963
12013
  readFileSync as readFileSync20,
@@ -12242,7 +12292,7 @@ function prepareAtomicCopy(source, destination, nonce) {
12242
12292
  if (identityOf(source).kind !== "file") {
12243
12293
  throw new Error(`staged artifact must be a regular file: ${source}`);
12244
12294
  }
12245
- mkdirSync8(dirname13(destination), { recursive: true });
12295
+ mkdirSync9(dirname13(destination), { recursive: true });
12246
12296
  assertNoSymlinkComponents(dirname13(destination), destination);
12247
12297
  if (existsSync11(destination)) {
12248
12298
  const info = lstatSync13(destination);
@@ -12265,7 +12315,7 @@ function prepareAtomicCopy(source, destination, nonce) {
12265
12315
  return temporary;
12266
12316
  }
12267
12317
  function copyDirectory(source, destination) {
12268
- mkdirSync8(destination, { mode: 448 });
12318
+ mkdirSync9(destination, { mode: 448 });
12269
12319
  for (const entry of readdirSync8(source, { withFileTypes: true })) {
12270
12320
  const from = join23(source, entry.name);
12271
12321
  const to = join23(destination, entry.name);
@@ -12287,7 +12337,7 @@ function prepareAtomicDirectory(source, destination, nonce) {
12287
12337
  if (identityOf(source).kind !== "directory") {
12288
12338
  throw new Error(`staged artifact must be a directory: ${source}`);
12289
12339
  }
12290
- mkdirSync8(dirname13(destination), { recursive: true });
12340
+ mkdirSync9(dirname13(destination), { recursive: true });
12291
12341
  assertNoSymlinkComponents(dirname13(destination), destination);
12292
12342
  const temporary = join23(
12293
12343
  dirname13(destination),
@@ -12551,7 +12601,7 @@ function acquirePublicationLock(controlDestination, allowedDestinations) {
12551
12601
  const acquired = [];
12552
12602
  try {
12553
12603
  for (const lockPath of paths.locks) {
12554
- mkdirSync8(dirname13(lockPath), { recursive: true });
12604
+ mkdirSync9(dirname13(lockPath), { recursive: true });
12555
12605
  const fd = openSync6(
12556
12606
  lockPath,
12557
12607
  constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY | constants3.O_NOFOLLOW,
@@ -12724,7 +12774,7 @@ async function createArtifactOutputTransaction(input) {
12724
12774
  controlDestination: destinations.json,
12725
12775
  allowedDestinations
12726
12776
  });
12727
- mkdirSync8(dirname13(destinations.json), { recursive: true });
12777
+ mkdirSync9(dirname13(destinations.json), { recursive: true });
12728
12778
  assertNoSymlinkComponents(repoDir, destinations.json);
12729
12779
  publicationMetadata = acquirePublicationLock(destinations.json, allowedDestinations);
12730
12780
  input.publicationTestHooks?.afterCrashPoint?.({ phase: "locks-acquired" });
@@ -12736,7 +12786,7 @@ async function createArtifactOutputTransaction(input) {
12736
12786
  if (operations.some((operation) => operation.destination === destination)) {
12737
12787
  throw new Error(`staged artifacts collide at ${destination}`);
12738
12788
  }
12739
- mkdirSync8(dirname13(destination), { recursive: true });
12789
+ mkdirSync9(dirname13(destination), { recursive: true });
12740
12790
  assertNoSymlinkComponents(repoDir, destination);
12741
12791
  const parent = parentIdentity(destination);
12742
12792
  const existingIdentity = existsSync11(destination) ? identityOf(destination) : void 0;
@@ -13602,7 +13652,7 @@ function writeArtifacts(report, opts) {
13602
13652
  const patchRevertText = `${JSON.stringify(report.patchRevertLocal, null, 2)}
13603
13653
  `;
13604
13654
  patchRevertDigest = sha256Hex(patchRevertText);
13605
- mkdirSync9(dirname15(patchRevertOut), { recursive: true });
13655
+ mkdirSync10(dirname15(patchRevertOut), { recursive: true });
13606
13656
  writeFileSync11(patchRevertOut, patchRevertText, { mode: 384 });
13607
13657
  }
13608
13658
  const rationalesText = JSON.stringify(buildRationalesFile(report.findings), null, 2) + "\n";
@@ -13610,7 +13660,7 @@ function writeArtifacts(report, opts) {
13610
13660
  let rawReportDigest = null;
13611
13661
  if (report.rawReportText != null) {
13612
13662
  rawReportDigest = sha256Hex(report.rawReportText);
13613
- mkdirSync9(dirname15(rawReportOut), { recursive: true });
13663
+ mkdirSync10(dirname15(rawReportOut), { recursive: true });
13614
13664
  writeFileSync11(rawReportOut, report.rawReportText);
13615
13665
  } else {
13616
13666
  rmSync12(rawReportOut, { force: true });
@@ -13627,7 +13677,7 @@ function writeArtifacts(report, opts) {
13627
13677
  const redactedText = `${JSON.stringify(redacted, null, 2)}
13628
13678
  `;
13629
13679
  redactedReportDigest = sha256Hex(redactedText);
13630
- mkdirSync9(dirname15(redactedReportOut), { recursive: true });
13680
+ mkdirSync10(dirname15(redactedReportOut), { recursive: true });
13631
13681
  writeFileSync11(redactedReportOut, redactedText, { mode: 384 });
13632
13682
  } else {
13633
13683
  rmSync12(redactedReportOut, { force: true });
@@ -13638,7 +13688,7 @@ function writeArtifacts(report, opts) {
13638
13688
  let rawCoverageDigest = null;
13639
13689
  if (report.rawCoverageText != null) {
13640
13690
  rawCoverageDigest = sha256Hex(report.rawCoverageText);
13641
- mkdirSync9(dirname15(rawCoverageOut), { recursive: true });
13691
+ mkdirSync10(dirname15(rawCoverageOut), { recursive: true });
13642
13692
  writeFileSync11(rawCoverageOut, report.rawCoverageText);
13643
13693
  } else {
13644
13694
  rmSync12(rawCoverageOut, { force: true });
@@ -13647,17 +13697,17 @@ function writeArtifacts(report, opts) {
13647
13697
  if (report.rawCarrierReports && report.rawCarrierReports.length > 0) {
13648
13698
  const text = JSON.stringify({ schema: "attest-raw-carrier-reports/v2", reports: report.rawCarrierReports }, null, 2) + "\n";
13649
13699
  rawCarrierDigest = sha256Hex(text);
13650
- mkdirSync9(dirname15(rawCarrierOut), { recursive: true });
13700
+ mkdirSync10(dirname15(rawCarrierOut), { recursive: true });
13651
13701
  writeFileSync11(rawCarrierOut, text);
13652
13702
  } else {
13653
13703
  rmSync12(rawCarrierOut, { force: true });
13654
13704
  }
13655
13705
  const artifact = buildArtifact(report, rationalesDigest, rawReportDigest, rawCoverageDigest, rawCarrierDigest, patchRevertDigest, redactedReportDigest);
13656
- mkdirSync9(dirname15(rationalesOut), { recursive: true });
13706
+ mkdirSync10(dirname15(rationalesOut), { recursive: true });
13657
13707
  writeFileSync11(rationalesOut, rationalesText);
13658
- mkdirSync9(dirname15(jsonOut), { recursive: true });
13708
+ mkdirSync10(dirname15(jsonOut), { recursive: true });
13659
13709
  writeFileSync11(jsonOut, JSON.stringify(artifact, null, 2) + "\n");
13660
- mkdirSync9(dirname15(mdOut), { recursive: true });
13710
+ mkdirSync10(dirname15(mdOut), { recursive: true });
13661
13711
  writeFileSync11(mdOut, renderMarkdown(report, rawReportDigest, rawCoverageDigest));
13662
13712
  log(`staged ${logical.json} and ${logical.md}`);
13663
13713
  log(`rationales (local only): ${logical.rationales} \u2014 sha256 ${rationalesDigest.slice(0, 16)}\u2026 recorded in artifact`);
@@ -15462,7 +15512,7 @@ Replace each link with a tracked regular file, or point it to a tracked regular
15462
15512
  null,
15463
15513
  2
15464
15514
  ) + "\n";
15465
- mkdirSync9(dirname15(fixProofsOut), { recursive: true });
15515
+ mkdirSync10(dirname15(fixProofsOut), { recursive: true });
15466
15516
  writeFileSync11(fixProofsOut, fixProofsText);
15467
15517
  if (fixLoopBlock.state === "completed") fixLoopBlock = { ...fixLoopBlock, proofsDigest: sha256Hex(fixProofsText) };
15468
15518
  log(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloh/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3-rc.1",
4
4
  "description": "Abloh CLI: the `abloh run` command. The package will publish under the @abloh scope.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -26,16 +26,16 @@
26
26
  "dependencies": {
27
27
  "semver": "7.8.5",
28
28
  "yaml": "^2.5.0",
29
- "@abloh/core": "0.1.1",
30
- "@abloh/sandbox": "0.1.1",
31
- "@abloh/triage": "0.1.1",
32
- "@abloh/engine-stryker": "0.1.1",
33
- "@abloh/engine-python": "0.1.1"
29
+ "@abloh/sandbox": "0.1.2",
30
+ "@abloh/core": "0.1.2",
31
+ "@abloh/engine-python": "0.1.2",
32
+ "@abloh/triage": "0.1.2",
33
+ "@abloh/engine-stryker": "0.1.3-rc.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/semver": "7.7.1",
37
- "@abloh/github-app": "0.1.0",
38
- "@abloh/engine-deep-mutation": "0.1.0"
37
+ "@abloh/engine-deep-mutation": "0.1.0",
38
+ "@abloh/github-app": "0.1.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsup",