pi-apexlang 0.1.0 → 0.2.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
@@ -90,6 +90,19 @@ code** requires an explicit target mode:
90
90
  Without GUI support, the tool always stops after checking and reports import
91
91
  as a follow-up.
92
92
 
93
+ When refreshing a full APEXlang export, run one SQLcl export with explicit
94
+ replacement semantics:
95
+
96
+ ```text
97
+ apex export -applicationid <id> -exptype APEXLANG -split -dir <absolute-parent-directory> -force
98
+ ```
99
+
100
+ `-dir` names the parent directory; SQLcl creates the application-alias folder
101
+ below it. The `-force` flag removes and recreates that export folder, so a
102
+ repeat export produces one current snapshot instead of collision copies such
103
+ as `application_1.apx` and `p00005_1.apx`. Because this replaces the complete
104
+ local export, preserve or import any local-only work before refreshing it.
105
+
93
106
  All app paths must remain inside the active Pi workspace. The adapter rejects
94
107
  traversal, app-tree symlinks, and multiply linked files on mutating vocabulary
95
108
  fixes; verifies live workspace input against `deployments/default.json`; and
@@ -20,6 +20,8 @@ const CHECK_ONLY_CHOICE = "Check APEXlang code (recommended) — stop after the
20
20
  const IMPORT_CHOICE = "Check and import APEXlang code — revalidate and import in one SQLcl session";
21
21
  const UPDATE_EXISTING_CHOICE = "Update an existing app — require one proven remote target";
22
22
  const CREATE_NEW_CHOICE = "Create a new app — require proof that the alias is absent";
23
+ const EXPORT_OVERWRITE_GUIDELINE =
24
+ "For a full APEXlang export refresh, run exactly one SQLcl `apex export` command with `-force` and `-dir` set to the absolute parent directory. Never export without `-force` into an existing destination: SQLcl can collision-suffix every artifact as `*_1.apx` instead of replacing the snapshot.";
23
25
 
24
26
  function trimOutput(value: string, outputRoot?: string): string {
25
27
  if (value.length <= MAX_TOOL_OUTPUT) return value;
@@ -110,6 +112,7 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
110
112
  promptGuidelines: [
111
113
  "Load the apexlang skill before using the apexlang tool and follow its routing and Missing Inputs rules.",
112
114
  "Use apexlang workspace_probe before app-scoped APEXlang work.",
115
+ EXPORT_OVERWRITE_GUIDELINE,
113
116
  "Use apexlang runtime_validate only after the user provides both db_connection_name and the matching APEX workspace_name; import requires the tool's separate post-check GUI choice."
114
117
  ],
115
118
  executionMode: "sequential",
@@ -157,7 +160,7 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
157
160
  ),
158
161
  list: Type.Optional(Type.Boolean({ description: "List matching compiler component types." })),
159
162
  supporting_objects: Type.Optional(
160
- Type.Boolean({ description: "Include supporting objects in runtime preflight/doctor." })
163
+ Type.Boolean({ description: "Include supporting objects in runtime preflight, validation, and import." })
161
164
  ),
162
165
  fix_vocab: Type.Optional(
163
166
  Type.Boolean({ description: "Apply local vocabulary fixes after interactive confirmation." })
@@ -250,6 +253,12 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
250
253
  };
251
254
  }
252
255
  if (choice === IMPORT_CHOICE) {
256
+ const expectedAppDigest = String(result.appDigest ?? "").trim().toLowerCase();
257
+ if (!/^[a-f0-9]{64}$/.test(expectedAppDigest)) {
258
+ throw new Error(
259
+ "APEXlang live check did not produce a valid application snapshot digest; import is blocked until it is revalidated."
260
+ );
261
+ }
253
262
  const targetChoice = await ctx.ui.select("Choose the explicitly intended import target:", [
254
263
  UPDATE_EXISTING_CHOICE,
255
264
  CREATE_NEW_CHOICE
@@ -286,7 +295,9 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
286
295
  ],
287
296
  details: { action: input.action, targetResolutionMode, provingTarget: true }
288
297
  });
