@akanjs/cli 2.3.9-rc.4 → 2.3.9-rc.5
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/incrementalBuilder.proc.js +736 -313
- package/index.js +937 -378
- package/package.json +2 -2
- package/templates/module/__model__.dictionary.ts +10 -4
|
@@ -3396,28 +3396,28 @@ class SysExecutor extends Executor {
|
|
|
3396
3396
|
return scalarModules;
|
|
3397
3397
|
}
|
|
3398
3398
|
async getViewComponents() {
|
|
3399
|
-
const viewComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.View.tsx`).exists());
|
|
3399
|
+
const viewComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${capitalize(name)}.View.tsx`).exists());
|
|
3400
3400
|
return viewComponents;
|
|
3401
3401
|
}
|
|
3402
3402
|
async getUnitComponents() {
|
|
3403
|
-
const unitComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`).exists());
|
|
3403
|
+
const unitComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${capitalize(name)}.Unit.tsx`).exists());
|
|
3404
3404
|
return unitComponents;
|
|
3405
3405
|
}
|
|
3406
3406
|
async getTemplateComponents() {
|
|
3407
|
-
const templateComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`).exists());
|
|
3407
|
+
const templateComponents = (await this.readdir("lib")).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${capitalize(name)}.Template.tsx`).exists());
|
|
3408
3408
|
return templateComponents;
|
|
3409
3409
|
}
|
|
3410
3410
|
async getViewsSourceCode() {
|
|
3411
3411
|
const viewComponents = await this.getViewComponents();
|
|
3412
|
-
return Promise.all(viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`)));
|
|
3412
|
+
return Promise.all(viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${capitalize(viewComponent)}.View.tsx`)));
|
|
3413
3413
|
}
|
|
3414
3414
|
async getUnitsSourceCode() {
|
|
3415
3415
|
const unitComponents = await this.getUnitComponents();
|
|
3416
|
-
return Promise.all(unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`)));
|
|
3416
|
+
return Promise.all(unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${capitalize(unitComponent)}.Unit.tsx`)));
|
|
3417
3417
|
}
|
|
3418
3418
|
async getTemplatesSourceCode() {
|
|
3419
3419
|
const templateComponents = await this.getTemplateComponents();
|
|
3420
|
-
return Promise.all(templateComponents.map((templateComponent) => this.getLocalFile(`lib/${templateComponent}/${templateComponent}.Template.tsx`)));
|
|
3420
|
+
return Promise.all(templateComponents.map((templateComponent) => this.getLocalFile(`lib/${templateComponent}/${capitalize(templateComponent)}.Template.tsx`)));
|
|
3421
3421
|
}
|
|
3422
3422
|
async getScalarConstantFiles() {
|
|
3423
3423
|
const scalarModules = await this.getScalarModules();
|
|
@@ -4889,6 +4889,12 @@ var statusForScope = (commands, diagnostics, scopes, expectedScope) => {
|
|
|
4889
4889
|
return "unknown";
|
|
4890
4890
|
return hasScopeFailure(scopes, expectedScope, diagnostics) ? "failed" : "passed";
|
|
4891
4891
|
};
|
|
4892
|
+
var statusForValidationKind = (commands, kind) => {
|
|
4893
|
+
const matching = commands.filter((command) => command.kind === kind);
|
|
4894
|
+
if (matching.length === 0)
|
|
4895
|
+
return "unknown";
|
|
4896
|
+
return matching.some((command) => command.status === "failed") ? "failed" : "passed";
|
|
4897
|
+
};
|
|
4892
4898
|
var createKnownBlockers = (commands, diagnostics) => {
|
|
4893
4899
|
const commandBlockers = commands.filter((command) => command.status === "failed" && (command.failureScope === "workspace-config" || command.failureScope === "environment")).map((command) => ({
|
|
4894
4900
|
code: `workflow-validation-${command.failureScope}`,
|
|
@@ -4922,7 +4928,17 @@ var createValidationStatuses = (commands, diagnostics) => {
|
|
|
4922
4928
|
const sourceStatus = statusForScope(commands, diagnostics, scopes, "source-change");
|
|
4923
4929
|
const workspaceStatus = hasScopeFailure(scopes, "workspace-config", diagnostics) || hasScopeFailure(scopes, "environment", diagnostics) ? "failed" : commands.length || diagnostics.length ? "passed" : "unknown";
|
|
4924
4930
|
const overallStatus = hasScopeFailure(scopes, "source-change", diagnostics) ? "failed" : hasScopeFailure(scopes, "workspace-config", diagnostics) ? "blocked-by-workspace-config" : hasScopeFailure(scopes, "environment", diagnostics) ? "blocked-by-environment" : workflowStatus(diagnostics) === "failed" || commandStatus(commands) === "failed" ? "failed" : "passed";
|
|
4925
|
-
return {
|
|
4931
|
+
return {
|
|
4932
|
+
sourceStatus,
|
|
4933
|
+
workspaceStatus,
|
|
4934
|
+
overallStatus,
|
|
4935
|
+
summary: {
|
|
4936
|
+
sourceChange: sourceStatus,
|
|
4937
|
+
generatedSync: statusForValidationKind(commands, "sync"),
|
|
4938
|
+
workspaceConfig: statusForScope(commands, diagnostics, scopes, "workspace-config"),
|
|
4939
|
+
environment: statusForScope(commands, diagnostics, scopes, "environment")
|
|
4940
|
+
}
|
|
4941
|
+
};
|
|
4926
4942
|
};
|
|
4927
4943
|
var createWorkflowValidationRunReport = async ({
|
|
4928
4944
|
runId = createWorkflowRunId("validation"),
|
|
@@ -5032,221 +5048,6 @@ var createRepairReport = ({
|
|
|
5032
5048
|
});
|
|
5033
5049
|
// pkgs/@akanjs/devkit/workflow/executor.ts
|
|
5034
5050
|
import { capitalize as capitalize2 } from "akanjs/common";
|
|
5035
|
-
var workflowStepKey = (workflow, stepId) => `${workflow}:${stepId}`;
|
|
5036
|
-
var primitiveReportToWorkflowStepResult = (report) => ({
|
|
5037
|
-
changedFiles: report.changedFiles,
|
|
5038
|
-
generatedFiles: report.generatedFiles,
|
|
5039
|
-
commands: report.validationCommands,
|
|
5040
|
-
diagnostics: report.diagnostics,
|
|
5041
|
-
recommendations: [],
|
|
5042
|
-
nextActions: report.nextActions
|
|
5043
|
-
});
|
|
5044
|
-
var workflowStringInput = (value) => typeof value === "string" ? value : null;
|
|
5045
|
-
var workflowStringListInput = (value) => Array.isArray(value) ? value.join(",") : null;
|
|
5046
|
-
var resolveWorkflowSys = async (workspace, target) => {
|
|
5047
|
-
if (!target)
|
|
5048
|
-
return null;
|
|
5049
|
-
const [apps, libs] = await workspace.getSyss();
|
|
5050
|
-
if (apps.includes(target))
|
|
5051
|
-
return AppExecutor.from(workspace, target);
|
|
5052
|
-
if (libs.includes(target))
|
|
5053
|
-
return LibExecutor.from(workspace, target);
|
|
5054
|
-
return null;
|
|
5055
|
-
};
|
|
5056
|
-
var targetMissing = (input2 = "app") => ({
|
|
5057
|
-
severity: "error",
|
|
5058
|
-
code: "workflow-target-missing",
|
|
5059
|
-
input: input2,
|
|
5060
|
-
message: "Workflow target app or library was not found."
|
|
5061
|
-
});
|
|
5062
|
-
var inputMissing = (input2) => ({
|
|
5063
|
-
severity: "error",
|
|
5064
|
-
code: "workflow-input-missing",
|
|
5065
|
-
input: input2,
|
|
5066
|
-
message: `Workflow input "${input2}" is required for apply.`
|
|
5067
|
-
});
|
|
5068
|
-
var unsupportedInput = (input2, message) => ({
|
|
5069
|
-
severity: "error",
|
|
5070
|
-
code: "workflow-input-unsupported",
|
|
5071
|
-
input: input2,
|
|
5072
|
-
message
|
|
5073
|
-
});
|
|
5074
|
-
var addFieldUiSurfaceInspection = (plan) => {
|
|
5075
|
-
const app = workflowStringInput(plan.inputs.app);
|
|
5076
|
-
const module = workflowStringInput(plan.inputs.module) ?? "<module>";
|
|
5077
|
-
const field = workflowStringInput(plan.inputs.field) ?? "<field>";
|
|
5078
|
-
const typeName = workflowStringInput(plan.inputs.type);
|
|
5079
|
-
const isNumeric = typeName === "Int" || typeName === "Float" || typeName === "integer" || typeName === "float";
|
|
5080
|
-
const moduleClassName = capitalize2(module);
|
|
5081
|
-
const target = `${app ? `apps/${app}` : "*"}/lib/${module}/${moduleClassName}.Template.tsx`;
|
|
5082
|
-
return {
|
|
5083
|
-
recommendations: [
|
|
5084
|
-
{
|
|
5085
|
-
code: "add-field-ui-surface-review",
|
|
5086
|
-
kind: "manual-action",
|
|
5087
|
-
target,
|
|
5088
|
-
action: isNumeric ? `Review ${moduleClassName} Template/Unit/View/Store surfaces before adding ${field}; confirm the local Field.Text numeric parser/formatter, validation rule, and dictionary label pattern.` : `Add ${field} to ${moduleClassName} UI surfaces only when the local Field.* pattern is clear.`,
|
|
5089
|
-
confidence: "medium",
|
|
5090
|
-
message: isNumeric ? `No UI file was modified automatically because a safe numeric input component pattern is not yet detected for ${module}.${field}.` : `Review Template/Unit/View/Store surfaces for ${module}.${field}; no UI file was modified automatically.`
|
|
5091
|
-
}
|
|
5092
|
-
],
|
|
5093
|
-
nextActions: [
|
|
5094
|
-
{
|
|
5095
|
-
command: `akan workflow explain ${plan.workflow}`,
|
|
5096
|
-
reason: "Review UI surface guidance before manually editing ambiguous UI files."
|
|
5097
|
-
}
|
|
5098
|
-
]
|
|
5099
|
-
};
|
|
5100
|
-
};
|
|
5101
|
-
var createWorkflowStepRegistry = ({
|
|
5102
|
-
workspace,
|
|
5103
|
-
createModule,
|
|
5104
|
-
createScalar,
|
|
5105
|
-
createUi,
|
|
5106
|
-
addField,
|
|
5107
|
-
addEnumField
|
|
5108
|
-
}) => {
|
|
5109
|
-
const inspect = async () => {
|
|
5110
|
-
return;
|
|
5111
|
-
};
|
|
5112
|
-
const commandOnly = async () => {
|
|
5113
|
-
return;
|
|
5114
|
-
};
|
|
5115
|
-
return {
|
|
5116
|
-
inspectSystem: inspect,
|
|
5117
|
-
inspectModule: inspect,
|
|
5118
|
-
syncTarget: commandOnly,
|
|
5119
|
-
lintTarget: commandOnly,
|
|
5120
|
-
[workflowStepKey("create-module", "create-module")]: async (_step, plan) => {
|
|
5121
|
-
const app = workflowStringInput(plan.inputs.app);
|
|
5122
|
-
const module = workflowStringInput(plan.inputs.module);
|
|
5123
|
-
const sys2 = await resolveWorkflowSys(workspace, app);
|
|
5124
|
-
if (!sys2 || !module)
|
|
5125
|
-
return { diagnostics: [!sys2 ? targetMissing() : inputMissing("module")] };
|
|
5126
|
-
return primitiveReportToWorkflowStepResult(await createModule(sys2, module));
|
|
5127
|
-
},
|
|
5128
|
-
[workflowStepKey("create-scalar", "create-scalar")]: async (_step, plan) => {
|
|
5129
|
-
const app = workflowStringInput(plan.inputs.app);
|
|
5130
|
-
const scalar = workflowStringInput(plan.inputs.scalar);
|
|
5131
|
-
const sys2 = await resolveWorkflowSys(workspace, app);
|
|
5132
|
-
if (!sys2 || !scalar)
|
|
5133
|
-
return { diagnostics: [!sys2 ? targetMissing() : inputMissing("scalar")] };
|
|
5134
|
-
return primitiveReportToWorkflowStepResult(await createScalar(sys2, scalar));
|
|
5135
|
-
},
|
|
5136
|
-
[workflowStepKey("create-ui", "create-ui")]: async (_step, plan) => {
|
|
5137
|
-
const surface = workflowStringInput(plan.inputs.surface);
|
|
5138
|
-
if (surface !== "view" && surface !== "unit" && surface !== "template") {
|
|
5139
|
-
return {
|
|
5140
|
-
diagnostics: [
|
|
5141
|
-
unsupportedInput("surface", "Workflow apply currently supports create-ui surfaces: view, unit, template.")
|
|
5142
|
-
]
|
|
5143
|
-
};
|
|
5144
|
-
}
|
|
5145
|
-
return primitiveReportToWorkflowStepResult(await createUi({
|
|
5146
|
-
app: workflowStringInput(plan.inputs.app),
|
|
5147
|
-
module: workflowStringInput(plan.inputs.module),
|
|
5148
|
-
surface
|
|
5149
|
-
}));
|
|
5150
|
-
},
|
|
5151
|
-
[workflowStepKey("add-field", "update-constant")]: async (_step, plan) => {
|
|
5152
|
-
if (workflowStringInput(plan.inputs.type)?.toLowerCase() === "enum") {
|
|
5153
|
-
return primitiveReportToWorkflowStepResult(await addEnumField({
|
|
5154
|
-
app: workflowStringInput(plan.inputs.app),
|
|
5155
|
-
module: workflowStringInput(plan.inputs.module),
|
|
5156
|
-
field: workflowStringInput(plan.inputs.field),
|
|
5157
|
-
values: workflowStringListInput(plan.inputs.values),
|
|
5158
|
-
defaultValue: workflowStringInput(plan.inputs.default)
|
|
5159
|
-
}));
|
|
5160
|
-
}
|
|
5161
|
-
return primitiveReportToWorkflowStepResult(await addField({
|
|
5162
|
-
app: workflowStringInput(plan.inputs.app),
|
|
5163
|
-
module: workflowStringInput(plan.inputs.module),
|
|
5164
|
-
field: workflowStringInput(plan.inputs.field),
|
|
5165
|
-
type: workflowStringInput(plan.inputs.type),
|
|
5166
|
-
defaultValue: workflowStringInput(plan.inputs.default)
|
|
5167
|
-
}));
|
|
5168
|
-
},
|
|
5169
|
-
[workflowStepKey("add-field", "update-dictionary")]: inspect,
|
|
5170
|
-
[workflowStepKey("add-field", "update-ui-surfaces")]: async (_step, plan) => addFieldUiSurfaceInspection(plan),
|
|
5171
|
-
[workflowStepKey("add-enum-field", "update-constant")]: async (_step, plan) => primitiveReportToWorkflowStepResult(await addEnumField({
|
|
5172
|
-
app: workflowStringInput(plan.inputs.app),
|
|
5173
|
-
module: workflowStringInput(plan.inputs.module),
|
|
5174
|
-
field: workflowStringInput(plan.inputs.field),
|
|
5175
|
-
values: workflowStringListInput(plan.inputs.values),
|
|
5176
|
-
defaultValue: workflowStringInput(plan.inputs.default)
|
|
5177
|
-
})),
|
|
5178
|
-
[workflowStepKey("add-enum-field", "update-dictionary")]: inspect,
|
|
5179
|
-
[workflowStepKey("add-enum-field", "update-option")]: inspect
|
|
5180
|
-
};
|
|
5181
|
-
};
|
|
5182
|
-
class WorkflowExecutor {
|
|
5183
|
-
registry;
|
|
5184
|
-
constructor(registry) {
|
|
5185
|
-
this.registry = registry;
|
|
5186
|
-
}
|
|
5187
|
-
async apply(plan) {
|
|
5188
|
-
const changedFiles = [];
|
|
5189
|
-
const generatedFiles = [];
|
|
5190
|
-
const recommendedValidationCommands = [];
|
|
5191
|
-
const diagnostics = [...plan.diagnostics];
|
|
5192
|
-
const recommendations = [...plan.recommendations];
|
|
5193
|
-
const nextActions = [];
|
|
5194
|
-
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
5195
|
-
return createWorkflowApplyReport({
|
|
5196
|
-
workflow: plan.workflow,
|
|
5197
|
-
mode: "apply",
|
|
5198
|
-
changedFiles,
|
|
5199
|
-
generatedFiles,
|
|
5200
|
-
recommendedValidationCommands,
|
|
5201
|
-
diagnostics,
|
|
5202
|
-
recommendations,
|
|
5203
|
-
nextActions,
|
|
5204
|
-
plan
|
|
5205
|
-
});
|
|
5206
|
-
}
|
|
5207
|
-
recommendedValidationCommands.push(...workflowCommandsForPlan(plan));
|
|
5208
|
-
nextActions.push(...workflowCommandsForPlan(plan));
|
|
5209
|
-
for (const step of plan.steps) {
|
|
5210
|
-
const runner = this.registry[workflowStepKey(plan.workflow, step.id)] ?? this.registry[step.tool] ?? this.registry[step.id];
|
|
5211
|
-
if (!runner) {
|
|
5212
|
-
diagnostics.push({
|
|
5213
|
-
severity: "error",
|
|
5214
|
-
code: "workflow-step-unsupported",
|
|
5215
|
-
message: `Workflow ${plan.workflow} step "${step.id}" is not supported by workflow apply yet.`
|
|
5216
|
-
});
|
|
5217
|
-
nextActions.push({
|
|
5218
|
-
command: `akan workflow explain ${plan.workflow}`,
|
|
5219
|
-
reason: "Review the unsupported workflow step before retrying apply."
|
|
5220
|
-
});
|
|
5221
|
-
break;
|
|
5222
|
-
}
|
|
5223
|
-
const result = await runner(step, plan);
|
|
5224
|
-
if (!result)
|
|
5225
|
-
continue;
|
|
5226
|
-
changedFiles.push(...result.changedFiles ?? []);
|
|
5227
|
-
generatedFiles.push(...result.generatedFiles ?? []);
|
|
5228
|
-
recommendedValidationCommands.push(...result.commands ?? []);
|
|
5229
|
-
diagnostics.push(...result.diagnostics ?? []);
|
|
5230
|
-
recommendations.push(...result.recommendations ?? []);
|
|
5231
|
-
nextActions.push(...result.nextActions ?? []);
|
|
5232
|
-
if (diagnostics.some((diagnostic) => diagnostic.severity === "error"))
|
|
5233
|
-
break;
|
|
5234
|
-
}
|
|
5235
|
-
return createWorkflowApplyReport({
|
|
5236
|
-
workflow: plan.workflow,
|
|
5237
|
-
mode: "apply",
|
|
5238
|
-
changedFiles,
|
|
5239
|
-
generatedFiles,
|
|
5240
|
-
recommendedValidationCommands,
|
|
5241
|
-
diagnostics,
|
|
5242
|
-
recommendations,
|
|
5243
|
-
nextActions,
|
|
5244
|
-
plan
|
|
5245
|
-
});
|
|
5246
|
-
}
|
|
5247
|
-
}
|
|
5248
|
-
// pkgs/@akanjs/devkit/workflow/plan.ts
|
|
5249
|
-
import { capitalize as capitalize3 } from "akanjs/common";
|
|
5250
5051
|
|
|
5251
5052
|
// pkgs/@akanjs/devkit/workflow/primitive.ts
|
|
5252
5053
|
var createPrimitiveWriteReport = ({
|
|
@@ -5298,6 +5099,23 @@ var sourceFile = (sys2, path10, action, reason) => ({
|
|
|
5298
5099
|
action,
|
|
5299
5100
|
reason
|
|
5300
5101
|
});
|
|
5102
|
+
var moduleComponentName = (moduleName) => `${moduleName.slice(0, 1).toUpperCase()}${moduleName.slice(1)}`;
|
|
5103
|
+
var moduleSourcePaths = (moduleName) => {
|
|
5104
|
+
const componentName = moduleComponentName(moduleName);
|
|
5105
|
+
return {
|
|
5106
|
+
abstract: `lib/${moduleName}/${moduleName}.abstract.md`,
|
|
5107
|
+
constant: `lib/${moduleName}/${moduleName}.constant.ts`,
|
|
5108
|
+
dictionary: `lib/${moduleName}/${moduleName}.dictionary.ts`,
|
|
5109
|
+
service: `lib/${moduleName}/${moduleName}.service.ts`,
|
|
5110
|
+
signal: `lib/${moduleName}/${moduleName}.signal.ts`,
|
|
5111
|
+
store: `lib/${moduleName}/${moduleName}.store.ts`,
|
|
5112
|
+
template: `lib/${moduleName}/${componentName}.Template.tsx`,
|
|
5113
|
+
unit: `lib/${moduleName}/${componentName}.Unit.tsx`,
|
|
5114
|
+
util: `lib/${moduleName}/${componentName}.Util.tsx`,
|
|
5115
|
+
view: `lib/${moduleName}/${componentName}.View.tsx`,
|
|
5116
|
+
zone: `lib/${moduleName}/${componentName}.Zone.tsx`
|
|
5117
|
+
};
|
|
5118
|
+
};
|
|
5301
5119
|
var generatedFilesForSync = (sys2, reason = "Generated files may change after sync.") => generatedFilePathsForTarget(getSysRoot(sys2), reason);
|
|
5302
5120
|
var validationCommandsForTarget = (target) => [
|
|
5303
5121
|
{ command: `akan sync ${target}`, reason: "Refresh generated Akan files from source conventions." },
|
|
@@ -5324,6 +5142,50 @@ var createPassedPrimitiveReport = ({
|
|
|
5324
5142
|
var scalarChangedFiles = (sys2, scalarName, files) => Object.values(files).map((file) => sourceFile(sys2, `lib/__scalar/${scalarName}/${file.filename}`, "create", "Scalar source file was created."));
|
|
5325
5143
|
var titleize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
5326
5144
|
var lowerlize = (value) => `${value.slice(0, 1).toLowerCase()}${value.slice(1)}`;
|
|
5145
|
+
var koLabels = {
|
|
5146
|
+
amount: "\uAE08\uC561",
|
|
5147
|
+
budget: "\uC608\uC0B0",
|
|
5148
|
+
category: "\uCE74\uD14C\uACE0\uB9AC",
|
|
5149
|
+
content: "\uB0B4\uC6A9",
|
|
5150
|
+
count: "\uAC1C\uC218",
|
|
5151
|
+
createdAt: "\uC0DD\uC131\uC77C",
|
|
5152
|
+
date: "\uB0A0\uC9DC",
|
|
5153
|
+
description: "\uC124\uBA85",
|
|
5154
|
+
due: "\uB9C8\uAC10\uC77C",
|
|
5155
|
+
dueAt: "\uB9C8\uAC10\uC77C",
|
|
5156
|
+
email: "\uC774\uBA54\uC77C",
|
|
5157
|
+
enabled: "\uD65C\uC131\uD654",
|
|
5158
|
+
endAt: "\uC885\uB8CC\uC77C",
|
|
5159
|
+
id: "ID",
|
|
5160
|
+
name: "\uC774\uB984",
|
|
5161
|
+
owner: "\uB2F4\uB2F9\uC790",
|
|
5162
|
+
priority: "\uC6B0\uC120\uC21C\uC704",
|
|
5163
|
+
project: "\uD504\uB85C\uC81D\uD2B8",
|
|
5164
|
+
rating: "\uD3C9\uC810",
|
|
5165
|
+
startAt: "\uC2DC\uC791\uC77C",
|
|
5166
|
+
status: "\uC0C1\uD0DC",
|
|
5167
|
+
title: "\uC81C\uBAA9",
|
|
5168
|
+
updatedAt: "\uC218\uC815\uC77C"
|
|
5169
|
+
};
|
|
5170
|
+
var splitFieldWords = (fieldName) => fieldName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").split(/\s+/).map((word) => word.trim()).filter(Boolean);
|
|
5171
|
+
var koLabelForField = (fieldName) => {
|
|
5172
|
+
if (koLabels[fieldName])
|
|
5173
|
+
return koLabels[fieldName];
|
|
5174
|
+
const words = splitFieldWords(fieldName);
|
|
5175
|
+
const translated = words.map((word) => koLabels[word] ?? koLabels[lowerlize(word)] ?? null);
|
|
5176
|
+
return translated.every(Boolean) ? translated.join(" ") : null;
|
|
5177
|
+
};
|
|
5178
|
+
var bilingualLabelForField = (fieldName) => {
|
|
5179
|
+
const en = titleize(fieldName);
|
|
5180
|
+
return { en, ko: koLabelForField(fieldName) ?? en };
|
|
5181
|
+
};
|
|
5182
|
+
var bilingualDescriptionForField = (fieldName) => {
|
|
5183
|
+
const label = bilingualLabelForField(fieldName);
|
|
5184
|
+
return {
|
|
5185
|
+
en: `Enter ${label.en.toLowerCase()}.`,
|
|
5186
|
+
ko: `${label.ko} \uAC12\uC744 \uC785\uB825\uD569\uB2C8\uB2E4.`
|
|
5187
|
+
};
|
|
5188
|
+
};
|
|
5327
5189
|
var normalizeFieldType = (typeName) => {
|
|
5328
5190
|
const normalizedTypes = {
|
|
5329
5191
|
string: "String",
|
|
@@ -5351,6 +5213,15 @@ var ensureBaseTypeImport = (content, typeName) => {
|
|
|
5351
5213
|
${content}`;
|
|
5352
5214
|
};
|
|
5353
5215
|
var numericDefault = (typeName, rawDefault) => {
|
|
5216
|
+
if (typeof rawDefault === "number") {
|
|
5217
|
+
if (!Number.isFinite(rawDefault))
|
|
5218
|
+
return null;
|
|
5219
|
+
if (typeName === "Int" && !Number.isInteger(rawDefault))
|
|
5220
|
+
return null;
|
|
5221
|
+
return String(rawDefault);
|
|
5222
|
+
}
|
|
5223
|
+
if (typeof rawDefault !== "string")
|
|
5224
|
+
return null;
|
|
5354
5225
|
const trimmed = rawDefault.trim();
|
|
5355
5226
|
if (!trimmed || !Number.isFinite(Number(trimmed)))
|
|
5356
5227
|
return null;
|
|
@@ -5358,16 +5229,41 @@ var numericDefault = (typeName, rawDefault) => {
|
|
|
5358
5229
|
return null;
|
|
5359
5230
|
return trimmed;
|
|
5360
5231
|
};
|
|
5361
|
-
var
|
|
5362
|
-
if (
|
|
5363
|
-
return
|
|
5364
|
-
|
|
5232
|
+
var booleanDefault = (rawDefault) => {
|
|
5233
|
+
if (typeof rawDefault === "boolean")
|
|
5234
|
+
return String(rawDefault);
|
|
5235
|
+
if (typeof rawDefault !== "string")
|
|
5236
|
+
return null;
|
|
5237
|
+
const lowered = rawDefault.trim().toLowerCase();
|
|
5238
|
+
return lowered === "true" || lowered === "false" ? lowered : null;
|
|
5239
|
+
};
|
|
5240
|
+
var dateDefault = (rawDefault) => {
|
|
5241
|
+
if (typeof rawDefault === "number" && Number.isFinite(rawDefault))
|
|
5242
|
+
return `new Date(${rawDefault})`;
|
|
5243
|
+
if (typeof rawDefault !== "string")
|
|
5244
|
+
return null;
|
|
5245
|
+
const trimmed = rawDefault.trim();
|
|
5246
|
+
if (!trimmed)
|
|
5247
|
+
return null;
|
|
5248
|
+
if (trimmed === "now")
|
|
5249
|
+
return "new Date()";
|
|
5250
|
+
if (!Number.isNaN(Date.parse(trimmed)))
|
|
5251
|
+
return `new Date(${JSON.stringify(trimmed)})`;
|
|
5252
|
+
return null;
|
|
5253
|
+
};
|
|
5254
|
+
var coerceFieldDefault = (typeName, defaultValue, options = {}) => {
|
|
5255
|
+
const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
|
|
5256
|
+
if (defaultValue === undefined || defaultValue === null || defaultValue === "") {
|
|
5257
|
+
return { expression: null, normalized: false, normalizedType };
|
|
5258
|
+
}
|
|
5365
5259
|
if (normalizedType === "Int" || normalizedType === "Float") {
|
|
5366
5260
|
const expression = numericDefault(normalizedType, defaultValue);
|
|
5367
5261
|
if (expression !== null)
|
|
5368
|
-
return { expression };
|
|
5262
|
+
return { expression, normalized: typeof defaultValue === "string", normalizedType };
|
|
5369
5263
|
return {
|
|
5370
5264
|
expression: null,
|
|
5265
|
+
normalized: false,
|
|
5266
|
+
normalizedType,
|
|
5371
5267
|
diagnostic: {
|
|
5372
5268
|
severity: "error",
|
|
5373
5269
|
code: "primitive-default-value-invalid",
|
|
@@ -5378,11 +5274,13 @@ var coerceFieldDefault = (typeName, defaultValue) => {
|
|
|
5378
5274
|
};
|
|
5379
5275
|
}
|
|
5380
5276
|
if (normalizedType === "Boolean") {
|
|
5381
|
-
const
|
|
5382
|
-
if (
|
|
5383
|
-
return { expression:
|
|
5277
|
+
const expression = booleanDefault(defaultValue);
|
|
5278
|
+
if (expression !== null)
|
|
5279
|
+
return { expression, normalized: typeof defaultValue === "string", normalizedType };
|
|
5384
5280
|
return {
|
|
5385
5281
|
expression: null,
|
|
5282
|
+
normalized: false,
|
|
5283
|
+
normalizedType,
|
|
5386
5284
|
diagnostic: {
|
|
5387
5285
|
severity: "error",
|
|
5388
5286
|
code: "primitive-default-value-invalid",
|
|
@@ -5392,31 +5290,113 @@ var coerceFieldDefault = (typeName, defaultValue) => {
|
|
|
5392
5290
|
}
|
|
5393
5291
|
};
|
|
5394
5292
|
}
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5293
|
+
if (normalizedType === "Date") {
|
|
5294
|
+
const expression = dateDefault(defaultValue);
|
|
5295
|
+
if (expression !== null)
|
|
5296
|
+
return { expression, normalized: true, normalizedType };
|
|
5297
|
+
return {
|
|
5298
|
+
expression: null,
|
|
5299
|
+
normalized: false,
|
|
5300
|
+
normalizedType,
|
|
5301
|
+
diagnostic: {
|
|
5302
|
+
severity: "error",
|
|
5303
|
+
code: "primitive-default-value-invalid",
|
|
5304
|
+
input: "default",
|
|
5305
|
+
failureScope: "source-change",
|
|
5306
|
+
message: `Default value for Date must be "now", a timestamp, or a parseable date string. Received: ${JSON.stringify(defaultValue)}.`
|
|
5307
|
+
}
|
|
5308
|
+
};
|
|
5309
|
+
}
|
|
5310
|
+
if (normalizedType === "enum") {
|
|
5311
|
+
if (typeof defaultValue === "string" && options.enumValues?.includes(defaultValue)) {
|
|
5312
|
+
return { expression: JSON.stringify(defaultValue), normalized: false, normalizedType };
|
|
5313
|
+
}
|
|
5314
|
+
return {
|
|
5315
|
+
expression: null,
|
|
5316
|
+
normalized: false,
|
|
5317
|
+
normalizedType,
|
|
5318
|
+
diagnostic: {
|
|
5319
|
+
severity: "error",
|
|
5320
|
+
code: "primitive-default-value-invalid",
|
|
5321
|
+
input: "default",
|
|
5322
|
+
failureScope: "source-change",
|
|
5323
|
+
message: `Default value for enum must be one of: ${(options.enumValues ?? []).join(", ")}. Received: ${JSON.stringify(defaultValue)}.`
|
|
5324
|
+
}
|
|
5325
|
+
};
|
|
5326
|
+
}
|
|
5327
|
+
return {
|
|
5328
|
+
expression: JSON.stringify(String(defaultValue)),
|
|
5329
|
+
normalized: typeof defaultValue !== "string",
|
|
5330
|
+
normalizedType
|
|
5331
|
+
};
|
|
5332
|
+
};
|
|
5333
|
+
var fieldExpression = (typeName, defaultValue, options = {}) => {
|
|
5334
|
+
const typeExpression = normalizeFieldType(typeName);
|
|
5335
|
+
const defaultExpression = coerceFieldDefault(options.enumValues ? "enum" : typeExpression, defaultValue, options).expression;
|
|
5336
|
+
const defaultOption = defaultExpression ? `, { default: ${defaultExpression} }` : "";
|
|
5337
|
+
return `field(${typeExpression}${defaultOption})`;
|
|
5338
|
+
};
|
|
5339
|
+
var insertIntoObject = (content, className, line) => {
|
|
5340
|
+
const classIndex = content.indexOf(`export class ${className} extends via`);
|
|
5341
|
+
if (classIndex < 0)
|
|
5342
|
+
return null;
|
|
5343
|
+
const objectEndIndex = content.indexOf("}))", classIndex);
|
|
5344
|
+
if (objectEndIndex < 0)
|
|
5345
|
+
return null;
|
|
5346
|
+
const prefix = content.slice(0, objectEndIndex);
|
|
5347
|
+
const suffix = content.slice(objectEndIndex);
|
|
5348
|
+
const insertion = prefix.endsWith(`
|
|
5349
|
+
`) ? ` ${line}
|
|
5350
|
+
` : `
|
|
5351
|
+
${line}
|
|
5352
|
+
`;
|
|
5353
|
+
return `${prefix}${insertion}${suffix}`;
|
|
5354
|
+
};
|
|
5355
|
+
var insertLightProjectionField = (content, moduleClassName, fieldName) => {
|
|
5356
|
+
const classIndex = content.indexOf(`export class Light${moduleClassName} extends via`);
|
|
5357
|
+
if (classIndex < 0)
|
|
5358
|
+
return null;
|
|
5359
|
+
const arrayMatch = /\[([\s\S]*?)\]\s+as const/.exec(content.slice(classIndex));
|
|
5360
|
+
if (!arrayMatch || arrayMatch.index === undefined)
|
|
5361
|
+
return null;
|
|
5362
|
+
const arrayStart = classIndex + arrayMatch.index;
|
|
5363
|
+
const arrayEnd = arrayStart + arrayMatch[0].length;
|
|
5364
|
+
const fields = [...arrayMatch[1].matchAll(/"([^"]+)"/g)].map((match) => match[1]).filter(Boolean);
|
|
5365
|
+
if (fields.includes(fieldName))
|
|
5366
|
+
return content;
|
|
5367
|
+
const nextFields = [...fields, fieldName];
|
|
5368
|
+
const nextArray = nextFields.length === 0 ? "[] as const" : `[
|
|
5369
|
+
${nextFields.map((field) => ` ${JSON.stringify(field)},`).join(`
|
|
5370
|
+
`)}
|
|
5371
|
+
] as const`;
|
|
5372
|
+
return `${content.slice(0, arrayStart)}${nextArray}${content.slice(arrayEnd)}`;
|
|
5373
|
+
};
|
|
5374
|
+
var insertTemplateField = ({
|
|
5375
|
+
content,
|
|
5376
|
+
moduleName,
|
|
5377
|
+
moduleClassName,
|
|
5378
|
+
fieldName,
|
|
5379
|
+
component
|
|
5380
|
+
}) => {
|
|
5381
|
+
if (content.includes(`l("${moduleName}.${fieldName}")`) || content.includes(`.${fieldName}`))
|
|
5382
|
+
return content;
|
|
5383
|
+
const layoutEndIndex = content.indexOf(" </Layout.Template>");
|
|
5384
|
+
if (layoutEndIndex < 0)
|
|
5385
|
+
return null;
|
|
5386
|
+
const formName = `${moduleName}Form`;
|
|
5387
|
+
if (!content.includes(`const ${formName} = st.use.${moduleName}Form();`))
|
|
5388
|
+
return null;
|
|
5389
|
+
const fieldSetter = `st.do.set${moduleComponentName(fieldName)}On${moduleClassName}`;
|
|
5390
|
+
const fieldBlock = ` <${component}
|
|
5391
|
+
label={l("${moduleName}.${fieldName}")}
|
|
5392
|
+
desc={l("${moduleName}.${fieldName}.desc")}
|
|
5393
|
+
value={${formName}.${fieldName}}
|
|
5394
|
+
onChange={${fieldSetter}}
|
|
5395
|
+
/>
|
|
5396
|
+
`;
|
|
5397
|
+
return `${content.slice(0, layoutEndIndex)}${fieldBlock}${content.slice(layoutEndIndex)}`;
|
|
5398
|
+
};
|
|
5399
|
+
var ensureEnumImport = (content) => {
|
|
5420
5400
|
if (content.includes("enumOf"))
|
|
5421
5401
|
return content;
|
|
5422
5402
|
const baseImport = /import \{ ([^}]+) \} from "akanjs\/base";/.exec(content);
|
|
@@ -5445,14 +5425,15 @@ ${enumClass}`;
|
|
|
5445
5425
|
var insertDictionaryModelField = (content, moduleClassName, fieldName) => {
|
|
5446
5426
|
if (new RegExp(`\\b${fieldName}\\s*:`).test(content))
|
|
5447
5427
|
return content;
|
|
5448
|
-
const label =
|
|
5428
|
+
const label = bilingualLabelForField(fieldName);
|
|
5429
|
+
const desc = bilingualDescriptionForField(fieldName);
|
|
5449
5430
|
const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => ({`);
|
|
5450
5431
|
if (modelIndex < 0)
|
|
5451
5432
|
return null;
|
|
5452
5433
|
const objectEndIndex = content.indexOf(" }))", modelIndex);
|
|
5453
5434
|
if (objectEndIndex < 0)
|
|
5454
5435
|
return null;
|
|
5455
|
-
return `${content.slice(0, objectEndIndex)} ${fieldName}: t([${JSON.stringify(label)}, ${JSON.stringify(label)}]).desc([${JSON.stringify(
|
|
5436
|
+
return `${content.slice(0, objectEndIndex)} ${fieldName}: t([${JSON.stringify(label.en)}, ${JSON.stringify(label.ko)}]).desc([${JSON.stringify(desc.en)}, ${JSON.stringify(desc.ko)}]),
|
|
5456
5437
|
${content.slice(objectEndIndex)}`;
|
|
5457
5438
|
};
|
|
5458
5439
|
var ensureConstantTypeImport = (content, constantPath, typeName) => {
|
|
@@ -5483,7 +5464,273 @@ ${values.map((value) => ` ${value}: t([${JSON.stringify(titleize(value))}, ${
|
|
|
5483
5464
|
};
|
|
5484
5465
|
var parseValues = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
|
|
5485
5466
|
|
|
5467
|
+
// pkgs/@akanjs/devkit/workflow/uiPolicy.ts
|
|
5468
|
+
var addFieldUiPolicyForType = (typeName) => {
|
|
5469
|
+
const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
|
|
5470
|
+
if (normalizedType === "Int" || normalizedType === "Float") {
|
|
5471
|
+
return {
|
|
5472
|
+
normalizedType,
|
|
5473
|
+
component: "Field.Number",
|
|
5474
|
+
confidence: "high",
|
|
5475
|
+
autoTemplateSupported: true
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
if (normalizedType === "Date") {
|
|
5479
|
+
return {
|
|
5480
|
+
normalizedType,
|
|
5481
|
+
component: "Field.Date",
|
|
5482
|
+
confidence: "high",
|
|
5483
|
+
autoTemplateSupported: true
|
|
5484
|
+
};
|
|
5485
|
+
}
|
|
5486
|
+
if (normalizedType === "Boolean" || normalizedType === "enum") {
|
|
5487
|
+
return {
|
|
5488
|
+
normalizedType,
|
|
5489
|
+
component: "Field.ToggleSelect",
|
|
5490
|
+
confidence: "medium",
|
|
5491
|
+
autoTemplateSupported: false
|
|
5492
|
+
};
|
|
5493
|
+
}
|
|
5494
|
+
if (normalizedType === "String") {
|
|
5495
|
+
return {
|
|
5496
|
+
normalizedType,
|
|
5497
|
+
component: "Field.Text",
|
|
5498
|
+
confidence: "high",
|
|
5499
|
+
autoTemplateSupported: true
|
|
5500
|
+
};
|
|
5501
|
+
}
|
|
5502
|
+
return {
|
|
5503
|
+
normalizedType,
|
|
5504
|
+
component: "Field.Text",
|
|
5505
|
+
confidence: "low",
|
|
5506
|
+
autoTemplateSupported: false
|
|
5507
|
+
};
|
|
5508
|
+
};
|
|
5509
|
+
|
|
5510
|
+
// pkgs/@akanjs/devkit/workflow/executor.ts
|
|
5511
|
+
var workflowStepKey = (workflow, stepId) => `${workflow}:${stepId}`;
|
|
5512
|
+
var primitiveReportToWorkflowStepResult = (report) => ({
|
|
5513
|
+
changedFiles: report.changedFiles,
|
|
5514
|
+
generatedFiles: report.generatedFiles,
|
|
5515
|
+
commands: report.validationCommands,
|
|
5516
|
+
diagnostics: report.diagnostics,
|
|
5517
|
+
recommendations: [],
|
|
5518
|
+
nextActions: report.nextActions
|
|
5519
|
+
});
|
|
5520
|
+
var workflowStringInput = (value) => typeof value === "string" ? value : null;
|
|
5521
|
+
var workflowStringListInput = (value) => Array.isArray(value) ? value.join(",") : null;
|
|
5522
|
+
var workflowStringArrayInput = (value) => Array.isArray(value) ? value : null;
|
|
5523
|
+
var workflowBooleanInput = (value) => typeof value === "boolean" ? value : null;
|
|
5524
|
+
var resolveWorkflowSys = async (workspace, target) => {
|
|
5525
|
+
if (!target)
|
|
5526
|
+
return null;
|
|
5527
|
+
const [apps, libs] = await workspace.getSyss();
|
|
5528
|
+
if (apps.includes(target))
|
|
5529
|
+
return AppExecutor.from(workspace, target);
|
|
5530
|
+
if (libs.includes(target))
|
|
5531
|
+
return LibExecutor.from(workspace, target);
|
|
5532
|
+
return null;
|
|
5533
|
+
};
|
|
5534
|
+
var targetMissing = (input2 = "app") => ({
|
|
5535
|
+
severity: "error",
|
|
5536
|
+
code: "workflow-target-missing",
|
|
5537
|
+
input: input2,
|
|
5538
|
+
message: "Workflow target app or library was not found."
|
|
5539
|
+
});
|
|
5540
|
+
var inputMissing = (input2) => ({
|
|
5541
|
+
severity: "error",
|
|
5542
|
+
code: "workflow-input-missing",
|
|
5543
|
+
input: input2,
|
|
5544
|
+
message: `Workflow input "${input2}" is required for apply.`
|
|
5545
|
+
});
|
|
5546
|
+
var unsupportedInput = (input2, message) => ({
|
|
5547
|
+
severity: "error",
|
|
5548
|
+
code: "workflow-input-unsupported",
|
|
5549
|
+
input: input2,
|
|
5550
|
+
message
|
|
5551
|
+
});
|
|
5552
|
+
var addFieldUiSurfaceInspection = (plan) => {
|
|
5553
|
+
const app = workflowStringInput(plan.inputs.app);
|
|
5554
|
+
const module = workflowStringInput(plan.inputs.module) ?? "<module>";
|
|
5555
|
+
const field = workflowStringInput(plan.inputs.field) ?? "<field>";
|
|
5556
|
+
const typeName = workflowStringInput(plan.inputs.type);
|
|
5557
|
+
const policy = addFieldUiPolicyForType(typeName ?? "String");
|
|
5558
|
+
const surfaces = workflowStringArrayInput(plan.inputs.surfaces);
|
|
5559
|
+
const templateRequested = surfaces?.includes("template") ?? false;
|
|
5560
|
+
const moduleClassName = capitalize2(module);
|
|
5561
|
+
const target = `${app ? `apps/${app}` : "*"}/${moduleSourcePaths(module).template}`;
|
|
5562
|
+
return {
|
|
5563
|
+
recommendations: [
|
|
5564
|
+
{
|
|
5565
|
+
code: "add-field-ui-surface-review",
|
|
5566
|
+
kind: "manual-action",
|
|
5567
|
+
target,
|
|
5568
|
+
action: templateRequested ? `Template was requested for ${field}. If no Template file changed, auto-edit was skipped because the file was missing, the generated ${module}Form/Layout.Template pattern was not found, or ${policy.component} needs option binding. Candidate position: inside Layout.Template near the existing Field components.` : `Template was not selected, so UI files are intentionally left unchanged. Candidate positions if you expose it later: Layout.Template field list for editing, Light${moduleClassName} projection for list/card data, and Unit/View card sections for display.`,
|
|
5569
|
+
confidence: "medium",
|
|
5570
|
+
message: `Review UI surfaces for ${module}.${field}; recommended component is ${policy.component}, with manual reasons and candidate positions in action.`
|
|
5571
|
+
}
|
|
5572
|
+
],
|
|
5573
|
+
nextActions: [
|
|
5574
|
+
{
|
|
5575
|
+
command: `akan workflow explain ${plan.workflow}`,
|
|
5576
|
+
reason: "Review UI surface guidance before manually editing ambiguous UI files."
|
|
5577
|
+
}
|
|
5578
|
+
]
|
|
5579
|
+
};
|
|
5580
|
+
};
|
|
5581
|
+
var createWorkflowStepRegistry = ({
|
|
5582
|
+
workspace,
|
|
5583
|
+
createModule,
|
|
5584
|
+
createScalar,
|
|
5585
|
+
createUi,
|
|
5586
|
+
addField,
|
|
5587
|
+
addEnumField
|
|
5588
|
+
}) => {
|
|
5589
|
+
const inspect = async () => {
|
|
5590
|
+
return;
|
|
5591
|
+
};
|
|
5592
|
+
const commandOnly = async () => {
|
|
5593
|
+
return;
|
|
5594
|
+
};
|
|
5595
|
+
return {
|
|
5596
|
+
inspectSystem: inspect,
|
|
5597
|
+
inspectModule: inspect,
|
|
5598
|
+
syncTarget: commandOnly,
|
|
5599
|
+
lintTarget: commandOnly,
|
|
5600
|
+
[workflowStepKey("create-module", "create-module")]: async (_step, plan) => {
|
|
5601
|
+
const app = workflowStringInput(plan.inputs.app);
|
|
5602
|
+
const module = workflowStringInput(plan.inputs.module);
|
|
5603
|
+
const sys2 = await resolveWorkflowSys(workspace, app);
|
|
5604
|
+
if (!sys2 || !module)
|
|
5605
|
+
return { diagnostics: [!sys2 ? targetMissing() : inputMissing("module")] };
|
|
5606
|
+
return primitiveReportToWorkflowStepResult(await createModule(sys2, module));
|
|
5607
|
+
},
|
|
5608
|
+
[workflowStepKey("create-scalar", "create-scalar")]: async (_step, plan) => {
|
|
5609
|
+
const app = workflowStringInput(plan.inputs.app);
|
|
5610
|
+
const scalar = workflowStringInput(plan.inputs.scalar);
|
|
5611
|
+
const sys2 = await resolveWorkflowSys(workspace, app);
|
|
5612
|
+
if (!sys2 || !scalar)
|
|
5613
|
+
return { diagnostics: [!sys2 ? targetMissing() : inputMissing("scalar")] };
|
|
5614
|
+
return primitiveReportToWorkflowStepResult(await createScalar(sys2, scalar));
|
|
5615
|
+
},
|
|
5616
|
+
[workflowStepKey("create-ui", "create-ui")]: async (_step, plan) => {
|
|
5617
|
+
const surface = workflowStringInput(plan.inputs.surface);
|
|
5618
|
+
if (surface !== "view" && surface !== "unit" && surface !== "template") {
|
|
5619
|
+
return {
|
|
5620
|
+
diagnostics: [
|
|
5621
|
+
unsupportedInput("surface", "Workflow apply currently supports create-ui surfaces: view, unit, template.")
|
|
5622
|
+
]
|
|
5623
|
+
};
|
|
5624
|
+
}
|
|
5625
|
+
return primitiveReportToWorkflowStepResult(await createUi({
|
|
5626
|
+
app: workflowStringInput(plan.inputs.app),
|
|
5627
|
+
module: workflowStringInput(plan.inputs.module),
|
|
5628
|
+
surface
|
|
5629
|
+
}));
|
|
5630
|
+
},
|
|
5631
|
+
[workflowStepKey("add-field", "update-constant")]: async (_step, plan) => {
|
|
5632
|
+
if (workflowStringInput(plan.inputs.type)?.toLowerCase() === "enum") {
|
|
5633
|
+
return primitiveReportToWorkflowStepResult(await addEnumField({
|
|
5634
|
+
app: workflowStringInput(plan.inputs.app),
|
|
5635
|
+
module: workflowStringInput(plan.inputs.module),
|
|
5636
|
+
field: workflowStringInput(plan.inputs.field),
|
|
5637
|
+
values: workflowStringListInput(plan.inputs.values),
|
|
5638
|
+
defaultValue: workflowStringInput(plan.inputs.default),
|
|
5639
|
+
surfaces: workflowStringArrayInput(plan.inputs.surfaces),
|
|
5640
|
+
includeInLight: workflowBooleanInput(plan.inputs.includeInLight)
|
|
5641
|
+
}));
|
|
5642
|
+
}
|
|
5643
|
+
return primitiveReportToWorkflowStepResult(await addField({
|
|
5644
|
+
app: workflowStringInput(plan.inputs.app),
|
|
5645
|
+
module: workflowStringInput(plan.inputs.module),
|
|
5646
|
+
field: workflowStringInput(plan.inputs.field),
|
|
5647
|
+
type: workflowStringInput(plan.inputs.type),
|
|
5648
|
+
defaultValue: workflowStringInput(plan.inputs.default),
|
|
5649
|
+
surfaces: workflowStringArrayInput(plan.inputs.surfaces),
|
|
5650
|
+
includeInLight: workflowBooleanInput(plan.inputs.includeInLight)
|
|
5651
|
+
}));
|
|
5652
|
+
},
|
|
5653
|
+
[workflowStepKey("add-field", "update-dictionary")]: inspect,
|
|
5654
|
+
[workflowStepKey("add-field", "update-ui-surfaces")]: async (_step, plan) => addFieldUiSurfaceInspection(plan),
|
|
5655
|
+
[workflowStepKey("add-enum-field", "update-constant")]: async (_step, plan) => primitiveReportToWorkflowStepResult(await addEnumField({
|
|
5656
|
+
app: workflowStringInput(plan.inputs.app),
|
|
5657
|
+
module: workflowStringInput(plan.inputs.module),
|
|
5658
|
+
field: workflowStringInput(plan.inputs.field),
|
|
5659
|
+
values: workflowStringListInput(plan.inputs.values),
|
|
5660
|
+
defaultValue: workflowStringInput(plan.inputs.default)
|
|
5661
|
+
})),
|
|
5662
|
+
[workflowStepKey("add-enum-field", "update-dictionary")]: inspect,
|
|
5663
|
+
[workflowStepKey("add-enum-field", "update-option")]: inspect
|
|
5664
|
+
};
|
|
5665
|
+
};
|
|
5666
|
+
class WorkflowExecutor {
|
|
5667
|
+
registry;
|
|
5668
|
+
constructor(registry) {
|
|
5669
|
+
this.registry = registry;
|
|
5670
|
+
}
|
|
5671
|
+
async apply(plan) {
|
|
5672
|
+
const changedFiles = [];
|
|
5673
|
+
const generatedFiles = [];
|
|
5674
|
+
const recommendedValidationCommands = [];
|
|
5675
|
+
const diagnostics = [...plan.diagnostics];
|
|
5676
|
+
const recommendations = [...plan.recommendations];
|
|
5677
|
+
const nextActions = [];
|
|
5678
|
+
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
5679
|
+
return createWorkflowApplyReport({
|
|
5680
|
+
workflow: plan.workflow,
|
|
5681
|
+
mode: "apply",
|
|
5682
|
+
changedFiles,
|
|
5683
|
+
generatedFiles,
|
|
5684
|
+
recommendedValidationCommands,
|
|
5685
|
+
diagnostics,
|
|
5686
|
+
recommendations,
|
|
5687
|
+
nextActions,
|
|
5688
|
+
plan
|
|
5689
|
+
});
|
|
5690
|
+
}
|
|
5691
|
+
recommendedValidationCommands.push(...workflowCommandsForPlan(plan));
|
|
5692
|
+
nextActions.push(...workflowCommandsForPlan(plan));
|
|
5693
|
+
for (const step of plan.steps) {
|
|
5694
|
+
const runner = this.registry[workflowStepKey(plan.workflow, step.id)] ?? this.registry[step.tool] ?? this.registry[step.id];
|
|
5695
|
+
if (!runner) {
|
|
5696
|
+
diagnostics.push({
|
|
5697
|
+
severity: "error",
|
|
5698
|
+
code: "workflow-step-unsupported",
|
|
5699
|
+
message: `Workflow ${plan.workflow} step "${step.id}" is not supported by workflow apply yet.`
|
|
5700
|
+
});
|
|
5701
|
+
nextActions.push({
|
|
5702
|
+
command: `akan workflow explain ${plan.workflow}`,
|
|
5703
|
+
reason: "Review the unsupported workflow step before retrying apply."
|
|
5704
|
+
});
|
|
5705
|
+
break;
|
|
5706
|
+
}
|
|
5707
|
+
const result = await runner(step, plan);
|
|
5708
|
+
if (!result)
|
|
5709
|
+
continue;
|
|
5710
|
+
changedFiles.push(...result.changedFiles ?? []);
|
|
5711
|
+
generatedFiles.push(...result.generatedFiles ?? []);
|
|
5712
|
+
recommendedValidationCommands.push(...result.commands ?? []);
|
|
5713
|
+
diagnostics.push(...result.diagnostics ?? []);
|
|
5714
|
+
recommendations.push(...result.recommendations ?? []);
|
|
5715
|
+
nextActions.push(...result.nextActions ?? []);
|
|
5716
|
+
if (diagnostics.some((diagnostic) => diagnostic.severity === "error"))
|
|
5717
|
+
break;
|
|
5718
|
+
}
|
|
5719
|
+
return createWorkflowApplyReport({
|
|
5720
|
+
workflow: plan.workflow,
|
|
5721
|
+
mode: "apply",
|
|
5722
|
+
changedFiles,
|
|
5723
|
+
generatedFiles,
|
|
5724
|
+
recommendedValidationCommands,
|
|
5725
|
+
diagnostics,
|
|
5726
|
+
recommendations,
|
|
5727
|
+
nextActions,
|
|
5728
|
+
plan
|
|
5729
|
+
});
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5486
5732
|
// pkgs/@akanjs/devkit/workflow/plan.ts
|
|
5733
|
+
import { capitalize as capitalize3 } from "akanjs/common";
|
|
5487
5734
|
var surfaceModes = new Set(["infer", "include", "skip"]);
|
|
5488
5735
|
var parseStringList = (value) => {
|
|
5489
5736
|
if (Array.isArray(value)) {
|
|
@@ -5501,6 +5748,18 @@ var normalizeInputValue = (name, spec, value) => {
|
|
|
5501
5748
|
const values = parseStringList(value);
|
|
5502
5749
|
return values && values.length > 0 ? values : null;
|
|
5503
5750
|
}
|
|
5751
|
+
if (spec.type === "boolean") {
|
|
5752
|
+
if (typeof value === "boolean")
|
|
5753
|
+
return value;
|
|
5754
|
+
if (typeof value !== "string")
|
|
5755
|
+
return null;
|
|
5756
|
+
const lowered = value.trim().toLowerCase();
|
|
5757
|
+
if (lowered === "true")
|
|
5758
|
+
return true;
|
|
5759
|
+
if (lowered === "false")
|
|
5760
|
+
return false;
|
|
5761
|
+
return null;
|
|
5762
|
+
}
|
|
5504
5763
|
if (typeof value === "string" && surfaceModes.has(value))
|
|
5505
5764
|
return value;
|
|
5506
5765
|
throw new Error(`Unsupported workflow input value for ${name}`);
|
|
@@ -5508,17 +5767,45 @@ var normalizeInputValue = (name, spec, value) => {
|
|
|
5508
5767
|
var listWorkflowSpecs = (specs) => [...specs].sort((a, b) => a.name.localeCompare(b.name));
|
|
5509
5768
|
var getWorkflowSpec = (specs, name) => specs.find((spec) => spec.name === name) ?? null;
|
|
5510
5769
|
var compactWorkflowInputs = (inputs) => Object.fromEntries(Object.entries(inputs).filter(([, value]) => value !== null && value !== ""));
|
|
5511
|
-
var
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5770
|
+
var addFieldTargetRoot = (app) => app ? `apps/${app}` : "*";
|
|
5771
|
+
var addFieldPaths = (inputs) => {
|
|
5772
|
+
const app = typeof inputs.app === "string" ? inputs.app : null;
|
|
5773
|
+
const module = typeof inputs.module === "string" ? inputs.module : "<module>";
|
|
5774
|
+
const paths = moduleSourcePaths(module);
|
|
5775
|
+
const root = addFieldTargetRoot(app);
|
|
5776
|
+
return {
|
|
5777
|
+
constant: `${root}/${paths.constant}`,
|
|
5778
|
+
dictionary: `${root}/${paths.dictionary}`,
|
|
5779
|
+
template: `${root}/${paths.template}`,
|
|
5780
|
+
unit: `${root}/${paths.unit}`,
|
|
5781
|
+
view: `${root}/${paths.view}`
|
|
5782
|
+
};
|
|
5783
|
+
};
|
|
5784
|
+
var selectedAddFieldSurfaces = (inputs) => Array.isArray(inputs.surfaces) ? new Set(inputs.surfaces) : null;
|
|
5785
|
+
var addFieldDefaultCoercion = (inputs) => {
|
|
5786
|
+
const typeName = typeof inputs.type === "string" ? inputs.type : null;
|
|
5787
|
+
const defaultValue = typeof inputs.default === "string" ? inputs.default : null;
|
|
5788
|
+
if (!typeName || defaultValue === null)
|
|
5789
|
+
return null;
|
|
5790
|
+
if (typeName.toLowerCase() === "number" || typeName.toLowerCase() === "numeric")
|
|
5791
|
+
return null;
|
|
5792
|
+
const enumValues = Array.isArray(inputs.values) ? inputs.values : null;
|
|
5793
|
+
return coerceFieldDefault(typeName.toLowerCase() === "enum" ? "enum" : typeName, defaultValue, { enumValues });
|
|
5794
|
+
};
|
|
5795
|
+
var createAddFieldDefaultRecommendations = (inputs) => {
|
|
5796
|
+
const field = typeof inputs.field === "string" ? inputs.field : "<field>";
|
|
5797
|
+
const coercion = addFieldDefaultCoercion(inputs);
|
|
5798
|
+
if (!coercion?.normalized || !coercion.expression)
|
|
5799
|
+
return [];
|
|
5800
|
+
return [
|
|
5801
|
+
{
|
|
5802
|
+
code: "add-field-default-normalized",
|
|
5803
|
+
kind: "manual-action",
|
|
5804
|
+
confidence: "high",
|
|
5805
|
+
message: `Default for ${field} will be normalized to ${coercion.normalizedType} literal ${coercion.expression}.`,
|
|
5806
|
+
action: "Review the normalized default in the apply report if this value should stay unset."
|
|
5807
|
+
}
|
|
5808
|
+
];
|
|
5522
5809
|
};
|
|
5523
5810
|
var createAddFieldRecommendations = (inputs) => {
|
|
5524
5811
|
const app = typeof inputs.app === "string" ? inputs.app : "<app-or-lib>";
|
|
@@ -5527,16 +5814,18 @@ var createAddFieldRecommendations = (inputs) => {
|
|
|
5527
5814
|
const typeName = typeof inputs.type === "string" ? inputs.type : null;
|
|
5528
5815
|
if (!typeName)
|
|
5529
5816
|
return [];
|
|
5530
|
-
const
|
|
5531
|
-
const
|
|
5532
|
-
const
|
|
5533
|
-
const
|
|
5817
|
+
const policy = addFieldUiPolicyForType(typeName);
|
|
5818
|
+
const normalizedType = policy.normalizedType;
|
|
5819
|
+
const paths = addFieldPaths(inputs);
|
|
5820
|
+
const surfaces = selectedAddFieldSurfaces(inputs);
|
|
5821
|
+
const templateRequested = surfaces?.has("template") ?? false;
|
|
5822
|
+
const includeInLight = inputs.includeInLight === true;
|
|
5534
5823
|
return [
|
|
5535
5824
|
...normalizedType === "Int" || normalizedType === "Float" ? [
|
|
5536
5825
|
{
|
|
5537
5826
|
code: "add-field-import",
|
|
5538
5827
|
kind: "import",
|
|
5539
|
-
target:
|
|
5828
|
+
target: paths.constant,
|
|
5540
5829
|
confidence: "high",
|
|
5541
5830
|
message: `Import ${normalizedType} from "akanjs/base" before writing field(${normalizedType}).`
|
|
5542
5831
|
}
|
|
@@ -5544,35 +5833,122 @@ var createAddFieldRecommendations = (inputs) => {
|
|
|
5544
5833
|
{
|
|
5545
5834
|
code: "add-field-placement-constant",
|
|
5546
5835
|
kind: "placement",
|
|
5547
|
-
target:
|
|
5836
|
+
target: paths.constant,
|
|
5548
5837
|
confidence: "high",
|
|
5549
5838
|
message: `Insert ${field}: field(${normalizedType}) in ${capitalize3(module)}Input.`
|
|
5550
5839
|
},
|
|
5551
5840
|
{
|
|
5552
5841
|
code: "add-field-placement-dictionary",
|
|
5553
5842
|
kind: "placement",
|
|
5554
|
-
target:
|
|
5843
|
+
target: paths.dictionary,
|
|
5555
5844
|
confidence: "high",
|
|
5556
5845
|
message: `Add dictionary labels for ${module}.${field}.`
|
|
5557
5846
|
},
|
|
5558
5847
|
{
|
|
5559
5848
|
code: "add-field-component",
|
|
5560
5849
|
kind: "ui-component",
|
|
5561
|
-
target:
|
|
5562
|
-
confidence:
|
|
5563
|
-
action:
|
|
5564
|
-
message:
|
|
5850
|
+
target: paths.template,
|
|
5851
|
+
confidence: policy.confidence,
|
|
5852
|
+
action: templateRequested ? `apply_workflow will try to add ${policy.component} to Template when the existing Template has a safe generated field-list pattern.` : `Recommended component is ${policy.component}. Pass surfaces=["template"] when this field should be rendered in the Template form.`,
|
|
5853
|
+
message: `Recommended UI component for ${field} (${normalizedType}): ${policy.component}.`
|
|
5565
5854
|
},
|
|
5855
|
+
...!surfaces ? [
|
|
5856
|
+
{
|
|
5857
|
+
code: "add-field-template-surface-choice",
|
|
5858
|
+
kind: "manual-action",
|
|
5859
|
+
target: paths.template,
|
|
5860
|
+
action: `Choose whether to expose ${field} in Template by passing surfaces=["template"].`,
|
|
5861
|
+
confidence: "medium",
|
|
5862
|
+
message: `Template exposure for ${module}.${field} is not selected yet.`
|
|
5863
|
+
}
|
|
5864
|
+
] : [],
|
|
5865
|
+
...!includeInLight ? [
|
|
5866
|
+
{
|
|
5867
|
+
code: "add-field-light-projection-choice",
|
|
5868
|
+
kind: "manual-action",
|
|
5869
|
+
target: paths.constant,
|
|
5870
|
+
action: `Pass includeInLight=true when ${field} should appear in Light${capitalize3(module)} list/card projections.`,
|
|
5871
|
+
confidence: "medium",
|
|
5872
|
+
message: `Light projection exposure for ${module}.${field} is not selected yet.`
|
|
5873
|
+
}
|
|
5874
|
+
] : [],
|
|
5875
|
+
...includeInLight ? [
|
|
5876
|
+
{
|
|
5877
|
+
code: "add-field-light-projection",
|
|
5878
|
+
kind: "placement",
|
|
5879
|
+
target: paths.constant,
|
|
5880
|
+
confidence: "high",
|
|
5881
|
+
message: `Add ${field} to Light${capitalize3(module)} projection fields.`
|
|
5882
|
+
}
|
|
5883
|
+
] : [],
|
|
5884
|
+
...surfaces && !templateRequested ? [
|
|
5885
|
+
{
|
|
5886
|
+
code: "add-field-ui-surface-skip",
|
|
5887
|
+
kind: "manual-action",
|
|
5888
|
+
target: paths.template,
|
|
5889
|
+
confidence: "medium",
|
|
5890
|
+
message: `Template is not included in surfaces, so ${module}.${field} will not be auto-rendered there.`
|
|
5891
|
+
}
|
|
5892
|
+
] : [],
|
|
5566
5893
|
{
|
|
5567
5894
|
code: "add-field-ui-manual-review",
|
|
5568
5895
|
kind: "manual-action",
|
|
5569
|
-
target:
|
|
5570
|
-
action: `Review ${app}:${module} Template
|
|
5896
|
+
target: paths.template,
|
|
5897
|
+
action: `Review ${app}:${module} UI after apply. Template auto-edit requires a generated ${module}Form hook and Layout.Template field list; Unit/View are not auto-edited because list/card placement depends on local layout. Candidate positions: Layout.Template before the closing tag, Light${capitalize3(module)} projection array for list data, and Unit/View card sections for display.`,
|
|
5571
5898
|
confidence: "medium",
|
|
5572
|
-
message:
|
|
5899
|
+
message: "UI manual review includes the reason auto-edit may be skipped and candidate insertion positions."
|
|
5900
|
+
},
|
|
5901
|
+
...createAddFieldDefaultRecommendations(inputs)
|
|
5902
|
+
];
|
|
5903
|
+
};
|
|
5904
|
+
var createWorkflowPlanPredictedChanges = (spec, inputs) => {
|
|
5905
|
+
if (spec.name !== "add-field")
|
|
5906
|
+
return spec.predictedChanges;
|
|
5907
|
+
const paths = addFieldPaths(inputs);
|
|
5908
|
+
const surfaces = selectedAddFieldSurfaces(inputs);
|
|
5909
|
+
const includeInLight = inputs.includeInLight === true;
|
|
5910
|
+
return [
|
|
5911
|
+
{
|
|
5912
|
+
target: paths.constant,
|
|
5913
|
+
action: "modify",
|
|
5914
|
+
applyScope: "auto",
|
|
5915
|
+
reason: includeInLight ? "Field shape and Light projection are added." : "Field shape is added."
|
|
5916
|
+
},
|
|
5917
|
+
{
|
|
5918
|
+
target: paths.dictionary,
|
|
5919
|
+
action: "modify",
|
|
5920
|
+
applyScope: "auto",
|
|
5921
|
+
reason: "Field label is added."
|
|
5922
|
+
},
|
|
5923
|
+
...!surfaces || surfaces.has("template") ? [
|
|
5924
|
+
{
|
|
5925
|
+
target: paths.template,
|
|
5926
|
+
action: "modify",
|
|
5927
|
+
applyScope: surfaces?.has("template") ? "auto" : "manual-review",
|
|
5928
|
+
reason: surfaces?.has("template") ? "Template form is selected for safe-pattern auto insertion." : "Form surface may include the field."
|
|
5929
|
+
}
|
|
5930
|
+
] : [],
|
|
5931
|
+
{
|
|
5932
|
+
target: `${addFieldTargetRoot(typeof inputs.app === "string" ? inputs.app : null)}/lib/cnst.ts`,
|
|
5933
|
+
action: "sync",
|
|
5934
|
+
applyScope: "generated-sync",
|
|
5935
|
+
reason: "Generated constants may change after sync."
|
|
5936
|
+
},
|
|
5937
|
+
{
|
|
5938
|
+
target: `${addFieldTargetRoot(typeof inputs.app === "string" ? inputs.app : null)}/lib/dict.ts`,
|
|
5939
|
+
action: "sync",
|
|
5940
|
+
applyScope: "generated-sync",
|
|
5941
|
+
reason: "Generated dictionary barrel may change after sync."
|
|
5573
5942
|
}
|
|
5574
5943
|
];
|
|
5575
5944
|
};
|
|
5945
|
+
var createWorkflowPlanOptionalSurfaces = (spec, inputs) => {
|
|
5946
|
+
const optionalSurfaces = spec.optionalSurfaces ?? {};
|
|
5947
|
+
const surfaces = selectedAddFieldSurfaces(inputs);
|
|
5948
|
+
if (spec.name !== "add-field" || !surfaces)
|
|
5949
|
+
return optionalSurfaces;
|
|
5950
|
+
return Object.fromEntries(Object.entries(optionalSurfaces).map(([surface, mode]) => [surface, surfaces.has(surface) ? "include" : mode]));
|
|
5951
|
+
};
|
|
5576
5952
|
var createWorkflowPlanRecommendations = (spec, inputs) => [
|
|
5577
5953
|
{
|
|
5578
5954
|
code: "workflow-apply-first",
|
|
@@ -5636,14 +6012,32 @@ var createWorkflowPlan = (spec, rawInputs) => {
|
|
|
5636
6012
|
message: `Field type "${fieldType}" is ambiguous in Akan. Use Int for integer fields or Float for decimal fields.`
|
|
5637
6013
|
});
|
|
5638
6014
|
}
|
|
6015
|
+
if (spec.name === "add-field") {
|
|
6016
|
+
const defaultCoercion = addFieldDefaultCoercion(inputs);
|
|
6017
|
+
if (defaultCoercion?.diagnostic) {
|
|
6018
|
+
diagnostics.push({
|
|
6019
|
+
...defaultCoercion.diagnostic,
|
|
6020
|
+
code: "workflow-default-value-invalid",
|
|
6021
|
+
message: `Plan input default is not valid for ${defaultCoercion.normalizedType}: ${defaultCoercion.diagnostic.message}`
|
|
6022
|
+
});
|
|
6023
|
+
} else if (defaultCoercion?.normalized && defaultCoercion.expression) {
|
|
6024
|
+
diagnostics.push({
|
|
6025
|
+
severity: "warning",
|
|
6026
|
+
code: "workflow-default-value-normalized",
|
|
6027
|
+
input: "default",
|
|
6028
|
+
failureScope: "source-change",
|
|
6029
|
+
message: `Plan input default will be written as ${defaultCoercion.normalizedType} literal ${defaultCoercion.expression}.`
|
|
6030
|
+
});
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
5639
6033
|
return {
|
|
5640
6034
|
schemaVersion: 1,
|
|
5641
6035
|
workflow: spec.name,
|
|
5642
6036
|
mode: "plan",
|
|
5643
6037
|
inputs,
|
|
5644
|
-
optionalSurfaces: spec
|
|
6038
|
+
optionalSurfaces: createWorkflowPlanOptionalSurfaces(spec, inputs),
|
|
5645
6039
|
steps: spec.steps,
|
|
5646
|
-
predictedChanges: spec
|
|
6040
|
+
predictedChanges: createWorkflowPlanPredictedChanges(spec, inputs),
|
|
5647
6041
|
validation: spec.validation,
|
|
5648
6042
|
diagnostics,
|
|
5649
6043
|
recommendations: createWorkflowPlanRecommendations(spec, inputs),
|
|
@@ -5712,35 +6106,55 @@ var renderWorkflowPlan = (plan) => [
|
|
|
5712
6106
|
""
|
|
5713
6107
|
].join(`
|
|
5714
6108
|
`);
|
|
5715
|
-
var
|
|
5716
|
-
|
|
5717
|
-
""
|
|
5718
|
-
`-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
""
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
6109
|
+
var renderRecommendation = (recommendation) => {
|
|
6110
|
+
const target = recommendation.target ? ` ${recommendation.target}` : "";
|
|
6111
|
+
const action = recommendation.action ? ` Action: ${recommendation.action}` : "";
|
|
6112
|
+
return `- [${recommendation.kind}]${target} ${recommendation.message}${action}`;
|
|
6113
|
+
};
|
|
6114
|
+
var renderDiagnostic = (diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`;
|
|
6115
|
+
var renderWorkflowApplyReport = (report) => {
|
|
6116
|
+
const manualReviewItems = [
|
|
6117
|
+
...report.diagnostics.filter((diagnostic) => diagnostic.severity === "warning").map(renderDiagnostic),
|
|
6118
|
+
...report.recommendations.filter((recommendation) => recommendation.kind === "manual-action").map(renderRecommendation)
|
|
6119
|
+
];
|
|
6120
|
+
const validationBlockers = report.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "workspace-config" || diagnostic.failureScope === "environment")).map(renderDiagnostic);
|
|
6121
|
+
return [
|
|
6122
|
+
`# Workflow Apply: ${report.workflow}`,
|
|
6123
|
+
"",
|
|
6124
|
+
`- Mode: ${report.mode}`,
|
|
6125
|
+
`- Status: ${report.status}`,
|
|
6126
|
+
...report.validationTarget ? [`- Validation target: ${report.validationTarget}`] : [],
|
|
6127
|
+
"",
|
|
6128
|
+
"## Automatically Modified",
|
|
6129
|
+
...report.changedFiles.length ? report.changedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
|
|
6130
|
+
"",
|
|
6131
|
+
"## Generated Sync",
|
|
6132
|
+
...report.generatedFiles.length ? report.generatedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
|
|
6133
|
+
"",
|
|
6134
|
+
"## Applied Commands",
|
|
6135
|
+
...report.appliedCommands.length ? report.appliedCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
|
|
6136
|
+
"",
|
|
6137
|
+
"## Recommended Validation Commands",
|
|
6138
|
+
...report.recommendedValidationCommands.length ? report.recommendedValidationCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
|
|
6139
|
+
"",
|
|
6140
|
+
"## User Review Required",
|
|
6141
|
+
...manualReviewItems.length ? manualReviewItems : ["- none"],
|
|
6142
|
+
"",
|
|
6143
|
+
"## Validation Blockers",
|
|
6144
|
+
...validationBlockers.length ? validationBlockers : report.recommendedValidationCommands.length ? ["- none detected during apply; run validation with the validation target for command-level blockers."] : ["- none"],
|
|
6145
|
+
"",
|
|
6146
|
+
"## Diagnostics",
|
|
6147
|
+
...report.diagnostics.length ? report.diagnostics.map(renderDiagnostic) : ["- none"],
|
|
6148
|
+
"",
|
|
6149
|
+
"## Recommendations",
|
|
6150
|
+
...report.recommendations.length ? report.recommendations.map(renderRecommendation) : ["- none"],
|
|
6151
|
+
"",
|
|
6152
|
+
"## Next Actions",
|
|
6153
|
+
...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
|
|
6154
|
+
""
|
|
6155
|
+
].join(`
|
|
5743
6156
|
`);
|
|
6157
|
+
};
|
|
5744
6158
|
var renderWorkflowApply = (report, format = "markdown") => format === "json" ? jsonText(report) : renderWorkflowApplyReport(report);
|
|
5745
6159
|
var renderWorkflowValidationRunReport = (report) => [
|
|
5746
6160
|
`# Workflow Validation: ${report.workflow}`,
|
|
@@ -5751,11 +6165,18 @@ var renderWorkflowValidationRunReport = (report) => [
|
|
|
5751
6165
|
`- Workspace status: ${report.workspaceStatus}`,
|
|
5752
6166
|
`- Overall status: ${report.overallStatus}`,
|
|
5753
6167
|
"",
|
|
6168
|
+
"## Status Summary",
|
|
6169
|
+
`- Required source-change validation: ${report.summary.sourceChange}`,
|
|
6170
|
+
`- Generated sync validation: ${report.summary.generatedSync}`,
|
|
6171
|
+
`- Workspace configuration validation: ${report.summary.workspaceConfig}`,
|
|
6172
|
+
`- Environment validation: ${report.summary.environment}`,
|
|
6173
|
+
"",
|
|
5754
6174
|
"## Known Blockers",
|
|
5755
6175
|
...report.knownBlockers.length ? report.knownBlockers.map((blocker) => {
|
|
5756
6176
|
const command = blocker.command ? ` \`${blocker.command}\`` : "";
|
|
5757
6177
|
const count = blocker.count > 1 ? ` (${blocker.count}x)` : "";
|
|
5758
|
-
|
|
6178
|
+
const known = blocker.known ? " known" : "";
|
|
6179
|
+
return `- [${blocker.failureScope}${known}]${command}${count}: ${blocker.message}`;
|
|
5759
6180
|
}) : ["- none"],
|
|
5760
6181
|
"",
|
|
5761
6182
|
"## Commands",
|
|
@@ -12663,6 +13084,8 @@ var NODE_NATIVE_MODULE_SET = new Set([
|
|
|
12663
13084
|
]);
|
|
12664
13085
|
// pkgs/@akanjs/devkit/getCredentials.ts
|
|
12665
13086
|
import yaml from "js-yaml";
|
|
13087
|
+
// pkgs/@akanjs/devkit/getModelFileData.ts
|
|
13088
|
+
import { capitalize as capitalize8 } from "akanjs/common";
|
|
12666
13089
|
// pkgs/@akanjs/devkit/getRelatedCnsts.ts
|
|
12667
13090
|
import { readFileSync as readFileSync4, realpathSync } from "fs";
|
|
12668
13091
|
import ora2 from "ora";
|