arc-1 0.9.2 → 0.9.4
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 +4 -4
- package/dist/adt/client.d.ts +12 -1
- package/dist/adt/client.d.ts.map +1 -1
- package/dist/adt/client.js +56 -1
- package/dist/adt/client.js.map +1 -1
- package/dist/adt/devtools.d.ts.map +1 -1
- package/dist/adt/devtools.js +191 -51
- package/dist/adt/devtools.js.map +1 -1
- package/dist/adt/diagnostics.d.ts +21 -1
- package/dist/adt/diagnostics.d.ts.map +1 -1
- package/dist/adt/diagnostics.js +72 -0
- package/dist/adt/diagnostics.js.map +1 -1
- package/dist/adt/fm-signature.d.ts +77 -0
- package/dist/adt/fm-signature.d.ts.map +1 -0
- package/dist/adt/fm-signature.js +343 -0
- package/dist/adt/fm-signature.js.map +1 -0
- package/dist/adt/http.d.ts +9 -1
- package/dist/adt/http.d.ts.map +1 -1
- package/dist/adt/http.js +8 -7
- package/dist/adt/http.js.map +1 -1
- package/dist/adt/rap-generate.d.ts +110 -0
- package/dist/adt/rap-generate.d.ts.map +1 -0
- package/dist/adt/rap-generate.js +262 -0
- package/dist/adt/rap-generate.js.map +1 -0
- package/dist/adt/rap-handlers.d.ts +14 -0
- package/dist/adt/rap-handlers.d.ts.map +1 -1
- package/dist/adt/rap-handlers.js +96 -9
- package/dist/adt/rap-handlers.js.map +1 -1
- package/dist/adt/types.d.ts +73 -1
- package/dist/adt/types.d.ts.map +1 -1
- package/dist/adt/xml-parser.d.ts.map +1 -1
- package/dist/adt/xml-parser.js +14 -0
- package/dist/adt/xml-parser.js.map +1 -1
- package/dist/authz/policy.d.ts.map +1 -1
- package/dist/authz/policy.js +9 -0
- package/dist/authz/policy.js.map +1 -1
- package/dist/context/method-surgery.d.ts +27 -0
- package/dist/context/method-surgery.d.ts.map +1 -1
- package/dist/context/method-surgery.js +104 -7
- package/dist/context/method-surgery.js.map +1 -1
- package/dist/handlers/intent.d.ts +20 -0
- package/dist/handlers/intent.d.ts.map +1 -1
- package/dist/handlers/intent.js +729 -71
- package/dist/handlers/intent.js.map +1 -1
- package/dist/handlers/schemas.d.ts +111 -3
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +163 -11
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +152 -33
- package/dist/handlers/tools.js.map +1 -1
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +1 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/server.d.ts +1 -1
- package/dist/server/server.js +1 -1
- package/dist/server/types.d.ts +2 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js.map +1 -1
- package/package.json +1 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level RAP behavior pool generator (PR-C / SAPWrite generate_behavior_implementation).
|
|
3
|
+
*
|
|
4
|
+
* One-shot equivalent of Eclipse ADT's "Generate Behavior Implementation"
|
|
5
|
+
* Cmd+1 quickfix on a behavior pool class. Composes existing capabilities:
|
|
6
|
+
*
|
|
7
|
+
* 1. parseClassMetadata.rootEntityRef — auto-discover the bound BDEF
|
|
8
|
+
* 2. extractRapHandlerRequirements — derive every required handler method
|
|
9
|
+
* 3. applyRapHandlerScaffold — auto-create lhc_<alias> skeletons,
|
|
10
|
+
* inject signatures + empty stubs
|
|
11
|
+
* 4. updateSource (per include URL) — write CCDEF + CCIMP under one lock
|
|
12
|
+
* 5. activateBatch — optional final activation
|
|
13
|
+
*
|
|
14
|
+
* This avoids the broken `/sap/bc/adt/quickfixes/proposals/.../create_class_implementation`
|
|
15
|
+
* server endpoint (HTTP 500 on a4h regardless of payload — verified live during research).
|
|
16
|
+
* Local generation is deterministic, fully unit-testable, and reuses the proven PR #257
|
|
17
|
+
* include-write path.
|
|
18
|
+
*
|
|
19
|
+
* Inputs:
|
|
20
|
+
* className — the behavior pool class (e.g. "ZBP_DM_PROJECT")
|
|
21
|
+
* options.bdefName — explicit BDEF override; default is auto-discovery from rootEntityRef
|
|
22
|
+
* options.targetAlias — restrict scaffold to one entity alias (case-insensitive)
|
|
23
|
+
* options.activate — also run SAPActivate after writing (default true)
|
|
24
|
+
* options.dryRun — preview without writing/activating (default false)
|
|
25
|
+
*
|
|
26
|
+
* Output:
|
|
27
|
+
* `RapGenerateResult` carries the discovery, validation, scaffold, and activation
|
|
28
|
+
* outcomes. Activation failures matching the "stale active CCDEF/CCIMP placeholder
|
|
29
|
+
* + new inactive content" coupling DO NOT throw — they return `activation.success=false`
|
|
30
|
+
* with a guided `hint` so the caller can surface the recovery path. Other activation
|
|
31
|
+
* failures rethrow.
|
|
32
|
+
*/
|
|
33
|
+
import type { AdtClient } from './client.js';
|
|
34
|
+
import { type RapHandlerRequirement } from './rap-handlers.js';
|
|
35
|
+
/** Options for `generateBehaviorImplementation`. */
|
|
36
|
+
export interface RapGenerateOptions {
|
|
37
|
+
/** Explicit BDEF name (overrides rootEntityRef auto-discovery). */
|
|
38
|
+
bdefName?: string;
|
|
39
|
+
/** Restrict scaffold to a single entity alias (case-insensitive). */
|
|
40
|
+
targetAlias?: string;
|
|
41
|
+
/** Also run `SAPActivate` on the class after writing (default `true`). */
|
|
42
|
+
activate?: boolean;
|
|
43
|
+
/** Preview the plan without writing or activating (default `false`). */
|
|
44
|
+
dryRun?: boolean;
|
|
45
|
+
/** Optional transport request to attribute writes to. */
|
|
46
|
+
transport?: string;
|
|
47
|
+
}
|
|
48
|
+
/** Discovery + validation diagnostics. */
|
|
49
|
+
export interface RapGenerateDiscovery {
|
|
50
|
+
className: string;
|
|
51
|
+
bdefName: string;
|
|
52
|
+
/** Where the BDEF name came from. */
|
|
53
|
+
source: 'rootEntityRef' | 'explicit';
|
|
54
|
+
/** Class metadata category (must be `behaviorPool`). */
|
|
55
|
+
classCategory: string;
|
|
56
|
+
}
|
|
57
|
+
export interface RapGenerateValidation {
|
|
58
|
+
/** MAIN source contains a `FOR BEHAVIOR OF <bdef>` clause that points at the discovered BDEF. */
|
|
59
|
+
mainHasForBehaviorOf: boolean;
|
|
60
|
+
/** BDEF source contains `managed implementation in class <className>` (or `unmanaged …`) bound to the class. */
|
|
61
|
+
bdefBindsClass: boolean;
|
|
62
|
+
/** Free-text reason when one of the cross-references doesn't match. */
|
|
63
|
+
mismatchReason?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface RapGenerateActivation {
|
|
66
|
+
success: boolean;
|
|
67
|
+
/** Human-friendly recovery hint when `success === false` for a known soft-failure mode. */
|
|
68
|
+
hint?: string;
|
|
69
|
+
/** Activation messages from SAP (errors + warnings + info). */
|
|
70
|
+
messages?: string[];
|
|
71
|
+
}
|
|
72
|
+
export interface RapGenerateResult {
|
|
73
|
+
discovery: RapGenerateDiscovery;
|
|
74
|
+
validation: RapGenerateValidation;
|
|
75
|
+
/** Whether any include source actually changed during scaffolding. */
|
|
76
|
+
scaffoldChanged: boolean;
|
|
77
|
+
/** Sections updated by the scaffold (e.g. ['definitions', 'implementations']). */
|
|
78
|
+
changedSections: Array<'main' | 'definitions' | 'implementations'>;
|
|
79
|
+
/** Counts by category for telemetry / talk demos. */
|
|
80
|
+
inserted: {
|
|
81
|
+
signatures: number;
|
|
82
|
+
stubs: number;
|
|
83
|
+
autoCreatedSkeletons: number;
|
|
84
|
+
};
|
|
85
|
+
/** Required handlers parsed out of the BDEF (post `targetAlias` filter). */
|
|
86
|
+
required: RapHandlerRequirement[];
|
|
87
|
+
/** Activation report; absent when `activate=false` or when scaffold made no changes. */
|
|
88
|
+
activation?: RapGenerateActivation;
|
|
89
|
+
/** Echoes the `dryRun` request flag for caller convenience. */
|
|
90
|
+
dryRun: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Classify a `generate_behavior_implementation` outcome as MCP success vs error.
|
|
94
|
+
*
|
|
95
|
+
* The orchestrator never throws on activation failure — it returns a structured
|
|
96
|
+
* result so the caller can see what was scaffolded. The handler then decides
|
|
97
|
+
* which MCP result code to surface. See Codex review on PR #260 (P1):
|
|
98
|
+
* - activation absent (dryRun / activate=false / no scaffold change + no activation) → success
|
|
99
|
+
* - activation.success === true → success
|
|
100
|
+
* - activation.success === false WITH hint (e.g. stale-active CCDEF coupling) → success
|
|
101
|
+
* (the source is correct; the user follows the recovery path)
|
|
102
|
+
* - activation.success === false WITHOUT hint → error (real compile failure)
|
|
103
|
+
*/
|
|
104
|
+
export declare function isRapGenerateResultSuccess(result: RapGenerateResult): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Run the high-level "Generate Behavior Implementation" flow against a
|
|
107
|
+
* behavior pool class. See module-level docs for the contract.
|
|
108
|
+
*/
|
|
109
|
+
export declare function generateBehaviorImplementation(client: AdtClient, className: string, options?: RapGenerateOptions): Promise<RapGenerateResult>;
|
|
110
|
+
//# sourceMappingURL=rap-generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rap-generate.d.ts","sourceRoot":"","sources":["../../src/adt/rap-generate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAE3B,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,MAAM,EAAE,eAAe,GAAG,UAAU,CAAC;IACrC,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,iGAAiG;IACjG,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gHAAgH;IAChH,cAAc,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,oBAAoB,CAAC;IAChC,UAAU,EAAE,qBAAqB,CAAC;IAClC,sEAAsE;IACtE,eAAe,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,eAAe,EAAE,KAAK,CAAC,MAAM,GAAG,aAAa,GAAG,iBAAiB,CAAC,CAAC;IACnE,qDAAqD;IACrD,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,4EAA4E;IAC5E,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,wFAAwF;IACxF,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,+DAA+D;IAC/D,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAI7E;AA8CD;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAiN5B"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level RAP behavior pool generator (PR-C / SAPWrite generate_behavior_implementation).
|
|
3
|
+
*
|
|
4
|
+
* One-shot equivalent of Eclipse ADT's "Generate Behavior Implementation"
|
|
5
|
+
* Cmd+1 quickfix on a behavior pool class. Composes existing capabilities:
|
|
6
|
+
*
|
|
7
|
+
* 1. parseClassMetadata.rootEntityRef — auto-discover the bound BDEF
|
|
8
|
+
* 2. extractRapHandlerRequirements — derive every required handler method
|
|
9
|
+
* 3. applyRapHandlerScaffold — auto-create lhc_<alias> skeletons,
|
|
10
|
+
* inject signatures + empty stubs
|
|
11
|
+
* 4. updateSource (per include URL) — write CCDEF + CCIMP under one lock
|
|
12
|
+
* 5. activateBatch — optional final activation
|
|
13
|
+
*
|
|
14
|
+
* This avoids the broken `/sap/bc/adt/quickfixes/proposals/.../create_class_implementation`
|
|
15
|
+
* server endpoint (HTTP 500 on a4h regardless of payload — verified live during research).
|
|
16
|
+
* Local generation is deterministic, fully unit-testable, and reuses the proven PR #257
|
|
17
|
+
* include-write path.
|
|
18
|
+
*
|
|
19
|
+
* Inputs:
|
|
20
|
+
* className — the behavior pool class (e.g. "ZBP_DM_PROJECT")
|
|
21
|
+
* options.bdefName — explicit BDEF override; default is auto-discovery from rootEntityRef
|
|
22
|
+
* options.targetAlias — restrict scaffold to one entity alias (case-insensitive)
|
|
23
|
+
* options.activate — also run SAPActivate after writing (default true)
|
|
24
|
+
* options.dryRun — preview without writing/activating (default false)
|
|
25
|
+
*
|
|
26
|
+
* Output:
|
|
27
|
+
* `RapGenerateResult` carries the discovery, validation, scaffold, and activation
|
|
28
|
+
* outcomes. Activation failures matching the "stale active CCDEF/CCIMP placeholder
|
|
29
|
+
* + new inactive content" coupling DO NOT throw — they return `activation.success=false`
|
|
30
|
+
* with a guided `hint` so the caller can surface the recovery path. Other activation
|
|
31
|
+
* failures rethrow.
|
|
32
|
+
*/
|
|
33
|
+
import { lockObject, unlockObject, updateSource } from './crud.js';
|
|
34
|
+
import { activateBatch } from './devtools.js';
|
|
35
|
+
import { AdtApiError, AdtSafetyError } from './errors.js';
|
|
36
|
+
import { applyRapHandlerScaffold, extractRapHandlerRequirements, findMissingRapHandlerImplementationStubs, findMissingRapHandlerRequirements, } from './rap-handlers.js';
|
|
37
|
+
/**
|
|
38
|
+
* Classify a `generate_behavior_implementation` outcome as MCP success vs error.
|
|
39
|
+
*
|
|
40
|
+
* The orchestrator never throws on activation failure — it returns a structured
|
|
41
|
+
* result so the caller can see what was scaffolded. The handler then decides
|
|
42
|
+
* which MCP result code to surface. See Codex review on PR #260 (P1):
|
|
43
|
+
* - activation absent (dryRun / activate=false / no scaffold change + no activation) → success
|
|
44
|
+
* - activation.success === true → success
|
|
45
|
+
* - activation.success === false WITH hint (e.g. stale-active CCDEF coupling) → success
|
|
46
|
+
* (the source is correct; the user follows the recovery path)
|
|
47
|
+
* - activation.success === false WITHOUT hint → error (real compile failure)
|
|
48
|
+
*/
|
|
49
|
+
export function isRapGenerateResultSuccess(result) {
|
|
50
|
+
if (!result.activation)
|
|
51
|
+
return true;
|
|
52
|
+
if (result.activation.success)
|
|
53
|
+
return true;
|
|
54
|
+
return Boolean(result.activation.hint);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Recovery hint for the well-known "stale active CCDEF/CCIMP placeholder + new
|
|
58
|
+
* inactive handlers" activation rejection. Surfaced verbatim when SAP returns
|
|
59
|
+
* `Local classes of "CL_ABAP_BEHAVIOR_HANDLER" can only be derived in the
|
|
60
|
+
* "Local Definitions/Implementations" of a global BEHAVIOR class`. The hint is
|
|
61
|
+
* intentionally specific — generic "try Eclipse" advice would not unblock the
|
|
62
|
+
* SEGW→RAP migration skill.
|
|
63
|
+
*/
|
|
64
|
+
const STALE_ACTIVE_HINT = 'Activation rejected with the well-known "Local classes of CL_ABAP_BEHAVIOR_HANDLER…" error. ' +
|
|
65
|
+
'This typically means the active CCDEF/CCIMP for this class are still SAP placeholder comments ' +
|
|
66
|
+
'while the inactive copies now contain real handlers, and RAP refuses the inactive→active transition. ' +
|
|
67
|
+
'Recovery options: (a) activate the class once via Eclipse "Generate Behavior Implementation" wizard ' +
|
|
68
|
+
'(it bypasses this coupling), or (b) delete and recreate the class via SAPWrite(action="delete", type="CLAS") ' +
|
|
69
|
+
'followed by SAPWrite(action="create", type="CLAS", …) and rerun generate_behavior_implementation against ' +
|
|
70
|
+
'the freshly created class. The just-written CCDEF/CCIMP source is correct and reusable in both recovery paths.';
|
|
71
|
+
/** Build the include URL for CCDEF/CCIMP/macros/testclasses (mirror of intent.ts:classIncludeUrl). */
|
|
72
|
+
function classIncludeUrlFor(name, include) {
|
|
73
|
+
return `/sap/bc/adt/oo/classes/${encodeURIComponent(name)}/includes/${include}`;
|
|
74
|
+
}
|
|
75
|
+
function classObjectUrl(name) {
|
|
76
|
+
return `/sap/bc/adt/oo/classes/${encodeURIComponent(name)}`;
|
|
77
|
+
}
|
|
78
|
+
function classMainSourceUrl(name) {
|
|
79
|
+
return `${classObjectUrl(name)}/source/main`;
|
|
80
|
+
}
|
|
81
|
+
const FOR_BEHAVIOR_OF_RE = /\bfor\s+behavior\s+of\s+(\w+)/i;
|
|
82
|
+
const MANAGED_IMPL_RE = /\b(?:managed|unmanaged|projection)\s+implementation\s+in\s+class\s+(\w+)\s+unique\b/i;
|
|
83
|
+
/**
|
|
84
|
+
* "Local classes of CL_ABAP_BEHAVIOR_HANDLER…" is the activation rejection that
|
|
85
|
+
* happens when the active CCDEF/CCIMP placeholders are out of sync with the new
|
|
86
|
+
* inactive content. We recognize it by the stable English fragment SAP emits in
|
|
87
|
+
* the activation message body — the message text is identical across 7.50 and
|
|
88
|
+
* 7.58 (verified live during PR-C research, 2026-05-10).
|
|
89
|
+
*/
|
|
90
|
+
const STALE_ACTIVE_RE = /local classes of\s+["']?cl_abap_behavior_handler["']?\s+can\s+only\s+be\s+derived/i;
|
|
91
|
+
/**
|
|
92
|
+
* Run the high-level "Generate Behavior Implementation" flow against a
|
|
93
|
+
* behavior pool class. See module-level docs for the contract.
|
|
94
|
+
*/
|
|
95
|
+
export async function generateBehaviorImplementation(client, className, options = {}) {
|
|
96
|
+
const dryRun = options.dryRun === true;
|
|
97
|
+
const activateRequested = options.activate !== false; // default true
|
|
98
|
+
const targetAlias = (options.targetAlias ?? '').trim().toLowerCase();
|
|
99
|
+
const transport = options.transport;
|
|
100
|
+
if (!className?.trim()) {
|
|
101
|
+
throw new AdtSafetyError('generate_behavior_implementation: className is required.');
|
|
102
|
+
}
|
|
103
|
+
const cleanClassName = className.trim();
|
|
104
|
+
// ── Phase 1: discovery ────────────────────────────────────────────────
|
|
105
|
+
const metadata = await client.getClassMetadata(cleanClassName);
|
|
106
|
+
if (metadata.category !== 'behaviorPool') {
|
|
107
|
+
throw new AdtSafetyError(`generate_behavior_implementation: class ${cleanClassName} is not a RAP behavior pool ` +
|
|
108
|
+
`(class:category=${metadata.category || '<empty>'}). The action only operates on classes ` +
|
|
109
|
+
`marked behaviorPool. Create the class via SAPWrite(action="create", type="CLAS") with a ` +
|
|
110
|
+
`'CLASS … FOR BEHAVIOR OF <bdef>' DEFINITION header and ensure the BDEF is active first.`);
|
|
111
|
+
}
|
|
112
|
+
const explicitBdef = options.bdefName?.trim();
|
|
113
|
+
let bdefName = explicitBdef ?? metadata.rootEntityRef?.name ?? '';
|
|
114
|
+
const discoverySource = explicitBdef ? 'explicit' : 'rootEntityRef';
|
|
115
|
+
if (!bdefName) {
|
|
116
|
+
throw new AdtSafetyError(`generate_behavior_implementation: cannot auto-discover BDEF for ${cleanClassName} — ` +
|
|
117
|
+
`class metadata has no rootEntityRef. Pass an explicit "bdefName" parameter to override.`);
|
|
118
|
+
}
|
|
119
|
+
bdefName = bdefName.toUpperCase();
|
|
120
|
+
// ── Phase 2: read sources + cross-validate ────────────────────────────
|
|
121
|
+
const structured = await client.getClassStructured(cleanClassName);
|
|
122
|
+
const mainSource = structured.main ?? '';
|
|
123
|
+
const definitionsSource = structured.definitions ?? '';
|
|
124
|
+
const implementationsSource = structured.implementations ?? '';
|
|
125
|
+
const bdefRead = await client.getBdef(bdefName);
|
|
126
|
+
const bdefSource = bdefRead.source;
|
|
127
|
+
const mainBdefMatch = FOR_BEHAVIOR_OF_RE.exec(mainSource);
|
|
128
|
+
const bdefClassMatch = MANAGED_IMPL_RE.exec(bdefSource);
|
|
129
|
+
const mainBdefRef = mainBdefMatch?.[1]?.toUpperCase();
|
|
130
|
+
const bdefClassRef = bdefClassMatch?.[1]?.toUpperCase();
|
|
131
|
+
const validation = {
|
|
132
|
+
mainHasForBehaviorOf: Boolean(mainBdefRef),
|
|
133
|
+
bdefBindsClass: Boolean(bdefClassRef),
|
|
134
|
+
};
|
|
135
|
+
const mismatches = [];
|
|
136
|
+
if (!mainBdefRef) {
|
|
137
|
+
mismatches.push(`MAIN source for ${cleanClassName} does not contain "FOR BEHAVIOR OF <bdef>"`);
|
|
138
|
+
}
|
|
139
|
+
else if (mainBdefRef !== bdefName) {
|
|
140
|
+
mismatches.push(`MAIN binds BDEF ${mainBdefRef} but discovery resolved to ${bdefName}`);
|
|
141
|
+
}
|
|
142
|
+
if (!bdefClassRef) {
|
|
143
|
+
mismatches.push(`BDEF ${bdefName} does not contain "managed implementation in class <class> unique"`);
|
|
144
|
+
}
|
|
145
|
+
else if (bdefClassRef !== cleanClassName.toUpperCase()) {
|
|
146
|
+
mismatches.push(`BDEF ${bdefName} binds class ${bdefClassRef} but we are generating for ${cleanClassName}`);
|
|
147
|
+
}
|
|
148
|
+
if (mismatches.length > 0) {
|
|
149
|
+
validation.mismatchReason = mismatches.join('; ');
|
|
150
|
+
}
|
|
151
|
+
if (validation.mismatchReason && !dryRun) {
|
|
152
|
+
throw new AdtSafetyError(`generate_behavior_implementation: cross-reference validation failed (${validation.mismatchReason}). ` +
|
|
153
|
+
`Refusing to mutate. Re-run with dryRun=true to inspect the report and fix the source files first.`);
|
|
154
|
+
}
|
|
155
|
+
// ── Phase 3: scaffold plan ────────────────────────────────────────────
|
|
156
|
+
let requirements = extractRapHandlerRequirements(bdefSource);
|
|
157
|
+
if (targetAlias) {
|
|
158
|
+
requirements = requirements.filter((req) => req.entityAlias.toLowerCase() === targetAlias);
|
|
159
|
+
}
|
|
160
|
+
const combinedSource = [mainSource, definitionsSource, implementationsSource].filter(Boolean).join('\n\n');
|
|
161
|
+
const missingSignatures = findMissingRapHandlerRequirements(requirements, combinedSource);
|
|
162
|
+
const missingStubs = findMissingRapHandlerImplementationStubs(requirements, combinedSource);
|
|
163
|
+
const scaffoldPlan = applyRapHandlerScaffold({
|
|
164
|
+
main: mainSource,
|
|
165
|
+
definitions: definitionsSource || undefined,
|
|
166
|
+
implementations: implementationsSource || undefined,
|
|
167
|
+
}, missingSignatures, missingStubs);
|
|
168
|
+
const result = {
|
|
169
|
+
discovery: {
|
|
170
|
+
className: cleanClassName,
|
|
171
|
+
bdefName,
|
|
172
|
+
source: discoverySource,
|
|
173
|
+
classCategory: metadata.category,
|
|
174
|
+
},
|
|
175
|
+
validation,
|
|
176
|
+
scaffoldChanged: scaffoldPlan.changedSections.length > 0,
|
|
177
|
+
changedSections: scaffoldPlan.changedSections.filter((section) => section === 'main' || section === 'definitions' || section === 'implementations'),
|
|
178
|
+
inserted: {
|
|
179
|
+
signatures: scaffoldPlan.insertedSignatureCount,
|
|
180
|
+
stubs: scaffoldPlan.insertedImplementationStubCount,
|
|
181
|
+
autoCreatedSkeletons: (scaffoldPlan.skeletons?.createdDefinitions.length ?? 0) +
|
|
182
|
+
(scaffoldPlan.skeletons?.createdImplementations.length ?? 0),
|
|
183
|
+
},
|
|
184
|
+
required: requirements,
|
|
185
|
+
dryRun,
|
|
186
|
+
};
|
|
187
|
+
// Dry-run short-circuits before any side effects.
|
|
188
|
+
if (dryRun) {
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
const objectUrl = classObjectUrl(cleanClassName);
|
|
192
|
+
// ── Phase 4: write (only when scaffold has changes) ───────────────────
|
|
193
|
+
// When scaffoldChanged=false, all handlers are already in place — skip the
|
|
194
|
+
// lock+write cycle entirely. Activation still runs below if requested, because
|
|
195
|
+
// a populated-but-inactive class is a realistic rerun/recovery state after
|
|
196
|
+
// earlier manual include writes (Codex review note on PR #260).
|
|
197
|
+
if (result.scaffoldChanged) {
|
|
198
|
+
await client.http.withStatefulSession(async (session) => {
|
|
199
|
+
const lock = await lockObject(session, client.safety, objectUrl, 'MODIFY');
|
|
200
|
+
const effectiveTransport = transport ?? (lock.corrNr || undefined);
|
|
201
|
+
try {
|
|
202
|
+
if (scaffoldPlan.changed.main && scaffoldPlan.sections.main !== mainSource) {
|
|
203
|
+
await updateSource(session, client.safety, classMainSourceUrl(cleanClassName), scaffoldPlan.sections.main, lock.lockHandle, effectiveTransport);
|
|
204
|
+
}
|
|
205
|
+
if (scaffoldPlan.changed.definitions && scaffoldPlan.sections.definitions) {
|
|
206
|
+
await updateSource(session, client.safety, classIncludeUrlFor(cleanClassName, 'definitions'), scaffoldPlan.sections.definitions, lock.lockHandle, effectiveTransport);
|
|
207
|
+
}
|
|
208
|
+
if (scaffoldPlan.changed.implementations && scaffoldPlan.sections.implementations) {
|
|
209
|
+
await updateSource(session, client.safety, classIncludeUrlFor(cleanClassName, 'implementations'), scaffoldPlan.sections.implementations, lock.lockHandle, effectiveTransport);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
try {
|
|
214
|
+
await unlockObject(session, objectUrl, lock.lockHandle);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// best-effort-cleanup: surface the original error, not an unlock failure
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// ── Phase 5: optional activation ──────────────────────────────────────
|
|
223
|
+
if (activateRequested) {
|
|
224
|
+
try {
|
|
225
|
+
const activationOutcome = await activateBatch(client.http, client.safety, [
|
|
226
|
+
{ url: objectUrl, name: cleanClassName },
|
|
227
|
+
]);
|
|
228
|
+
const detailMessages = (activationOutcome.details ?? []).map((d) => d.text).filter(Boolean);
|
|
229
|
+
const allMessages = [...(activationOutcome.messages ?? []), ...detailMessages];
|
|
230
|
+
if (activationOutcome.success) {
|
|
231
|
+
result.activation = { success: true, messages: allMessages };
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
const matchedStaleActive = allMessages.some((msg) => STALE_ACTIVE_RE.test(msg));
|
|
235
|
+
result.activation = {
|
|
236
|
+
success: false,
|
|
237
|
+
messages: allMessages,
|
|
238
|
+
hint: matchedStaleActive ? STALE_ACTIVE_HINT : undefined,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
// The activateBatch path normally returns a result rather than throwing,
|
|
244
|
+
// but RAP-not-available / network errors / safety errors propagate. The
|
|
245
|
+
// stale-active soft-failure is detected via message inspection above.
|
|
246
|
+
// For unrecognised errors we attach the source-of-truth error message but
|
|
247
|
+
// keep the result structure so callers can still see the scaffold report.
|
|
248
|
+
if (err instanceof AdtApiError && STALE_ACTIVE_RE.test(err.message)) {
|
|
249
|
+
result.activation = {
|
|
250
|
+
success: false,
|
|
251
|
+
messages: [err.message],
|
|
252
|
+
hint: STALE_ACTIVE_HINT,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=rap-generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rap-generate.js","sourceRoot":"","sources":["../../src/adt/rap-generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -60,6 +60,12 @@ export interface RapHandlerSectionApplyResults {
|
|
|
60
60
|
}
|
|
61
61
|
export interface RapHandlerScaffoldPlan {
|
|
62
62
|
sections: RapHandlerSourceSections;
|
|
63
|
+
skeletons: {
|
|
64
|
+
createdDefinitions: string[];
|
|
65
|
+
createdImplementations: string[];
|
|
66
|
+
changed: Record<RapHandlerSectionName, boolean>;
|
|
67
|
+
changedSections: RapHandlerSectionName[];
|
|
68
|
+
};
|
|
63
69
|
signatures: RapHandlerSectionApplyResults;
|
|
64
70
|
implementationStubs: RapHandlerSectionApplyResults;
|
|
65
71
|
unresolved: RapHandlerRequirement[];
|
|
@@ -68,6 +74,13 @@ export interface RapHandlerScaffoldPlan {
|
|
|
68
74
|
insertedSignatureCount: number;
|
|
69
75
|
insertedImplementationStubCount: number;
|
|
70
76
|
}
|
|
77
|
+
export interface RapHandlerSkeletonResult {
|
|
78
|
+
sections: RapHandlerSourceSections;
|
|
79
|
+
createdDefinitions: string[];
|
|
80
|
+
createdImplementations: string[];
|
|
81
|
+
changed: Record<RapHandlerSectionName, boolean>;
|
|
82
|
+
changedSections: RapHandlerSectionName[];
|
|
83
|
+
}
|
|
71
84
|
export declare function rapHandlerRequirementKey(requirement: RapHandlerRequirement): string;
|
|
72
85
|
/**
|
|
73
86
|
* Extract RAP behavior-pool handler method requirements from interface BDEF source.
|
|
@@ -145,6 +158,7 @@ export declare function applyRapHandlerImplementationStubs(classSource: string,
|
|
|
145
158
|
createImplementationBlocks?: boolean;
|
|
146
159
|
definitionSource?: string;
|
|
147
160
|
}): RapHandlerApplyResult;
|
|
161
|
+
export declare function ensureRapHandlerSkeletons(sections: RapHandlerSourceSections, requirements: RapHandlerRequirement[]): RapHandlerSkeletonResult;
|
|
148
162
|
/**
|
|
149
163
|
* Build the complete auto-apply plan for a behavior pool without doing I/O.
|
|
150
164
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rap-handlers.d.ts","sourceRoot":"","sources":["../../src/adt/rap-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,eAAe,GACf,YAAY,GACZ,wBAAwB,GACxB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,cAAc,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,qBAAqB,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE/E,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,qBAAqB,CAAC;IAC5B,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,wBAAwB,CAAC;IACnC,UAAU,EAAE,6BAA6B,CAAC;IAC1C,mBAAmB,EAAE,6BAA6B,CAAC;IACnD,UAAU,EAAE,qBAAqB,EAAE,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAChD,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,+BAA+B,EAAE,MAAM,CAAC;CACzC;
|
|
1
|
+
{"version":3,"file":"rap-handlers.d.ts","sourceRoot":"","sources":["../../src/adt/rap-handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/adt/rap-handlers.js
CHANGED
|
@@ -718,6 +718,82 @@ function countInserted(results) {
|
|
|
718
718
|
function changedSectionsFrom(changed) {
|
|
719
719
|
return Object.keys(changed).filter((section) => changed[section]);
|
|
720
720
|
}
|
|
721
|
+
function uniqueRequirementsByTargetClass(requirements) {
|
|
722
|
+
const seen = new Set();
|
|
723
|
+
const out = [];
|
|
724
|
+
for (const requirement of requirements) {
|
|
725
|
+
const key = requirement.targetHandlerClass.toLowerCase();
|
|
726
|
+
if (seen.has(key))
|
|
727
|
+
continue;
|
|
728
|
+
seen.add(key);
|
|
729
|
+
out.push(requirement);
|
|
730
|
+
}
|
|
731
|
+
return out;
|
|
732
|
+
}
|
|
733
|
+
function hasClassDefinition(sections, targetHandlerClass) {
|
|
734
|
+
const target = targetHandlerClass.toLowerCase();
|
|
735
|
+
return [sections.main, sections.definitions, sections.implementations]
|
|
736
|
+
.filter(Boolean)
|
|
737
|
+
.some((source) => parseClassDefinitionRanges(source ?? '').some((range) => range.name.toLowerCase() === target));
|
|
738
|
+
}
|
|
739
|
+
function hasClassImplementation(sections, targetHandlerClass) {
|
|
740
|
+
const target = targetHandlerClass.toLowerCase();
|
|
741
|
+
return [sections.main, sections.definitions, sections.implementations]
|
|
742
|
+
.filter(Boolean)
|
|
743
|
+
.some((source) => parseClassImplementationRanges(source ?? '').some((range) => range.name.toLowerCase() === target));
|
|
744
|
+
}
|
|
745
|
+
function appendBlocksToSection(source, blocks) {
|
|
746
|
+
if (blocks.length === 0)
|
|
747
|
+
return source;
|
|
748
|
+
const blockText = blocks.join('\n\n');
|
|
749
|
+
if (!source || source.trim().length === 0)
|
|
750
|
+
return `${blockText}\n`;
|
|
751
|
+
const separator = source.endsWith('\n') ? (source.endsWith('\n\n') ? '' : '\n') : '\n\n';
|
|
752
|
+
return `${source}${separator}${blockText}\n`;
|
|
753
|
+
}
|
|
754
|
+
function handlerDefinitionSkeleton(targetHandlerClass) {
|
|
755
|
+
return `CLASS ${targetHandlerClass} DEFINITION INHERITING FROM cl_abap_behavior_handler.
|
|
756
|
+
PRIVATE SECTION.
|
|
757
|
+
ENDCLASS.`;
|
|
758
|
+
}
|
|
759
|
+
function handlerImplementationSkeleton(targetHandlerClass) {
|
|
760
|
+
return `CLASS ${targetHandlerClass} IMPLEMENTATION.
|
|
761
|
+
ENDCLASS.`;
|
|
762
|
+
}
|
|
763
|
+
export function ensureRapHandlerSkeletons(sections, requirements) {
|
|
764
|
+
const targetRequirements = uniqueRequirementsByTargetClass(requirements);
|
|
765
|
+
const definitionBlocks = [];
|
|
766
|
+
const implementationBlocks = [];
|
|
767
|
+
const createdDefinitions = [];
|
|
768
|
+
const createdImplementations = [];
|
|
769
|
+
for (const requirement of targetRequirements) {
|
|
770
|
+
const targetHandlerClass = requirement.targetHandlerClass;
|
|
771
|
+
if (!hasClassDefinition(sections, targetHandlerClass)) {
|
|
772
|
+
definitionBlocks.push(handlerDefinitionSkeleton(targetHandlerClass));
|
|
773
|
+
createdDefinitions.push(targetHandlerClass);
|
|
774
|
+
}
|
|
775
|
+
if (!hasClassImplementation(sections, targetHandlerClass)) {
|
|
776
|
+
implementationBlocks.push(handlerImplementationSkeleton(targetHandlerClass));
|
|
777
|
+
createdImplementations.push(targetHandlerClass);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
const changed = {
|
|
781
|
+
main: false,
|
|
782
|
+
definitions: createdDefinitions.length > 0,
|
|
783
|
+
implementations: createdImplementations.length > 0,
|
|
784
|
+
};
|
|
785
|
+
return {
|
|
786
|
+
sections: {
|
|
787
|
+
main: sections.main,
|
|
788
|
+
definitions: appendBlocksToSection(sections.definitions, definitionBlocks),
|
|
789
|
+
implementations: appendBlocksToSection(sections.implementations, implementationBlocks),
|
|
790
|
+
},
|
|
791
|
+
createdDefinitions,
|
|
792
|
+
createdImplementations,
|
|
793
|
+
changed,
|
|
794
|
+
changedSections: changedSectionsFrom(changed),
|
|
795
|
+
};
|
|
796
|
+
}
|
|
721
797
|
/**
|
|
722
798
|
* Build the source used to resolve semantic method names while creating stubs.
|
|
723
799
|
*
|
|
@@ -783,30 +859,35 @@ function applySignaturesAcrossSections(sections, missingSignatures) {
|
|
|
783
859
|
* names come from declarations, not necessarily from BDEF action names".
|
|
784
860
|
*/
|
|
785
861
|
export function applyRapHandlerScaffold(sections, missingSignatures, missingImplementationStubs) {
|
|
786
|
-
const
|
|
862
|
+
const skeletonPlan = ensureRapHandlerSkeletons(sections, [...missingSignatures, ...missingImplementationStubs]);
|
|
863
|
+
const signaturePlan = applySignaturesAcrossSections(skeletonPlan.sections, missingSignatures);
|
|
787
864
|
// A METHOD stub is only useful after its declaration exists. If the target
|
|
788
865
|
// `lhc_*` class was not found anywhere, suppress the stub for that unresolved
|
|
789
866
|
// declaration rather than creating an implementation block with no matching
|
|
790
867
|
// RAP handler signature.
|
|
791
868
|
const unresolvedDeclarationKeys = new Set(signaturePlan.unresolved.map(rapHandlerRequirementKey));
|
|
792
869
|
const stubRequirements = missingImplementationStubs.filter((req) => !unresolvedDeclarationKeys.has(rapHandlerRequirementKey(req)));
|
|
793
|
-
const definitionLookupSource = buildDefinitionLookupSource(sections, signaturePlan);
|
|
870
|
+
const definitionLookupSource = buildDefinitionLookupSource(skeletonPlan.sections, signaturePlan);
|
|
794
871
|
const stubMain = applyRapHandlerImplementationStubs(signaturePlan.updatedSections.main, stubRequirements, {
|
|
795
872
|
createImplementationBlocks: true,
|
|
796
873
|
definitionSource: definitionLookupSource,
|
|
797
874
|
});
|
|
798
|
-
const stubDefinitions = sections.definitions
|
|
799
|
-
? applyRapHandlerImplementationStubs(signaturePlan.updatedSections.definitions ?? sections.definitions, stubRequirements, {
|
|
875
|
+
const stubDefinitions = skeletonPlan.sections.definitions
|
|
876
|
+
? applyRapHandlerImplementationStubs(signaturePlan.updatedSections.definitions ?? skeletonPlan.sections.definitions, stubRequirements, {
|
|
800
877
|
definitionSource: definitionLookupSource,
|
|
801
878
|
})
|
|
802
879
|
: undefined;
|
|
803
|
-
const stubImplementations = sections.implementations
|
|
804
|
-
? applyRapHandlerImplementationStubs(signaturePlan.updatedSections.implementations ?? sections.implementations, stubRequirements, { createImplementationBlocks: true, definitionSource: definitionLookupSource })
|
|
880
|
+
const stubImplementations = skeletonPlan.sections.implementations
|
|
881
|
+
? applyRapHandlerImplementationStubs(signaturePlan.updatedSections.implementations ?? skeletonPlan.sections.implementations, stubRequirements, { createImplementationBlocks: true, definitionSource: definitionLookupSource })
|
|
805
882
|
: undefined;
|
|
806
883
|
const changed = {
|
|
807
|
-
main: signaturePlan.signatures.main.changed || stubMain.changed,
|
|
808
|
-
definitions:
|
|
809
|
-
|
|
884
|
+
main: skeletonPlan.changed.main || signaturePlan.signatures.main.changed || stubMain.changed,
|
|
885
|
+
definitions: skeletonPlan.changed.definitions ||
|
|
886
|
+
(signaturePlan.signatures.definitions?.changed ?? false) ||
|
|
887
|
+
(stubDefinitions?.changed ?? false),
|
|
888
|
+
implementations: skeletonPlan.changed.implementations ||
|
|
889
|
+
(signaturePlan.signatures.implementations?.changed ?? false) ||
|
|
890
|
+
(stubImplementations?.changed ?? false),
|
|
810
891
|
};
|
|
811
892
|
const changedSections = changedSectionsFrom(changed);
|
|
812
893
|
return {
|
|
@@ -815,6 +896,12 @@ export function applyRapHandlerScaffold(sections, missingSignatures, missingImpl
|
|
|
815
896
|
definitions: stubDefinitions?.updatedSource ?? signaturePlan.updatedSections.definitions,
|
|
816
897
|
implementations: stubImplementations?.updatedSource ?? signaturePlan.updatedSections.implementations,
|
|
817
898
|
},
|
|
899
|
+
skeletons: {
|
|
900
|
+
createdDefinitions: skeletonPlan.createdDefinitions,
|
|
901
|
+
createdImplementations: skeletonPlan.createdImplementations,
|
|
902
|
+
changed: skeletonPlan.changed,
|
|
903
|
+
changedSections: skeletonPlan.changedSections,
|
|
904
|
+
},
|
|
818
905
|
signatures: signaturePlan.signatures,
|
|
819
906
|
implementationStubs: {
|
|
820
907
|
main: stubMain,
|