@method-ai-hq/sdk 0.20.0 → 0.20.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.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  MIT-licensed JavaScript API and the `method` CLI. Source and releases: https://github.com/method-ai-hq/method-sdk
4
4
 
5
5
  ```sh
6
- npm install https://github.com/method-ai-hq/method-sdk/releases/download/v0.20.0/method-ai-hq-sdk-0.20.0.tgz
6
+ npm install https://github.com/method-ai-hq/method-sdk/releases/download/v0.20.1/method-ai-hq-sdk-0.20.1.tgz
7
7
  npx method --version
8
8
  ```
9
9
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@method-ai-hq/sdk",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "description": "Build and run reusable .method files with checked steps and saved results.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "prepack": "npm --prefix ../.. run build"
36
36
  },
37
37
  "dependencies": {
38
- "@withmethod/runtime": "https://codeload.github.com/method-ai-hq/method-spec/tar.gz/v0.16.1",
38
+ "@withmethod/runtime": "https://codeload.github.com/method-ai-hq/method-spec/tar.gz/v0.16.2",
39
39
  "fflate": "^0.8.3",
40
40
  "yaml": "^2.9.0",
41
41
  "zod": "^3.25.76"
@@ -205,6 +205,7 @@ export declare function fixWaiting(client: MethodClient, file: string, options?:
205
205
  /** Runs cases of a Method file (quality.ts runCases); tests replace it. */
206
206
  export type RunCases = (file: string, flags: Record<string, never>, options: {
207
207
  ids: string[];
208
+ casesDir?: string;
208
209
  }) => Promise<{
209
210
  cases: {
210
211
  id: string;
@@ -213,8 +214,8 @@ export type RunCases = (file: string, flags: Record<string, never>, options: {
213
214
  }>;
214
215
  /**
215
216
  * The later check of an applied change: the Method's other cases (improve.method's background_cases) run on the changed
216
- * file. A failing case that belongs to a retired learned rule (its from.case) brings that rule back. Any other failure
217
- * undoes the change, saves the restored file as a new version, and opens the corrections it answered again, so the next
217
+ * file. A failing case that belongs to a retired learned rule (its from.case) brings that rule back. Any other case that
218
+ * fails now and passed before the change (a correction that no fix answered yet fails on both) undoes the change, saves the restored file as a new version, and opens the corrections it answered again, so the next
218
219
  * method run fixes them anew. Each of these says one line on the next method run or method wait.
219
220
  */
220
221
  export declare function checkBackground(client: MethodClient, file: string, fix: Pick<FixOutcome, 'background_cases' | 'undo_id' | 'fixed' | 'cause'>, options?: {
@@ -1,5 +1,6 @@
1
- import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
- import { dirname, join, resolve, sep } from 'node:path';
1
+ import { appendFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { basename, dirname, join, relative, resolve, sep } from 'node:path';
3
4
  import { randomBytes, randomUUID } from 'node:crypto';
4
5
  import { isDeepStrictEqual } from 'node:util';
5
6
  import { MethodPackageSchema, packageDigest, packagePath } from '../../contracts/src/method-package.js';
@@ -13,7 +14,7 @@ import { localRuns, saveLocalProposal, writeMethodFile } from './proposals.js';
13
14
  import { changedSteps } from './merge.js';
14
15
  import { localJudgments, runFolderIndex } from './local-judgments.js';
15
16
  import { fixFolder, readFixState, saveError, saveNotice, saveOutcome, setWorker, storedOutcome, writeFixState } from './fix-outcomes.js';
16
- import { recordChange, saveVersion, snapshot, undoLast } from './undo.js';
17
+ import { recordChange, saveVersion, snapshot, undoLast, undoRecords } from './undo.js';
17
18
  import { fixUndoneLine, ruleBackLine } from './fix-lines.js';
18
19
  const outcomeKinds = ['fixed', 'no_fix_found', 'could_not_test', 'question', 'held', 'not_reproduced', 'not_fixable_here'];
19
20
  const reasons = ['missing_file', 'can_send', 'too_large', 'no_live_step'];
@@ -607,10 +608,40 @@ export async function fixWaiting(client, file, options = {}) {
607
608
  rmSync(lock, { force: true });
608
609
  }
609
610
  }
611
+ /**
612
+ * The cases among ids that pass on the Method as it was before the change undoId: a copy of the Method's folder with
613
+ * the file and the changed files from the undo record, tested with the Method's own cases. Without the record, every
614
+ * case counts as passing before.
615
+ */
616
+ async function passedBefore(file, undoId, ids, run) {
617
+ const record = undoRecords(file).find(r => r.id === undoId);
618
+ if (!record || !ids.length)
619
+ return new Set(ids);
620
+ const folder = dirname(resolve(file)), copy = mkdtempSync(join(tmpdir(), 'method-before-'));
621
+ try {
622
+ cpSync(folder, copy, { recursive: true, filter: source => !/^(cases|\.method)(\/|$)/.test(relative(folder, source)) });
623
+ const before = join(copy, basename(file));
624
+ writeFileSync(before, record.before.text);
625
+ for (const [path, content] of Object.entries(record.before.files)) {
626
+ const full = join(copy, packagePath(path));
627
+ if (content === null)
628
+ rmSync(full, { force: true });
629
+ else {
630
+ mkdirSync(dirname(full), { recursive: true });
631
+ writeFileSync(full, Buffer.from(content, 'base64'));
632
+ }
633
+ }
634
+ const report = await run(before, {}, { ids, casesDir: join(folder, 'cases') });
635
+ return new Set(report.cases.filter(c => c.verdict === 'pass').map(c => c.id));
636
+ }
637
+ finally {
638
+ rmSync(copy, { recursive: true, force: true });
639
+ }
640
+ }
610
641
  /**
611
642
  * The later check of an applied change: the Method's other cases (improve.method's background_cases) run on the changed
612
- * file. A failing case that belongs to a retired learned rule (its from.case) brings that rule back. Any other failure
613
- * undoes the change, saves the restored file as a new version, and opens the corrections it answered again, so the next
643
+ * file. A failing case that belongs to a retired learned rule (its from.case) brings that rule back. Any other case that
644
+ * fails now and passed before the change (a correction that no fix answered yet fails on both) undoes the change, saves the restored file as a new version, and opens the corrections it answered again, so the next
614
645
  * method run fixes them anew. Each of these says one line on the next method run or method wait.
615
646
  */
616
647
  export async function checkBackground(client, file, fix, options = {}) {
@@ -635,7 +666,9 @@ export async function checkBackground(client, file, fix, options = {}) {
635
666
  ruleCases.add(r.from.case);
636
667
  }
637
668
  catch { /* no readable learned rules */ }
638
- const broken = done.failed.filter(id => !ruleCases.has(id));
669
+ const others = done.failed.filter(id => !ruleCases.has(id));
670
+ const passed = await passedBefore(file, fix.undo_id, others, run);
671
+ const broken = others.filter(id => passed.has(id));
639
672
  if (broken.length && fix.undo_id) {
640
673
  try {
641
674
  undoLast(file, fix.undo_id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@method-ai-hq/sdk",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
4
4
  "description": "Build and run reusable .method files with checked steps and saved results.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "prepack": "npm --prefix ../.. run build"
36
36
  },
37
37
  "dependencies": {
38
- "@withmethod/runtime": "https://codeload.github.com/method-ai-hq/method-spec/tar.gz/v0.16.1",
38
+ "@withmethod/runtime": "https://codeload.github.com/method-ai-hq/method-spec/tar.gz/v0.16.2",
39
39
  "fflate": "^0.8.3",
40
40
  "yaml": "^2.9.0",
41
41
  "zod": "^3.25.76"