289
- const proofResult = await dependencies.runCreateNewProof(input, runOptions);
298
+ const proofResult = await dependencies.runCreateNewProof(input, runOptions, {
299
+ expectedAppDigest
300
+ });
290
301
  if (!createNewTargetProved(proofResult)) {
291
302
  throw new Error(
292
303
  failureOutput(
@@ -329,7 +340,8 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
329
340
  });
330
341
  const importResult = await dependencies.runImport(input, runOptions, {
331
342
  targetResolutionMode,
332
- createNewConfirmed
343
+ createNewConfirmed,
344
+ expectedAppDigest
333
345
  });
334
346
  const importOutput = processOutput(importResult);
335
347
  if (!liveImportPassed(importResult)) {
@@ -416,6 +428,7 @@ export {
416
428
  CHECK_ONLY_CHOICE,
417
429
  IMPORT_CHOICE,
418
430
  CREATE_NEW_CHOICE,
431
+ EXPORT_OVERWRITE_GUIDELINE,
419
432
  UPDATE_EXISTING_CHOICE,
420
433
  actionWritesProject,
421
434
  confirmationMessage,
@@ -43,11 +43,21 @@ export interface ApexlangRunOptions {
43
43
  export interface ApexlangImportOptions {
44
44
  targetResolutionMode?: "update-existing" | "create-new";
45
45
  createNewConfirmed?: boolean;
46
+ expectedAppDigest?: string;
47
+ }
48
+
49
+ export interface ApexlangApprovedImportOptions extends ApexlangImportOptions {
50
+ expectedAppDigest: string;
51
+ }
52
+
53
+ export interface ApexlangCreateNewProofOptions {
54
+ expectedAppDigest: string;
46
55
  }
47
56
 
48
57
  export interface ProcessTreeOptions {
49
58
  cwd: string;
50
59
  env?: NodeJS.ProcessEnv;
60
+ input?: string;
51
61
  maxBuffer?: number;
52
62
  signal?: AbortSignal;
53
63
  timeoutMs?: number;
@@ -60,11 +70,43 @@ export interface ApexlangProcessResult {
60
70
  stderr: string;
61
71
  }
62
72
 
73
+ export interface SqlclValidationImportOptions extends ProcessTreeOptions {
74
+ validateCommand: string;
75
+ importCommand: string;
76
+ }
77
+
78
+ export interface SqlclValidationImportResult extends ApexlangProcessResult {
79
+ validationAccepted: boolean;
80
+ validationEvidence: {
81
+ accepted: boolean;
82
+ reason: string;
83
+ warningCount?: number;
84
+ validationSuccessCount?: number;
85
+ outputSha256?: string;
86
+ };
87
+ ptyBacked: true;
88
+ ptyProcessGroupReady: boolean;
89
+ sessionReady: boolean;
90
+ validationSent: boolean;
91
+ importSent: boolean;
92
+ importCompleted: boolean;
93
+ hardFailureDetected: boolean;
94
+ orderedMergedOutput: true;
95
+ validationOutput: string;
96
+ importOutput: string;
97
+ }
98
+
63
99
  export interface ApexlangRunResult extends ApexlangProcessResult {
64
100
  action: ApexlangAction;
65
101
  command: ApexlangCommand;
66
102
  outputRoot: string;
67
103
  preludeResults: ApexlangProcessResult[];
104
+ runtimeApp: {
105
+ appPath?: string;
106
+ staged: boolean;
107
+ workspaceSource?: "workspace.name" | "app.workspace.name" | "explicit_workspace_name";
108
+ };
109
+ appDigest?: string;
68
110
  }
69
111
 
70
112
  export const APEXLANG_SKILL_ROOT: string;
@@ -91,11 +133,79 @@ export function validateMaterializationPaths(options: {
91
133
  requested: string;
92
134
  suggested: string;
93
135
  }): Promise<string>;
136
+ export function prepareRuntimeApp(
137
+ input: ApexlangInput,
138
+ cwd: string,
139
+ outputRoot: string,
140
+ options?: { forceStage?: boolean }
141
+ ): Promise<{
142
+ appPath?: string;
143
+ staged: boolean;
144
+ workspaceSource?: "workspace.name" | "app.workspace.name" | "explicit_workspace_name";
145
+ }>;
146
+ export function computeApexlangAppDigest(appPath: string): Promise<string>;
147
+ export function classifyWarningOnlyRuntimePayload(
148
+ payload: Record<string, unknown>,
149
+ transcript: string,
150
+ expectedImportIntent?: "validate-only" | "validate-and-import"
151
+ ): {
152
+ accepted: boolean;
153
+ reason: string;
154
+ attemptLabel?: string;
155
+ warningCount?: number;
156
+ validationSuccessCount?: number;
157
+ attemptSha256?: string;
158
+ };
159
+ export function classifyWarningCompatibleSqlclValidation(output: string): {
160
+ accepted: boolean;
161
+ reason: string;
162
+ warningCount: number;
163
+ validationSuccessCount: number;
164
+ outputSha256?: string;
165
+ };
166
+ export function proveWarningOnlyProblemsAreDiagnostics(
167
+ payload: Record<string, any>,
168
+ result: Pick<ApexlangRunResult, "outputRoot">
169
+ ): Promise<{
170
+ accepted: boolean;
171
+ reason?: string;
172
+ problemCount?: number;
173
+ problemsPath?: string;
174
+ problemsSha256?: string;
175
+ }>;
176
+ export function validateUpdateExistingImportProof(
177
+ payload: Record<string, any>,
178
+ input: ApexlangInput,
179
+ stagedAppPath: string
180
+ ): {
181
+ canonicalId: number;
182
+ canonicalAlias: string;
183
+ sourceId: number;
184
+ sourceAlias: string;
185
+ workspaceId: string;
186
+ workspaceName: string;
187
+ };
188
+ export function buildWarningCompatibleImportCommands(options: {
189
+ appPath: string;
190
+ workspaceId: string;
191
+ canonicalId: number;
192
+ }): { validateCommand: string; importCommand: string };
193
+ export function runWarningCompatibleImport(
194
+ input: ApexlangInput,
195
+ result: ApexlangRunResult,
196
+ options: ApexlangRunOptions,
197
+ dependencies?: { sessionRunner?: typeof executeSqlclValidationThenImport }
198
+ ): Promise<ApexlangRunResult>;
94
199
  export function executeProcessTree(
95
200
  executable: string,
96
201
  args: string[],
97
202
  options: ProcessTreeOptions
98
203
  ): Promise<ApexlangProcessResult>;
204
+ export function executeSqlclValidationThenImport(
205
+ executable: string,
206
+ args: string[],
207
+ options: SqlclValidationImportOptions
208
+ ): Promise<SqlclValidationImportResult>;
99
209
  export function runApexlang(
100
210
  input: ApexlangInput,
101
211
  options: ApexlangRunOptions
@@ -103,9 +213,10 @@ export function runApexlang(
103
213
  export function runApexlangImport(
104
214
  input: ApexlangInput,
105
215
  options: ApexlangRunOptions,
106
- importOptions?: ApexlangImportOptions
216
+ importOptions: ApexlangApprovedImportOptions
107
217
  ): Promise<ApexlangRunResult>;
108
218
  export function runApexlangCreateNewProof(
109
219
  input: ApexlangInput,
110
- options: ApexlangRunOptions
220
+ options: ApexlangRunOptions,
221
+ proofOptions: ApexlangCreateNewProofOptions
111
222
  ): Promise<ApexlangRunResult>;