@cspeach/cli 1.1.36 → 1.1.38

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.
@@ -28,6 +28,7 @@ import { effectiveRisk } from '../approvals/risk-floor.js';
28
28
  import { verifySyntax, verifyActive } from '../tools/verify.js';
29
29
  import { renderDiff } from '../repl/diff-display.js';
30
30
  import { parseIncludeSnapshotType } from '../tools/include-snapshot.js';
31
+ import { hasManualLocks } from '../sap/session-end.js';
31
32
  /** Compact single-line failure text for receipts / error envelopes. */
32
33
  function shortError(err) {
33
34
  const msg = err instanceof Error ? err.message : String(err);
@@ -148,7 +149,8 @@ export async function restoreSnapshot(c, deps) {
148
149
  if (currentSource === null) {
149
150
  let created;
150
151
  try {
151
- created = await deps.adt.createObject(c.objType, c.object, c.package ?? '', 'Restored via CSPeach rewind', deps.transport);
152
+ // Review fix round 1, I-1: keep the stateful session while a sap_lock is held.
153
+ created = await deps.adt.createObject(c.objType, c.object, c.package ?? '', 'Restored via CSPeach rewind', deps.transport, { keepSession: hasManualLocks() });
152
154
  }
153
155
  catch (err) {
154
156
  record('② written ✗');
@@ -26,6 +26,11 @@ export function noteManualLock() {
26
26
  export function noteManualUnlock() {
27
27
  manualLocks = Math.max(0, manualLocks - 1);
28
28
  }
29
+ /** True while a `sap_lock` handle is held (review fix round 1, I-1): sap-client's
30
+ * createObject must then keep the stateful session (extras.keepSession). */
31
+ export function hasManualLocks() {
32
+ return manualLocks > 0;
33
+ }
29
34
  export function __resetManualLocksForTests() {
30
35
  manualLocks = 0;
31
36
  }
@@ -393,7 +393,8 @@ registerTool({
393
393
  },
394
394
  handler: async (args, ctx) => {
395
395
  // atcRun(type, name, variant?) — type first
396
- const result = await ctx.adt.atcRun(args.type, args.name, args.variant ?? 'DEFAULT');
396
+ // Review fix round 1, M-3: Esc / Ctrl+C stops a long ATC run.
397
+ const result = await ctx.adt.atcRun(args.type, args.name, args.variant ?? 'DEFAULT', ctx.signal ? { signal: ctx.signal } : {});
397
398
  return { content: JSON.stringify(result, null, 2) };
398
399
  },
399
400
  });
@@ -49,7 +49,7 @@ import { noteWriteTransport, setCurrentTransport } from '../repl/current-transpo
49
49
  import { markTransportCreatedThisSession } from './transport.js';
50
50
  import { presentSafetyConfirmation } from '../repl/safety-confirm.js';
51
51
  import { isSafetyConfirmEnabled } from '../repl/safety-mode-state.js';
52
- import { noteManualLock, noteManualUnlock } from '../sap/session-end.js';
52
+ import { hasManualLocks, noteManualLock, noteManualUnlock } from '../sap/session-end.js';
53
53
  // ── Transcript visibility helpers (D16-display + tour slide-7, 2026-06-12) ──
54
54
  //
55
55
  // Rule 7 auto-snapshots always fired but the transcript never said so
@@ -825,6 +825,9 @@ registerTool({
825
825
  bindingType: args.bindingType,
826
826
  bindingVersion: args.bindingVersion,
827
827
  ...devcExtras,
828
+ // Review fix round 1, I-1: a sap_lock handle lives in the stateful
829
+ // session; sap-client ends that session before a create unless told.
830
+ keepSession: hasManualLocks(),
828
831
  });
829
832
  await auditLog('createObject', args.type, args.name, 'success', Date.now() - startedAt);
830
833
  }
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { recordSyntaxCheck } from './syntax-state.js';
14
14
  import { toObjectUrl, xmlParser } from '@cspeach/sap-client';
15
+ import * as sapClient from '@cspeach/sap-client';
15
16
  /** Line for display: the parsed line, else the `#start=L,C` fragment of the
16
17
  * checkruns uri (sap-client <= 0.1.14 left line at 0 for checkruns). */
17
18
  function lineOf(m) {
@@ -86,12 +87,40 @@ export function normaliseSyntaxResult(res) {
86
87
  * check once more with version="active" and require a processed report.
87
88
  * Anything else — an inactive version exists, the list is unreadable, the
88
89
  * retry is not processed — rethrows the original error (fail closed).
90
+ *
91
+ * TABL is NOT retried here (live-check finding 3, 2026-10-14): sap-client
92
+ * checks tables itself with an explicit chkrun:version ("inactive", then one
93
+ * "active" retry on notProcessed), so its "did not run" is already final.
94
+ * STRU is not retried either (FINDINGS item 20, proved live 2026-10-15), nor
95
+ * BDEF, DDLX, SRVD (fix/active-only-checks, proved live 2026-10-15).
96
+ *
97
+ * The list is sap-client's own export (VERSIONED_CHECK_TYPES), so the two
98
+ * cannot drift. An older sap-client without the export checks only TABL
99
+ * itself (0.1.22), so the fallback is TABL: the CLI then keeps retrying every
100
+ * other type, as before. Still retried here today: DTEL, SRVB, DOMA.
89
101
  */
102
+ export function versionedTypesFrom(mod) {
103
+ let list;
104
+ try {
105
+ list = mod['VERSIONED_CHECK_TYPES'];
106
+ }
107
+ catch {
108
+ list = undefined;
109
+ } // a test mock without the export throws
110
+ if (!Array.isArray(list) || !list.every((t) => typeof t === 'string'))
111
+ return new Set(['TABL']);
112
+ return new Set(list.map((t) => t.toUpperCase()));
113
+ }
114
+ export function sapClientVersionedTypes() {
115
+ return versionedTypesFrom(sapClient);
116
+ }
90
117
  export async function checkSyntax(adt, type, name) {
91
118
  try {
92
119
  return await adt.syntaxCheck(type, name);
93
120
  }
94
121
  catch (err) {
122
+ if (sapClientVersionedTypes().has(type.toUpperCase()))
123
+ throw err;
95
124
  if (!/did not run \(status notProcessed\)/i.test(String(err?.message ?? err)))
96
125
  throw err;
97
126
  const retried = await checkActiveVersion(adt, type, name).catch(() => undefined);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cspeach/cli",
3
- "version": "1.1.36",
3
+ "version": "1.1.38",
4
4
  "description": "CSPeach — AI-assisted ABAP development CLI. Direct SAP access, signed skills, safety gates.",
5
5
  "keywords": [
6
6
  "abap",
@@ -54,7 +54,7 @@
54
54
  "@anthropic-ai/sdk": "^0.90.0",
55
55
  "@azure/msal-node": "6.0.1",
56
56
  "@cspeach/register-core": "0.4.0",
57
- "@cspeach/sap-client": "0.1.21",
57
+ "@cspeach/sap-client": "0.1.23",
58
58
  "@iarna/toml": "^2.2.5",
59
59
  "@inkjs/ui": "^2.0.0",
60
60
  "@inquirer/prompts": "^7.0.0",