@akanjs/cli 2.3.9-rc.3 → 2.3.9-rc.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.
@@ -4778,238 +4778,11 @@ class AkanAppHost {
4778
4778
  // pkgs/@akanjs/devkit/akanContext.ts
4779
4779
  import { readdir } from "fs/promises";
4780
4780
  import path10 from "path";
4781
- import { capitalize as capitalize3 } from "akanjs/common";
4781
+ import { capitalize as capitalize4 } from "akanjs/common";
4782
4782
 
4783
- // pkgs/@akanjs/devkit/workflow/index.ts
4784
- import { capitalize as capitalize2 } from "akanjs/common";
4783
+ // pkgs/@akanjs/devkit/workflow/utils.ts
4785
4784
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
4786
4785
  ` : ""}`;
4787
- var surfaceModes = new Set(["infer", "include", "skip"]);
4788
- var parseStringList = (value) => {
4789
- if (Array.isArray(value)) {
4790
- const values = value.filter((item) => typeof item === "string" && item.trim().length > 0);
4791
- return values.length === value.length ? values : null;
4792
- }
4793
- if (typeof value !== "string")
4794
- return null;
4795
- return value.split(",").map((item) => item.trim()).filter(Boolean);
4796
- };
4797
- var normalizeInputValue = (name, spec, value) => {
4798
- if (spec.type === "string")
4799
- return typeof value === "string" && value.length > 0 ? value : null;
4800
- if (spec.type === "string-list") {
4801
- const values = parseStringList(value);
4802
- return values && values.length > 0 ? values : null;
4803
- }
4804
- if (typeof value === "string" && surfaceModes.has(value))
4805
- return value;
4806
- throw new Error(`Unsupported workflow input value for ${name}`);
4807
- };
4808
- var listWorkflowSpecs = (specs) => [...specs].sort((a, b) => a.name.localeCompare(b.name));
4809
- var getWorkflowSpec = (specs, name) => specs.find((spec) => spec.name === name) ?? null;
4810
- var compactWorkflowInputs = (inputs) => Object.fromEntries(Object.entries(inputs).filter(([, value]) => value !== null && value !== ""));
4811
- var addFieldComponentForType = (typeName) => {
4812
- const normalizedType = normalizeFieldType(typeName);
4813
- if (normalizedType === "Boolean")
4814
- return "Field.ToggleSelect";
4815
- if (normalizedType === "Date")
4816
- return "Field.Date";
4817
- if (normalizedType === "Int" || normalizedType === "Float")
4818
- return "Field.ToggleSelect or Field.Text";
4819
- if (typeName.toLowerCase() === "enum")
4820
- return "Field.ToggleSelect";
4821
- return "Field.Text";
4822
- };
4823
- var createAddFieldRecommendations = (inputs) => {
4824
- const app = typeof inputs.app === "string" ? inputs.app : "<app-or-lib>";
4825
- const module = typeof inputs.module === "string" ? inputs.module : "<module>";
4826
- const field = typeof inputs.field === "string" ? inputs.field : "<field>";
4827
- const typeName = typeof inputs.type === "string" ? inputs.type : null;
4828
- if (!typeName)
4829
- return [];
4830
- const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
4831
- const constantPath = `*/lib/${module}/${module}.constant.ts`;
4832
- const dictionaryPath = `*/lib/${module}/${module}.dictionary.ts`;
4833
- const templatePath = `*/lib/${module}/${capitalize2(module)}.Template.tsx`;
4834
- return [
4835
- ...normalizedType === "Int" || normalizedType === "Float" ? [
4836
- {
4837
- code: "add-field-import",
4838
- kind: "import",
4839
- target: constantPath,
4840
- confidence: "high",
4841
- message: `Import ${normalizedType} from "akanjs/base" before writing field(${normalizedType}).`
4842
- }
4843
- ] : [],
4844
- {
4845
- code: "add-field-placement-constant",
4846
- kind: "placement",
4847
- target: constantPath,
4848
- confidence: "high",
4849
- message: `Insert ${field}: field(${normalizedType}) in ${capitalize2(module)}Input.`
4850
- },
4851
- {
4852
- code: "add-field-placement-dictionary",
4853
- kind: "placement",
4854
- target: dictionaryPath,
4855
- confidence: "high",
4856
- message: `Add dictionary labels for ${module}.${field}.`
4857
- },
4858
- {
4859
- code: "add-field-component",
4860
- kind: "ui-component",
4861
- target: templatePath,
4862
- confidence: normalizedType === "Int" || normalizedType === "Float" ? "medium" : "high",
4863
- message: `Recommended UI component for ${field} (${normalizedType}): ${addFieldComponentForType(typeName)}.`
4864
- },
4865
- {
4866
- code: "add-field-ui-manual-review",
4867
- kind: "manual-action",
4868
- target: templatePath,
4869
- action: `Review ${app}:${module} Template/Unit/View/Store surfaces and add ${field} only where the existing pattern is clear.`,
4870
- confidence: "medium",
4871
- message: "UI surface edits are planned as manual-review unless a safe existing field-list pattern is detected."
4872
- }
4873
- ];
4874
- };
4875
- var createWorkflowPlanRecommendations = (spec, inputs) => [
4876
- {
4877
- code: "workflow-apply-first",
4878
- kind: "auto-apply",
4879
- confidence: "high",
4880
- action: "Call apply_workflow with the MCP planPath before editing source files directly.",
4881
- message: `Apply the ${spec.name} plan through apply_workflow when MCP returns planPath or next.tool=apply_workflow.`
4882
- },
4883
- {
4884
- code: "workflow-validate-apply-report",
4885
- kind: "validation",
4886
- confidence: "high",
4887
- action: "After apply_workflow, call run_validation with validationTarget when present; otherwise use applyReportPath.",
4888
- message: "Validate the apply report artifact so diagnostics and recommendations follow the actual apply result."
4889
- },
4890
- ...spec.name === "add-field" ? createAddFieldRecommendations(inputs) : []
4891
- ];
4892
- var createWorkflowPlan = (spec, rawInputs) => {
4893
- const inputs = {};
4894
- const diagnostics = [];
4895
- for (const [name, inputSpec] of Object.entries(spec.inputs)) {
4896
- const rawValue = rawInputs[name];
4897
- if (rawValue === undefined || rawValue === null || rawValue === "") {
4898
- if (inputSpec.required) {
4899
- diagnostics.push({
4900
- severity: "error",
4901
- code: "workflow-input-missing",
4902
- input: name,
4903
- message: `Workflow ${spec.name} requires input "${name}".`
4904
- });
4905
- }
4906
- continue;
4907
- }
4908
- const value = normalizeInputValue(name, inputSpec, rawValue);
4909
- if (value === null) {
4910
- diagnostics.push({
4911
- severity: "error",
4912
- code: "workflow-input-invalid",
4913
- input: name,
4914
- message: `Workflow ${spec.name} input "${name}" must be ${inputSpec.type}.`
4915
- });
4916
- continue;
4917
- }
4918
- if (inputSpec.allowedValues && typeof value === "string" && !inputSpec.allowedValues.includes(value)) {
4919
- diagnostics.push({
4920
- severity: "error",
4921
- code: "workflow-input-not-allowed",
4922
- input: name,
4923
- message: `Workflow ${spec.name} input "${name}" must be one of: ${inputSpec.allowedValues.join(", ")}.`
4924
- });
4925
- continue;
4926
- }
4927
- inputs[name] = value;
4928
- }
4929
- const fieldType = inputs.type;
4930
- if (spec.name === "add-field" && typeof fieldType === "string" && (fieldType.toLowerCase() === "number" || fieldType.toLowerCase() === "numeric")) {
4931
- diagnostics.push({
4932
- severity: "error",
4933
- code: "primitive-field-type-unsupported",
4934
- input: "type",
4935
- message: `Field type "${fieldType}" is ambiguous in Akan. Use Int for integer fields or Float for decimal fields.`
4936
- });
4937
- }
4938
- return {
4939
- schemaVersion: 1,
4940
- workflow: spec.name,
4941
- mode: "plan",
4942
- inputs,
4943
- optionalSurfaces: spec.optionalSurfaces ?? {},
4944
- steps: spec.steps,
4945
- predictedChanges: spec.predictedChanges,
4946
- validation: spec.validation,
4947
- diagnostics,
4948
- recommendations: createWorkflowPlanRecommendations(spec, inputs),
4949
- requiresApproval: true
4950
- };
4951
- };
4952
- var renderWorkflowList = (specs) => [
4953
- "# Akan Workflows",
4954
- "",
4955
- ...specs.flatMap((spec) => [`- \`${spec.name}\`: ${spec.description}`, ` - When: ${spec.whenToUse}`]),
4956
- ""
4957
- ].join(`
4958
- `);
4959
- var renderWorkflowExplain = (spec) => [
4960
- `# Workflow: ${spec.name}`,
4961
- "",
4962
- spec.description,
4963
- "",
4964
- "## When To Use",
4965
- spec.whenToUse,
4966
- "",
4967
- "## Inputs",
4968
- ...Object.entries(spec.inputs).map(([name, input2]) => `- \`${name}\`${input2.required ? " (required)" : ""}: ${input2.description}${input2.allowedValues ? ` Allowed: ${input2.allowedValues.join(", ")}.` : ""}`),
4969
- "",
4970
- "## Optional Surfaces",
4971
- ...Object.entries(spec.optionalSurfaces ?? {}).map(([name, mode]) => `- \`${name}\`: ${mode}`),
4972
- "",
4973
- "## Steps",
4974
- ...spec.steps.map((step, index) => `${index + 1}. \`${step.id}\` (${step.tool}): ${step.description}`),
4975
- "",
4976
- "## Validation",
4977
- ...spec.validation.map((validation) => `- \`${validation.command}\`: ${validation.reason}`),
4978
- ""
4979
- ].join(`
4980
- `);
4981
- var renderWorkflowPlan = (plan) => [
4982
- `# Workflow Plan: ${plan.workflow}`,
4983
- "",
4984
- `- Mode: ${plan.mode}`,
4985
- `- Requires approval: ${plan.requiresApproval}`,
4986
- "",
4987
- "## Inputs",
4988
- ...Object.entries(plan.inputs).map(([name, value]) => `- \`${name}\`: ${Array.isArray(value) ? value.join(", ") : value}`),
4989
- "",
4990
- "## Optional Surfaces",
4991
- ...Object.entries(plan.optionalSurfaces).map(([name, mode]) => `- \`${name}\`: ${mode}`),
4992
- "",
4993
- "## Steps",
4994
- ...plan.steps.map((step, index) => `${index + 1}. \`${step.id}\` (${step.tool}): ${step.description}`),
4995
- "",
4996
- "## Predicted Changes",
4997
- ...plan.predictedChanges.map((change) => {
4998
- const scope = change.applyScope ? ` (${change.applyScope})` : "";
4999
- return `- \`${change.action}\`${scope} ${change.target}: ${change.reason}`;
5000
- }),
5001
- "",
5002
- "## Validation",
5003
- ...plan.validation.map((validation) => `- \`${validation.command}\`: ${validation.reason}`),
5004
- "",
5005
- "## Diagnostics",
5006
- ...plan.diagnostics.length ? plan.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5007
- "",
5008
- "## Recommendations",
5009
- ...plan.recommendations.length ? plan.recommendations.map((recommendation) => `- [${recommendation.kind}] ${recommendation.message}`) : ["- none"],
5010
- ""
5011
- ].join(`
5012
- `);
5013
4786
  var workflowStatus = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.severity === "error") ? "failed" : "passed";
5014
4787
  var commandStatus = (commands) => commands.some((command) => command.status === "failed") ? "failed" : "passed";
5015
4788
  var uniqueBy = (values, key) => {
@@ -5022,6 +4795,9 @@ var uniqueBy = (values, key) => {
5022
4795
  return true;
5023
4796
  });
5024
4797
  };
4798
+ var compactDiagnostics = (diagnostics) => diagnostics.filter((diagnostic) => !!diagnostic);
4799
+
4800
+ // pkgs/@akanjs/devkit/workflow/artifacts.ts
5025
4801
  var createWorkflowApplyReport = ({
5026
4802
  workflow,
5027
4803
  mode,
@@ -5104,6 +4880,50 @@ var readWorkflowRunArtifact = async (workspace, runId) => {
5104
4880
  throw new Error(`Workflow run artifact does not exist: ${artifactPath}`);
5105
4881
  return await workspace.readJson(artifactPath);
5106
4882
  };
4883
+ var failedCommandScopes = (commands) => commands.filter((command) => command.status === "failed").map((command) => command.failureScope ?? "unknown");
4884
+ var errorDiagnosticScopes = (diagnostics) => diagnostics.filter((diagnostic) => diagnostic.severity === "error").map((diagnostic) => diagnostic.failureScope ?? (diagnostic.scope === "baseline" ? "workspace-config" : diagnostic.scope === "workflow" ? "source-change" : "unknown"));
4885
+ var hasScopeFailure = (scopes, scope, diagnostics = []) => scopes.includes(scope) || diagnostics.some((diagnostic) => diagnostic.severity === "error" && diagnostic.failureScope === scope);
4886
+ var statusForScope = (commands, diagnostics, scopes, expectedScope) => {
4887
+ const hasCommands = commands.length > 0 || diagnostics.length > 0;
4888
+ if (!hasCommands)
4889
+ return "unknown";
4890
+ return hasScopeFailure(scopes, expectedScope, diagnostics) ? "failed" : "passed";
4891
+ };
4892
+ var createKnownBlockers = (commands, diagnostics) => {
4893
+ const commandBlockers = commands.filter((command) => command.status === "failed" && (command.failureScope === "workspace-config" || command.failureScope === "environment")).map((command) => ({
4894
+ code: `workflow-validation-${command.failureScope}`,
4895
+ message: `${command.failureScope === "environment" ? "Environment" : "Workspace configuration"} blocker: ${command.command}`,
4896
+ failureScope: command.failureScope ?? "unknown",
4897
+ command: command.command,
4898
+ kind: command.kind,
4899
+ count: 1
4900
+ }));
4901
+ const diagnosticBlockers = diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "workspace-config" || diagnostic.failureScope === "environment" || diagnostic.scope === "baseline")).map((diagnostic) => ({
4902
+ code: diagnostic.code,
4903
+ message: diagnostic.message,
4904
+ failureScope: diagnostic.failureScope ?? "workspace-config",
4905
+ command: diagnostic.command,
4906
+ kind: diagnostic.kind,
4907
+ count: 1
4908
+ }));
4909
+ const grouped = new Map;
4910
+ for (const blocker of [...commandBlockers, ...diagnosticBlockers]) {
4911
+ const key = `${blocker.failureScope}:${blocker.code}:${blocker.command ?? ""}:${blocker.message}`;
4912
+ const existing = grouped.get(key);
4913
+ if (existing)
4914
+ existing.count += blocker.count;
4915
+ else
4916
+ grouped.set(key, blocker);
4917
+ }
4918
+ return [...grouped.values()];
4919
+ };
4920
+ var createValidationStatuses = (commands, diagnostics) => {
4921
+ const scopes = [...failedCommandScopes(commands), ...errorDiagnosticScopes(diagnostics)];
4922
+ const sourceStatus = statusForScope(commands, diagnostics, scopes, "source-change");
4923
+ const workspaceStatus = hasScopeFailure(scopes, "workspace-config", diagnostics) || hasScopeFailure(scopes, "environment", diagnostics) ? "failed" : commands.length || diagnostics.length ? "passed" : "unknown";
4924
+ 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 { sourceStatus, workspaceStatus, overallStatus };
4926
+ };
5107
4927
  var createWorkflowValidationRunReport = async ({
5108
4928
  runId = createWorkflowRunId("validation"),
5109
4929
  workflow,
@@ -5130,15 +4950,20 @@ var createWorkflowValidationRunReport = async ({
5130
4950
  failureScope: result.failureScope
5131
4951
  }
5132
4952
  ] : []);
4953
+ const reportDiagnostics = [...diagnostics, ...commandDiagnostics];
4954
+ const scopedDiagnostics = [...reportDiagnostics, ...baselineDiagnostics, ...workflowDiagnostics];
4955
+ const statuses = createValidationStatuses(results, scopedDiagnostics);
5133
4956
  return {
5134
4957
  schemaVersion: 1,
5135
4958
  runId,
5136
4959
  workflow,
5137
4960
  mode: "validate",
5138
4961
  source,
5139
- status: workflowStatus([...diagnostics, ...commandDiagnostics]) === "failed" ? "failed" : commandStatus(results),
4962
+ status: statuses.overallStatus === "passed" ? "passed" : "failed",
4963
+ ...statuses,
4964
+ knownBlockers: createKnownBlockers(results, scopedDiagnostics),
5140
4965
  commands: results,
5141
- diagnostics: [...diagnostics, ...commandDiagnostics],
4966
+ diagnostics: reportDiagnostics,
5142
4967
  baselineDiagnostics,
5143
4968
  workflowDiagnostics,
5144
4969
  repairActions: uniqueBy(repairActions, (action) => action.command),
@@ -5182,6 +5007,31 @@ var createDryRunWorkflowApplyReport = (plan) => {
5182
5007
  plan
5183
5008
  });
5184
5009
  };
5010
+ var createRepairReport = ({
5011
+ command,
5012
+ kind,
5013
+ target = null,
5014
+ diagnostics = [],
5015
+ repairActions = [],
5016
+ nextActions = [],
5017
+ commands = [],
5018
+ generatedFiles = [],
5019
+ syncedAt
5020
+ }) => ({
5021
+ schemaVersion: 1,
5022
+ command,
5023
+ kind,
5024
+ target,
5025
+ status: workflowStatus(diagnostics) === "failed" || commandStatus(commands) === "failed" ? "failed" : "passed",
5026
+ diagnostics,
5027
+ repairActions: uniqueBy(repairActions, (action) => action.command),
5028
+ nextActions: uniqueBy(nextActions, (action) => action.command),
5029
+ commands,
5030
+ generatedFiles,
5031
+ ...syncedAt ? { syncedAt } : {}
5032
+ });
5033
+ // pkgs/@akanjs/devkit/workflow/executor.ts
5034
+ import { capitalize as capitalize2 } from "akanjs/common";
5185
5035
  var workflowStepKey = (workflow, stepId) => `${workflow}:${stepId}`;
5186
5036
  var primitiveReportToWorkflowStepResult = (report) => ({
5187
5037
  changedFiles: report.changedFiles,
@@ -5222,19 +5072,22 @@ var unsupportedInput = (input2, message) => ({
5222
5072
  message
5223
5073
  });
5224
5074
  var addFieldUiSurfaceInspection = (plan) => {
5075
+ const app = workflowStringInput(plan.inputs.app);
5225
5076
  const module = workflowStringInput(plan.inputs.module) ?? "<module>";
5226
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";
5227
5080
  const moduleClassName = capitalize2(module);
5228
- const target = `*/lib/${module}/${moduleClassName}.Template.tsx`;
5081
+ const target = `${app ? `apps/${app}` : "*"}/lib/${module}/${moduleClassName}.Template.tsx`;
5229
5082
  return {
5230
5083
  recommendations: [
5231
5084
  {
5232
5085
  code: "add-field-ui-surface-review",
5233
5086
  kind: "manual-action",
5234
5087
  target,
5235
- action: `Add ${field} to ${moduleClassName} UI surfaces only when the local Field.* pattern is clear.`,
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.`,
5236
5089
  confidence: "medium",
5237
- message: `Review Template/Unit/View/Store surfaces for ${module}.${field}; no UI file was modified automatically.`
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.`
5238
5091
  }
5239
5092
  ],
5240
5093
  nextActions: [
@@ -5326,112 +5179,6 @@ var createWorkflowStepRegistry = ({
5326
5179
  [workflowStepKey("add-enum-field", "update-option")]: inspect
5327
5180
  };
5328
5181
  };
5329
- var renderWorkflowApplyReport = (report) => [
5330
- `# Workflow Apply: ${report.workflow}`,
5331
- "",
5332
- `- Mode: ${report.mode}`,
5333
- `- Status: ${report.status}`,
5334
- "",
5335
- "## Changed Files",
5336
- ...report.changedFiles.length ? report.changedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
5337
- "",
5338
- "## Generated Files",
5339
- ...report.generatedFiles.length ? report.generatedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
5340
- "",
5341
- "## Applied Commands",
5342
- ...report.appliedCommands.length ? report.appliedCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
5343
- "",
5344
- "## Recommended Validation Commands",
5345
- ...report.recommendedValidationCommands.length ? report.recommendedValidationCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
5346
- "",
5347
- "## Diagnostics",
5348
- ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5349
- "",
5350
- "## Recommendations",
5351
- ...report.recommendations.length ? report.recommendations.map((recommendation) => `- [${recommendation.kind}] ${recommendation.message}`) : ["- none"],
5352
- "",
5353
- "## Next Actions",
5354
- ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5355
- ""
5356
- ].join(`
5357
- `);
5358
- var renderWorkflowApply = (report, format = "markdown") => format === "json" ? jsonText(report) : renderWorkflowApplyReport(report);
5359
- var renderWorkflowValidationRunReport = (report) => [
5360
- `# Workflow Validation: ${report.workflow}`,
5361
- "",
5362
- `- Run: ${report.runId}`,
5363
- `- Status: ${report.status}`,
5364
- "",
5365
- "## Commands",
5366
- ...report.commands.length ? report.commands.map((command) => {
5367
- const scope = command.failureScope ? ` (${command.failureScope})` : "";
5368
- return `- [${command.status}] \`${command.command}\`${scope}: ${command.reason}`;
5369
- }) : ["- none"],
5370
- "",
5371
- "## Diagnostics",
5372
- ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5373
- "",
5374
- "## Repair Actions",
5375
- ...report.repairActions.length ? report.repairActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5376
- "",
5377
- "## Next Actions",
5378
- ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5379
- ""
5380
- ].join(`
5381
- `);
5382
- var renderWorkflowValidation = (report, format = "markdown") => format === "json" ? jsonText(report) : renderWorkflowValidationRunReport(report);
5383
- var renderWorkflowRunArtifact = (artifact, format = "markdown") => {
5384
- if ("kind" in artifact)
5385
- return renderRepairReport(artifact, format);
5386
- if ("mode" in artifact && artifact.mode === "validate")
5387
- return renderWorkflowValidation(artifact, format);
5388
- if ("mode" in artifact && (artifact.mode === "apply" || artifact.mode === "dry-run")) {
5389
- return renderWorkflowApply(artifact, format);
5390
- }
5391
- return jsonText(artifact);
5392
- };
5393
- var createRepairReport = ({
5394
- command,
5395
- kind,
5396
- target = null,
5397
- diagnostics = [],
5398
- repairActions = [],
5399
- nextActions = [],
5400
- commands = [],
5401
- generatedFiles = [],
5402
- syncedAt
5403
- }) => ({
5404
- schemaVersion: 1,
5405
- command,
5406
- kind,
5407
- target,
5408
- status: workflowStatus(diagnostics) === "failed" || commandStatus(commands) === "failed" ? "failed" : "passed",
5409
- diagnostics,
5410
- repairActions: uniqueBy(repairActions, (action) => action.command),
5411
- nextActions: uniqueBy(nextActions, (action) => action.command),
5412
- commands,
5413
- generatedFiles,
5414
- ...syncedAt ? { syncedAt } : {}
5415
- });
5416
- var renderRepairReportMarkdown = (report) => [
5417
- `# Akan Repair: ${report.kind}`,
5418
- "",
5419
- `- Status: ${report.status}`,
5420
- `- Target: ${report.target ?? "none"}`,
5421
- "",
5422
- "## Commands",
5423
- ...report.commands.length ? report.commands.map((command) => `- [${command.status}] \`${command.command}\`: ${command.reason}`) : ["- none"],
5424
- "",
5425
- "## Diagnostics",
5426
- ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5427
- "",
5428
- "## Next Actions",
5429
- ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5430
- ""
5431
- ].join(`
5432
- `);
5433
- var renderRepairReport = (report, format = "markdown") => format === "json" ? jsonText(report) : renderRepairReportMarkdown(report);
5434
-
5435
5182
  class WorkflowExecutor {
5436
5183
  registry;
5437
5184
  constructor(registry) {
@@ -5498,6 +5245,10 @@ class WorkflowExecutor {
5498
5245
  });
5499
5246
  }
5500
5247
  }
5248
+ // pkgs/@akanjs/devkit/workflow/plan.ts
5249
+ import { capitalize as capitalize3 } from "akanjs/common";
5250
+
5251
+ // pkgs/@akanjs/devkit/workflow/primitive.ts
5501
5252
  var createPrimitiveWriteReport = ({
5502
5253
  command,
5503
5254
  status,
@@ -5539,6 +5290,8 @@ var renderPrimitiveWriteReport = (report) => [
5539
5290
  ].join(`
5540
5291
  `);
5541
5292
  var renderPrimitiveReport = (report, format = "markdown") => format === "json" ? jsonText(report) : renderPrimitiveWriteReport(report);
5293
+
5294
+ // pkgs/@akanjs/devkit/workflow/source.ts
5542
5295
  var getSysRoot = (sys2) => `${sys2.type}s/${sys2.name}`;
5543
5296
  var sourceFile = (sys2, path10, action, reason) => ({
5544
5297
  path: `${getSysRoot(sys2)}/${path10}`,
@@ -5571,7 +5324,6 @@ var createPassedPrimitiveReport = ({
5571
5324
  var scalarChangedFiles = (sys2, scalarName, files) => Object.values(files).map((file) => sourceFile(sys2, `lib/__scalar/${scalarName}/${file.filename}`, "create", "Scalar source file was created."));
5572
5325
  var titleize = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
5573
5326
  var lowerlize = (value) => `${value.slice(0, 1).toLowerCase()}${value.slice(1)}`;
5574
- var compactDiagnostics = (diagnostics) => diagnostics.filter((diagnostic) => !!diagnostic);
5575
5327
  var normalizeFieldType = (typeName) => {
5576
5328
  const normalizedTypes = {
5577
5329
  string: "String",
@@ -5598,9 +5350,54 @@ var ensureBaseTypeImport = (content, typeName) => {
5598
5350
  return `import { ${typeName} } from "akanjs/base";
5599
5351
  ${content}`;
5600
5352
  };
5353
+ var numericDefault = (typeName, rawDefault) => {
5354
+ const trimmed = rawDefault.trim();
5355
+ if (!trimmed || !Number.isFinite(Number(trimmed)))
5356
+ return null;
5357
+ if (typeName === "Int" && !/^-?\d+$/.test(trimmed))
5358
+ return null;
5359
+ return trimmed;
5360
+ };
5361
+ var coerceFieldDefault = (typeName, defaultValue) => {
5362
+ if (defaultValue === undefined || defaultValue === null || defaultValue === "")
5363
+ return { expression: null };
5364
+ const normalizedType = normalizeFieldType(typeName);
5365
+ if (normalizedType === "Int" || normalizedType === "Float") {
5366
+ const expression = numericDefault(normalizedType, defaultValue);
5367
+ if (expression !== null)
5368
+ return { expression };
5369
+ return {
5370
+ expression: null,
5371
+ diagnostic: {
5372
+ severity: "error",
5373
+ code: "primitive-default-value-invalid",
5374
+ input: "default",
5375
+ failureScope: "source-change",
5376
+ message: `Default value for ${normalizedType} must be a numeric literal. Received: ${JSON.stringify(defaultValue)}.`
5377
+ }
5378
+ };
5379
+ }
5380
+ if (normalizedType === "Boolean") {
5381
+ const lowered = defaultValue.trim().toLowerCase();
5382
+ if (lowered === "true" || lowered === "false")
5383
+ return { expression: lowered };
5384
+ return {
5385
+ expression: null,
5386
+ diagnostic: {
5387
+ severity: "error",
5388
+ code: "primitive-default-value-invalid",
5389
+ input: "default",
5390
+ failureScope: "source-change",
5391
+ message: `Default value for Boolean must be true or false. Received: ${JSON.stringify(defaultValue)}.`
5392
+ }
5393
+ };
5394
+ }
5395
+ return { expression: JSON.stringify(defaultValue) };
5396
+ };
5601
5397
  var fieldExpression = (typeName, defaultValue) => {
5602
5398
  const typeExpression = normalizeFieldType(typeName);
5603
- const defaultOption = defaultValue ? `, { default: ${JSON.stringify(defaultValue)} }` : "";
5399
+ const defaultExpression = coerceFieldDefault(typeExpression, defaultValue).expression;
5400
+ const defaultOption = defaultExpression ? `, { default: ${defaultExpression} }` : "";
5604
5401
  return `field(${typeExpression}${defaultOption})`;
5605
5402
  };
5606
5403
  var insertIntoObject = (content, className, line) => {
@@ -5686,6 +5483,327 @@ ${values.map((value) => ` ${value}: t([${JSON.stringify(titleize(value))}, ${
5686
5483
  };
5687
5484
  var parseValues = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
5688
5485
 
5486
+ // pkgs/@akanjs/devkit/workflow/plan.ts
5487
+ var surfaceModes = new Set(["infer", "include", "skip"]);
5488
+ var parseStringList = (value) => {
5489
+ if (Array.isArray(value)) {
5490
+ const values = value.filter((item) => typeof item === "string" && item.trim().length > 0);
5491
+ return values.length === value.length ? values : null;
5492
+ }
5493
+ if (typeof value !== "string")
5494
+ return null;
5495
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
5496
+ };
5497
+ var normalizeInputValue = (name, spec, value) => {
5498
+ if (spec.type === "string")
5499
+ return typeof value === "string" && value.length > 0 ? value : null;
5500
+ if (spec.type === "string-list") {
5501
+ const values = parseStringList(value);
5502
+ return values && values.length > 0 ? values : null;
5503
+ }
5504
+ if (typeof value === "string" && surfaceModes.has(value))
5505
+ return value;
5506
+ throw new Error(`Unsupported workflow input value for ${name}`);
5507
+ };
5508
+ var listWorkflowSpecs = (specs) => [...specs].sort((a, b) => a.name.localeCompare(b.name));
5509
+ var getWorkflowSpec = (specs, name) => specs.find((spec) => spec.name === name) ?? null;
5510
+ var compactWorkflowInputs = (inputs) => Object.fromEntries(Object.entries(inputs).filter(([, value]) => value !== null && value !== ""));
5511
+ var addFieldComponentForType = (typeName) => {
5512
+ const normalizedType = normalizeFieldType(typeName);
5513
+ if (normalizedType === "Boolean")
5514
+ return "Field.ToggleSelect";
5515
+ if (normalizedType === "Date")
5516
+ return "Field.Date";
5517
+ if (normalizedType === "Int" || normalizedType === "Float")
5518
+ return "manual numeric input review";
5519
+ if (typeName.toLowerCase() === "enum")
5520
+ return "Field.ToggleSelect";
5521
+ return "Field.Text";
5522
+ };
5523
+ var createAddFieldRecommendations = (inputs) => {
5524
+ const app = typeof inputs.app === "string" ? inputs.app : "<app-or-lib>";
5525
+ const module = typeof inputs.module === "string" ? inputs.module : "<module>";
5526
+ const field = typeof inputs.field === "string" ? inputs.field : "<field>";
5527
+ const typeName = typeof inputs.type === "string" ? inputs.type : null;
5528
+ if (!typeName)
5529
+ return [];
5530
+ const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
5531
+ const constantPath = `*/lib/${module}/${module}.constant.ts`;
5532
+ const dictionaryPath = `*/lib/${module}/${module}.dictionary.ts`;
5533
+ const templatePath = `*/lib/${module}/${capitalize3(module)}.Template.tsx`;
5534
+ return [
5535
+ ...normalizedType === "Int" || normalizedType === "Float" ? [
5536
+ {
5537
+ code: "add-field-import",
5538
+ kind: "import",
5539
+ target: constantPath,
5540
+ confidence: "high",
5541
+ message: `Import ${normalizedType} from "akanjs/base" before writing field(${normalizedType}).`
5542
+ }
5543
+ ] : [],
5544
+ {
5545
+ code: "add-field-placement-constant",
5546
+ kind: "placement",
5547
+ target: constantPath,
5548
+ confidence: "high",
5549
+ message: `Insert ${field}: field(${normalizedType}) in ${capitalize3(module)}Input.`
5550
+ },
5551
+ {
5552
+ code: "add-field-placement-dictionary",
5553
+ kind: "placement",
5554
+ target: dictionaryPath,
5555
+ confidence: "high",
5556
+ message: `Add dictionary labels for ${module}.${field}.`
5557
+ },
5558
+ {
5559
+ code: "add-field-component",
5560
+ kind: "ui-component",
5561
+ target: templatePath,
5562
+ confidence: normalizedType === "Int" || normalizedType === "Float" ? "low" : "high",
5563
+ action: normalizedType === "Int" || normalizedType === "Float" ? "Do not auto-edit UI. Check local Template/Unit/View patterns for Field.Text parsing, formatting, validation rules, and dictionary labels before adding a numeric input." : undefined,
5564
+ message: normalizedType === "Int" || normalizedType === "Float" ? `Numeric UI for ${field} (${normalizedType}) requires manual review; a safe numeric input component pattern is not yet detected.` : `Recommended UI component for ${field} (${normalizedType}): ${addFieldComponentForType(typeName)}.`
5565
+ },
5566
+ {
5567
+ code: "add-field-ui-manual-review",
5568
+ kind: "manual-action",
5569
+ target: templatePath,
5570
+ action: `Review ${app}:${module} Template/Unit/View/Store surfaces and add ${field} only where the existing pattern is clear. For numeric fields, confirm parser/formatter behavior and validation before using Field.Text.`,
5571
+ confidence: "medium",
5572
+ message: normalizedType === "Int" || normalizedType === "Float" ? "UI surface edits stay manual because a safe numeric input component pattern is not yet detected." : "UI surface edits are planned as manual-review unless a safe existing field-list pattern is detected."
5573
+ }
5574
+ ];
5575
+ };
5576
+ var createWorkflowPlanRecommendations = (spec, inputs) => [
5577
+ {
5578
+ code: "workflow-apply-first",
5579
+ kind: "auto-apply",
5580
+ confidence: "high",
5581
+ action: "Call apply_workflow with the MCP planPath before editing source files directly.",
5582
+ message: `Apply the ${spec.name} plan through apply_workflow when MCP returns planPath or next.tool=apply_workflow.`
5583
+ },
5584
+ {
5585
+ code: "workflow-validate-apply-report",
5586
+ kind: "validation",
5587
+ confidence: "high",
5588
+ action: "After apply_workflow, call run_validation with validationTarget when present; otherwise use applyReportPath.",
5589
+ message: "Validate the apply report artifact so diagnostics and recommendations follow the actual apply result."
5590
+ },
5591
+ ...spec.name === "add-field" ? createAddFieldRecommendations(inputs) : []
5592
+ ];
5593
+ var createWorkflowPlan = (spec, rawInputs) => {
5594
+ const inputs = {};
5595
+ const diagnostics = [];
5596
+ for (const [name, inputSpec] of Object.entries(spec.inputs)) {
5597
+ const rawValue = rawInputs[name];
5598
+ if (rawValue === undefined || rawValue === null || rawValue === "") {
5599
+ if (inputSpec.required) {
5600
+ diagnostics.push({
5601
+ severity: "error",
5602
+ code: "workflow-input-missing",
5603
+ input: name,
5604
+ message: `Workflow ${spec.name} requires input "${name}".`
5605
+ });
5606
+ }
5607
+ continue;
5608
+ }
5609
+ const value = normalizeInputValue(name, inputSpec, rawValue);
5610
+ if (value === null) {
5611
+ diagnostics.push({
5612
+ severity: "error",
5613
+ code: "workflow-input-invalid",
5614
+ input: name,
5615
+ message: `Workflow ${spec.name} input "${name}" must be ${inputSpec.type}.`
5616
+ });
5617
+ continue;
5618
+ }
5619
+ if (inputSpec.allowedValues && typeof value === "string" && !inputSpec.allowedValues.includes(value)) {
5620
+ diagnostics.push({
5621
+ severity: "error",
5622
+ code: "workflow-input-not-allowed",
5623
+ input: name,
5624
+ message: `Workflow ${spec.name} input "${name}" must be one of: ${inputSpec.allowedValues.join(", ")}.`
5625
+ });
5626
+ continue;
5627
+ }
5628
+ inputs[name] = value;
5629
+ }
5630
+ const fieldType = inputs.type;
5631
+ if (spec.name === "add-field" && typeof fieldType === "string" && (fieldType.toLowerCase() === "number" || fieldType.toLowerCase() === "numeric")) {
5632
+ diagnostics.push({
5633
+ severity: "error",
5634
+ code: "primitive-field-type-unsupported",
5635
+ input: "type",
5636
+ message: `Field type "${fieldType}" is ambiguous in Akan. Use Int for integer fields or Float for decimal fields.`
5637
+ });
5638
+ }
5639
+ return {
5640
+ schemaVersion: 1,
5641
+ workflow: spec.name,
5642
+ mode: "plan",
5643
+ inputs,
5644
+ optionalSurfaces: spec.optionalSurfaces ?? {},
5645
+ steps: spec.steps,
5646
+ predictedChanges: spec.predictedChanges,
5647
+ validation: spec.validation,
5648
+ diagnostics,
5649
+ recommendations: createWorkflowPlanRecommendations(spec, inputs),
5650
+ requiresApproval: true
5651
+ };
5652
+ };
5653
+ // pkgs/@akanjs/devkit/workflow/render.ts
5654
+ var renderWorkflowList = (specs) => [
5655
+ "# Akan Workflows",
5656
+ "",
5657
+ ...specs.flatMap((spec) => [`- \`${spec.name}\`: ${spec.description}`, ` - When: ${spec.whenToUse}`]),
5658
+ ""
5659
+ ].join(`
5660
+ `);
5661
+ var renderWorkflowExplain = (spec) => [
5662
+ `# Workflow: ${spec.name}`,
5663
+ "",
5664
+ spec.description,
5665
+ "",
5666
+ "## When To Use",
5667
+ spec.whenToUse,
5668
+ "",
5669
+ "## Inputs",
5670
+ ...Object.entries(spec.inputs).map(([name, input2]) => `- \`${name}\`${input2.required ? " (required)" : ""}: ${input2.description}${input2.allowedValues ? ` Allowed: ${input2.allowedValues.join(", ")}.` : ""}`),
5671
+ "",
5672
+ "## Optional Surfaces",
5673
+ ...Object.entries(spec.optionalSurfaces ?? {}).map(([name, mode]) => `- \`${name}\`: ${mode}`),
5674
+ "",
5675
+ "## Steps",
5676
+ ...spec.steps.map((step, index) => `${index + 1}. \`${step.id}\` (${step.tool}): ${step.description}`),
5677
+ "",
5678
+ "## Validation",
5679
+ ...spec.validation.map((validation) => `- \`${validation.command}\`: ${validation.reason}`),
5680
+ ""
5681
+ ].join(`
5682
+ `);
5683
+ var renderWorkflowPlan = (plan) => [
5684
+ `# Workflow Plan: ${plan.workflow}`,
5685
+ "",
5686
+ `- Mode: ${plan.mode}`,
5687
+ `- Requires approval: ${plan.requiresApproval}`,
5688
+ "",
5689
+ "## Inputs",
5690
+ ...Object.entries(plan.inputs).map(([name, value]) => `- \`${name}\`: ${Array.isArray(value) ? value.join(", ") : value}`),
5691
+ "",
5692
+ "## Optional Surfaces",
5693
+ ...Object.entries(plan.optionalSurfaces).map(([name, mode]) => `- \`${name}\`: ${mode}`),
5694
+ "",
5695
+ "## Steps",
5696
+ ...plan.steps.map((step, index) => `${index + 1}. \`${step.id}\` (${step.tool}): ${step.description}`),
5697
+ "",
5698
+ "## Predicted Changes",
5699
+ ...plan.predictedChanges.map((change) => {
5700
+ const scope = change.applyScope ? ` (${change.applyScope})` : "";
5701
+ return `- \`${change.action}\`${scope} ${change.target}: ${change.reason}`;
5702
+ }),
5703
+ "",
5704
+ "## Validation",
5705
+ ...plan.validation.map((validation) => `- \`${validation.command}\`: ${validation.reason}`),
5706
+ "",
5707
+ "## Diagnostics",
5708
+ ...plan.diagnostics.length ? plan.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5709
+ "",
5710
+ "## Recommendations",
5711
+ ...plan.recommendations.length ? plan.recommendations.map((recommendation) => `- [${recommendation.kind}] ${recommendation.message}`) : ["- none"],
5712
+ ""
5713
+ ].join(`
5714
+ `);
5715
+ var renderWorkflowApplyReport = (report) => [
5716
+ `# Workflow Apply: ${report.workflow}`,
5717
+ "",
5718
+ `- Mode: ${report.mode}`,
5719
+ `- Status: ${report.status}`,
5720
+ "",
5721
+ "## Changed Files",
5722
+ ...report.changedFiles.length ? report.changedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
5723
+ "",
5724
+ "## Generated Files",
5725
+ ...report.generatedFiles.length ? report.generatedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
5726
+ "",
5727
+ "## Applied Commands",
5728
+ ...report.appliedCommands.length ? report.appliedCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
5729
+ "",
5730
+ "## Recommended Validation Commands",
5731
+ ...report.recommendedValidationCommands.length ? report.recommendedValidationCommands.map((command) => `- \`${command.command}\`: ${command.reason}`) : ["- none"],
5732
+ "",
5733
+ "## Diagnostics",
5734
+ ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5735
+ "",
5736
+ "## Recommendations",
5737
+ ...report.recommendations.length ? report.recommendations.map((recommendation) => `- [${recommendation.kind}] ${recommendation.message}`) : ["- none"],
5738
+ "",
5739
+ "## Next Actions",
5740
+ ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5741
+ ""
5742
+ ].join(`
5743
+ `);
5744
+ var renderWorkflowApply = (report, format = "markdown") => format === "json" ? jsonText(report) : renderWorkflowApplyReport(report);
5745
+ var renderWorkflowValidationRunReport = (report) => [
5746
+ `# Workflow Validation: ${report.workflow}`,
5747
+ "",
5748
+ `- Run: ${report.runId}`,
5749
+ `- Status: ${report.status}`,
5750
+ `- Source status: ${report.sourceStatus}`,
5751
+ `- Workspace status: ${report.workspaceStatus}`,
5752
+ `- Overall status: ${report.overallStatus}`,
5753
+ "",
5754
+ "## Known Blockers",
5755
+ ...report.knownBlockers.length ? report.knownBlockers.map((blocker) => {
5756
+ const command = blocker.command ? ` \`${blocker.command}\`` : "";
5757
+ const count = blocker.count > 1 ? ` (${blocker.count}x)` : "";
5758
+ return `- [${blocker.failureScope}]${command}${count}: ${blocker.message}`;
5759
+ }) : ["- none"],
5760
+ "",
5761
+ "## Commands",
5762
+ ...report.commands.length ? report.commands.map((command) => {
5763
+ const scope = command.failureScope ? ` (${command.failureScope})` : "";
5764
+ return `- [${command.status}] \`${command.command}\`${scope}: ${command.reason}`;
5765
+ }) : ["- none"],
5766
+ "",
5767
+ "## Diagnostics",
5768
+ ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5769
+ "",
5770
+ "## Repair Actions",
5771
+ ...report.repairActions.length ? report.repairActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5772
+ "",
5773
+ "## Next Actions",
5774
+ ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5775
+ ""
5776
+ ].join(`
5777
+ `);
5778
+ var renderWorkflowValidation = (report, format = "markdown") => format === "json" ? jsonText(report) : renderWorkflowValidationRunReport(report);
5779
+ var renderRepairReportMarkdown = (report) => [
5780
+ `# Akan Repair: ${report.kind}`,
5781
+ "",
5782
+ `- Status: ${report.status}`,
5783
+ `- Target: ${report.target ?? "none"}`,
5784
+ "",
5785
+ "## Commands",
5786
+ ...report.commands.length ? report.commands.map((command) => `- [${command.status}] \`${command.command}\`: ${command.reason}`) : ["- none"],
5787
+ "",
5788
+ "## Diagnostics",
5789
+ ...report.diagnostics.length ? report.diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
5790
+ "",
5791
+ "## Next Actions",
5792
+ ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
5793
+ ""
5794
+ ].join(`
5795
+ `);
5796
+ var renderRepairReport = (report, format = "markdown") => format === "json" ? jsonText(report) : renderRepairReportMarkdown(report);
5797
+ var renderWorkflowRunArtifact = (artifact, format = "markdown") => {
5798
+ if ("kind" in artifact)
5799
+ return renderRepairReport(artifact, format);
5800
+ if ("mode" in artifact && artifact.mode === "validate")
5801
+ return renderWorkflowValidation(artifact, format);
5802
+ if ("mode" in artifact && (artifact.mode === "apply" || artifact.mode === "dry-run")) {
5803
+ return renderWorkflowApply(artifact, format);
5804
+ }
5805
+ return jsonText(artifact);
5806
+ };
5689
5807
  // pkgs/@akanjs/devkit/akanContext.ts
5690
5808
  var resourceList = [
5691
5809
  { uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
@@ -5821,17 +5939,17 @@ var safeReadJson = async (filePath) => {
5821
5939
  var isWorkflowPlan = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && value.mode === "plan";
5822
5940
  var isWorkflowApplyReport = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && (value.mode === "apply" || value.mode === "dry-run");
5823
5941
  var isWorkflowRunArtifact = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1;
5824
- var planInputString = (plan, key) => {
5825
- const value = plan.inputs[key];
5942
+ var planInputString = (plan2, key) => {
5943
+ const value = plan2.inputs[key];
5826
5944
  return typeof value === "string" ? value : "";
5827
5945
  };
5828
- var expandWorkflowTarget = (target, plan) => {
5829
- const app = planInputString(plan, "app");
5830
- const module = planInputString(plan, "module");
5831
- const moduleClass = module ? capitalize3(module) : "<Module>";
5946
+ var expandWorkflowTarget = (target, plan2) => {
5947
+ const app = planInputString(plan2, "app");
5948
+ const module = planInputString(plan2, "module");
5949
+ const moduleClass = module ? capitalize4(module) : "<Module>";
5832
5950
  return target.replace(/^\*\//, app ? `apps/${app}/` : "").replaceAll("<module>", module || "<module>").replaceAll("<Module>", moduleClass);
5833
5951
  };
5834
- var workflowPathsForPlan = (plan) => plan.predictedChanges.map((change) => expandWorkflowTarget(change.target, plan));
5952
+ var workflowPathsForPlan = (plan2) => plan2.predictedChanges.map((change) => expandWorkflowTarget(change.target, plan2));
5835
5953
  var workflowPathsForArtifact = (artifact) => {
5836
5954
  if (isWorkflowPlan(artifact))
5837
5955
  return workflowPathsForPlan(artifact);
@@ -6046,7 +6164,7 @@ class AkanContextAnalyzer {
6046
6164
  severity: strict ? "error" : "warning",
6047
6165
  code: "module-abstract-missing",
6048
6166
  path: module.abstract.path,
6049
- message: `${capitalize3(module.kind)} module ${sys2.name}:${module.name} should include ${module.abstract.path}`,
6167
+ message: `${capitalize4(module.kind)} module ${sys2.name}:${module.name} should include ${module.abstract.path}`,
6050
6168
  repairActions: [action]
6051
6169
  });
6052
6170
  repairActions.push(action);
@@ -6058,7 +6176,7 @@ class AkanContextAnalyzer {
6058
6176
  severity: "error",
6059
6177
  code: "module-shape-invalid",
6060
6178
  path: module.path,
6061
- message: `${capitalize3(module.kind)} module ${sys2.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`,
6179
+ message: `${capitalize4(module.kind)} module ${sys2.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`,
6062
6180
  repairActions: [action]
6063
6181
  });
6064
6182
  repairActions.push(action);
@@ -6109,8 +6227,8 @@ class AkanContextAnalyzer {
6109
6227
  ...workflowPaths.length ? { baselineDiagnostics, workflowDiagnostics } : {}
6110
6228
  };
6111
6229
  }
6112
- static findModules(context, moduleName) {
6113
- const modules = [...context.apps, ...context.libs].flatMap((sys2) => sys2.modules);
6230
+ static findModules(context, moduleName, { app = null } = {}) {
6231
+ const modules = [...context.apps, ...context.libs].filter((sys2) => !app || sys2.name === app).flatMap((sys2) => sys2.modules);
6114
6232
  return moduleName ? modules.filter((module) => module.name === moduleName || module.folderName === moduleName) : modules;
6115
6233
  }
6116
6234
  static renderMarkdown(context, { module: moduleName } = {}) {
@@ -6300,7 +6418,7 @@ void st;
6300
6418
  ` : `const UserLayout = ({ children }) => children;
6301
6419
  const userLayout = {};
6302
6420
  `;
6303
- const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
6421
+ const source2 = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
6304
6422
  import { loadFonts } from "akanjs/client";
6305
6423
  import { System } from "akanjs/ui";
6306
6424
  import { env } from "@apps/${opts.appName}/env/env.client";
@@ -6376,7 +6494,7 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
6376
6494
  return <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;
6377
6495
  }
6378
6496
  `;
6379
- await Bun.write(absPath, source);
6497
+ await Bun.write(absPath, source2);
6380
6498
  return absPath;
6381
6499
  }
6382
6500
  async function resolveSsrPageEntries(opts) {
@@ -6533,23 +6651,23 @@ class BarrelAnalyzer {
6533
6651
  if (visited.has(absFile))
6534
6652
  return;
6535
6653
  visited.add(absFile);
6536
- const source = await readIfExists(absFile);
6537
- if (source === null)
6654
+ const source2 = await readIfExists(absFile);
6655
+ if (source2 === null)
6538
6656
  return;
6539
6657
  const currentSubpath = this.#subpathFor(pkg, absFile);
6540
6658
  if (!currentSubpath)
6541
6659
  return;
6542
- const authoritative = this.#scanExports(source, absFile);
6660
+ const authoritative = this.#scanExports(source2, absFile);
6543
6661
  authoritative.delete("default");
6544
6662
  const attributed = new Set;
6545
6663
  REEXPORT_RE.lastIndex = 0;
6546
- let m = REEXPORT_RE.exec(source);
6664
+ let m = REEXPORT_RE.exec(source2);
6547
6665
  while (m !== null) {
6548
6666
  const star = m[1];
6549
6667
  const nsAs = m[2];
6550
6668
  const namedList = m[3];
6551
6669
  const spec = m[5] ?? "";
6552
- m = REEXPORT_RE.exec(source);
6670
+ m = REEXPORT_RE.exec(source2);
6553
6671
  if (!isRelative(spec))
6554
6672
  continue;
6555
6673
  if (star) {
@@ -6585,10 +6703,10 @@ class BarrelAnalyzer {
6585
6703
  }
6586
6704
  }
6587
6705
  LOCAL_NAMED_RE.lastIndex = 0;
6588
- let n = LOCAL_NAMED_RE.exec(source);
6706
+ let n = LOCAL_NAMED_RE.exec(source2);
6589
6707
  while (n !== null) {
6590
6708
  const body = n[1] ?? "";
6591
- n = LOCAL_NAMED_RE.exec(source);
6709
+ n = LOCAL_NAMED_RE.exec(source2);
6592
6710
  for (const item of parseNamedList(body)) {
6593
6711
  if (item.isType)
6594
6712
  continue;
@@ -6610,10 +6728,10 @@ class BarrelAnalyzer {
6610
6728
  map.set(name, { subpath: currentSubpath, originalName: name });
6611
6729
  }
6612
6730
  }
6613
- #scanExports(source, absFile) {
6731
+ #scanExports(source2, absFile) {
6614
6732
  try {
6615
6733
  const transpiler = [".tsx", ".jsx"].includes(path13.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
6616
- const { exports } = transpiler.scan(source);
6734
+ const { exports } = transpiler.scan(source2);
6617
6735
  return new Set(exports);
6618
6736
  } catch (err) {
6619
6737
  this.#logger.error(`scan failed: ${err.message}`);
@@ -6725,28 +6843,28 @@ var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAf
6725
6843
  const raw = await Bun.file(realPath).text();
6726
6844
  return { contents: raw, loader };
6727
6845
  }
6728
- let source = await Bun.file(realPath).text();
6729
- const hasMacroAttr = MACRO_ATTR_RE.test(source);
6846
+ let source2 = await Bun.file(realPath).text();
6847
+ const hasMacroAttr = MACRO_ATTR_RE.test(source2);
6730
6848
  if (!hasMacroAttr && barrels.length > 0) {
6731
6849
  let maybe = false;
6732
6850
  for (const b of barrels) {
6733
- if (source.includes(b)) {
6851
+ if (source2.includes(b)) {
6734
6852
  maybe = true;
6735
6853
  break;
6736
6854
  }
6737
6855
  }
6738
6856
  if (maybe) {
6739
- const rewritten = await rewriteBarrelImports(source, barrels, analyzer);
6857
+ const rewritten = await rewriteBarrelImports(source2, barrels, analyzer);
6740
6858
  if (rewritten !== null)
6741
- source = rewritten;
6859
+ source2 = rewritten;
6742
6860
  }
6743
6861
  }
6744
6862
  if (pipeAfter) {
6745
- const piped = await pipeAfter(source, { path: realPath });
6863
+ const piped = await pipeAfter(source2, { path: realPath });
6746
6864
  if (piped !== null)
6747
- source = piped;
6865
+ source2 = piped;
6748
6866
  }
6749
- return { contents: source, loader };
6867
+ return { contents: source2, loader };
6750
6868
  });
6751
6869
  }
6752
6870
  };
@@ -6922,12 +7040,12 @@ var resolveFileCandidate = async (candidate) => {
6922
7040
  return null;
6923
7041
  };
6924
7042
  var MACRO_ATTR_RE = /with\s*\{\s*type\s*:\s*["']macro["']\s*\}/;
6925
- var rewriteBarrelImports = async (source, barrels, analyzer) => {
6926
- const statements = findImportStatements(source);
7043
+ var rewriteBarrelImports = async (source2, barrels, analyzer) => {
7044
+ const statements = findImportStatements(source2);
6927
7045
  if (statements.length === 0)
6928
7046
  return null;
6929
7047
  let changed = false;
6930
- let out = source;
7048
+ let out = source2;
6931
7049
  for (let i = statements.length - 1;i >= 0; i--) {
6932
7050
  const stmt = statements[i];
6933
7051
  if (!stmt)
@@ -6945,9 +7063,9 @@ var rewriteBarrelImports = async (source, barrels, analyzer) => {
6945
7063
  }
6946
7064
  return changed ? out : null;
6947
7065
  };
6948
- var findImportStatements = (source) => {
7066
+ var findImportStatements = (source2) => {
6949
7067
  const statements = [];
6950
- const sourceFile2 = ts4.createSourceFile("barrel-imports.tsx", source, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TSX);
7068
+ const sourceFile2 = ts4.createSourceFile("barrel-imports.tsx", source2, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TSX);
6951
7069
  for (const statement of sourceFile2.statements) {
6952
7070
  if (!ts4.isImportDeclaration(statement))
6953
7071
  continue;
@@ -6961,10 +7079,10 @@ var findImportStatements = (source) => {
6961
7079
  statements.push({
6962
7080
  start: statementStart,
6963
7081
  end: statementEnd,
6964
- clause: source.slice(importClause.getStart(sourceFile2), importClause.end).trim(),
7082
+ clause: source2.slice(importClause.getStart(sourceFile2), importClause.end).trim(),
6965
7083
  specifier: statement.moduleSpecifier.text,
6966
- trailingSemicolon: source.slice(statement.moduleSpecifier.end, statement.end).includes(";"),
6967
- raw: source.slice(statementStart, statementEnd)
7084
+ trailingSemicolon: source2.slice(statement.moduleSpecifier.end, statement.end).includes(";"),
7085
+ raw: source2.slice(statementStart, statementEnd)
6968
7086
  });
6969
7087
  }
6970
7088
  return statements;
@@ -7214,13 +7332,13 @@ class GraphClientEntryDiscovery {
7214
7332
  }
7215
7333
  return cached;
7216
7334
  }
7217
- async#getImports(file, source) {
7335
+ async#getImports(file, source2) {
7218
7336
  const absPath = path15.resolve(file);
7219
7337
  let cached = this.#importCache.get(absPath);
7220
7338
  if (!cached) {
7221
7339
  cached = Promise.resolve().then(() => {
7222
7340
  try {
7223
- return this.#tsTranspiler.scanImports(source);
7341
+ return this.#tsTranspiler.scanImports(source2);
7224
7342
  } catch {
7225
7343
  return [];
7226
7344
  }
@@ -7245,8 +7363,8 @@ class GraphClientEntryDiscovery {
7245
7363
  entries.add(absPath);
7246
7364
  return this.#finishDiscovery(absPath, visiting, entries);
7247
7365
  }
7248
- const source = await this.#getRewrittenSource(absPath, content);
7249
- const imports = await this.#getImports(absPath, source);
7366
+ const source2 = await this.#getRewrittenSource(absPath, content);
7367
+ const imports = await this.#getImports(absPath, source2);
7250
7368
  const importerDir = path15.dirname(absPath);
7251
7369
  for (const imp of imports) {
7252
7370
  const spec = imp.path;
@@ -7282,13 +7400,13 @@ var IMPLICIT_ROOT_LAYOUT_RE = /[/\\]\.akan[/\\]generated[/\\](?:implicit-root-la
7282
7400
  function toClientReferencePath(absPath, workspaceRoot) {
7283
7401
  return path16.relative(path16.resolve(workspaceRoot), path16.resolve(absPath)).split(path16.sep).join("/");
7284
7402
  }
7285
- function transformUseClient(source, args) {
7286
- if (!USE_CLIENT_RE2.test(source))
7403
+ function transformUseClient(source2, args) {
7404
+ if (!USE_CLIENT_RE2.test(source2))
7287
7405
  return null;
7288
7406
  if (IMPLICIT_ROOT_LAYOUT_RE.test(args.path))
7289
7407
  return null;
7290
7408
  const transpiler = new Bun.Transpiler({ loader: loaderFor2(args.path) });
7291
- const { exports } = transpiler.scan(source);
7409
+ const { exports } = transpiler.scan(source2);
7292
7410
  if (exports.length === 0)
7293
7411
  return null;
7294
7412
  const referencePath = args.workspaceRoot ? toClientReferencePath(args.path, args.workspaceRoot) : args.path;
@@ -7434,9 +7552,9 @@ ${absEntry}`).toString(36);
7434
7552
  `;
7435
7553
  }
7436
7554
  async#scanEntryExportNames(absEntry) {
7437
- const source = await Bun.file(absEntry).text();
7555
+ const source2 = await Bun.file(absEntry).text();
7438
7556
  const transpiler = new Bun.Transpiler({ loader: this.#loaderForEntry(absEntry) });
7439
- return transpiler.scan(source).exports;
7557
+ return transpiler.scan(source2).exports;
7440
7558
  }
7441
7559
  #loaderForEntry(absPath) {
7442
7560
  if (absPath.endsWith(".tsx"))
@@ -7483,14 +7601,14 @@ ${absEntry}`).toString(36);
7483
7601
  if (Object.keys(this.#externalAliases).length === 0)
7484
7602
  return;
7485
7603
  await Promise.all(outputs.filter((output) => output.path.endsWith(".js")).map(async (output) => {
7486
- const source = await Bun.file(output.path).text();
7487
- const rewritten = ClientEntriesBundler.rewriteExternalImportSpecifiers(source, this.#externalAliases);
7488
- if (rewritten !== source)
7604
+ const source2 = await Bun.file(output.path).text();
7605
+ const rewritten = ClientEntriesBundler.rewriteExternalImportSpecifiers(source2, this.#externalAliases);
7606
+ if (rewritten !== source2)
7489
7607
  await Bun.write(output.path, rewritten);
7490
7608
  }));
7491
7609
  }
7492
- static rewriteExternalImportSpecifiers(source, aliases) {
7493
- let rewritten = source;
7610
+ static rewriteExternalImportSpecifiers(source2, aliases) {
7611
+ let rewritten = source2;
7494
7612
  for (const [specifier, alias] of Object.entries(aliases)) {
7495
7613
  if (!alias)
7496
7614
  continue;
@@ -7745,9 +7863,9 @@ ${absEntry}`).toString(36);
7745
7863
  return { buildEntries, originalByBuildEntry };
7746
7864
  }
7747
7865
  async#scanExportNames(absEntry) {
7748
- const source = await Bun.file(absEntry).text();
7866
+ const source2 = await Bun.file(absEntry).text();
7749
7867
  const transpiler = new Bun.Transpiler({ loader: this.#loaderFor(absEntry) });
7750
- return transpiler.scan(source).exports;
7868
+ return transpiler.scan(source2).exports;
7751
7869
  }
7752
7870
  #loaderFor(absPath) {
7753
7871
  if (absPath.endsWith(".tsx"))
@@ -7758,10 +7876,10 @@ ${absEntry}`).toString(36);
7758
7876
  return "ts";
7759
7877
  return "js";
7760
7878
  }
7761
- static normalizeNamedDefaultFunctionForFastRefresh(source) {
7879
+ static normalizeNamedDefaultFunctionForFastRefresh(source2) {
7762
7880
  let changed = false;
7763
7881
  const defaultNames = [];
7764
- const next = source.replace(/(^|\n)(\s*)export\s+default\s+(async\s+)?function\s+([A-Za-z_$][\w$]*)(?=\s*(?:<|\())/g, (match, lineStart, indent, asyncKeyword, name) => {
7882
+ const next = source2.replace(/(^|\n)(\s*)export\s+default\s+(async\s+)?function\s+([A-Za-z_$][\w$]*)(?=\s*(?:<|\())/g, (match, lineStart, indent, asyncKeyword, name) => {
7765
7883
  changed = true;
7766
7884
  defaultNames.push(name);
7767
7885
  return `${lineStart}${indent}${asyncKeyword ?? ""}function ${name}`;
@@ -7989,8 +8107,8 @@ ${entries.join(`
7989
8107
  }
7990
8108
  static #hasAsyncDefaultExport(moduleAbsPath) {
7991
8109
  try {
7992
- const source = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
7993
- const sourceFile2 = ts5.createSourceFile(moduleAbsPath, source, ts5.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
8110
+ const source2 = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
8111
+ const sourceFile2 = ts5.createSourceFile(moduleAbsPath, source2, ts5.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
7994
8112
  return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile2);
7995
8113
  } catch {
7996
8114
  return false;
@@ -8250,8 +8368,8 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
8250
8368
  return html;
8251
8369
  return result + html.slice(lastIndex);
8252
8370
  }
8253
- static escapeInlineScript(source) {
8254
- return source.replace(/<\/script/gi, "<\\/script");
8371
+ static escapeInlineScript(source2) {
8372
+ return source2.replace(/<\/script/gi, "<\\/script");
8255
8373
  }
8256
8374
  static resolveHtmlAssetPath(htmlPath, src) {
8257
8375
  if (/^[a-z][a-z0-9+.-]*:/i.test(src) || src.startsWith("//")) {
@@ -8482,17 +8600,17 @@ class CssCompiler {
8482
8600
  } catch {
8483
8601
  continue;
8484
8602
  }
8485
- let source = content;
8603
+ let source2 = content;
8486
8604
  if (akanConfig2.barrelImports.length > 0) {
8487
8605
  try {
8488
8606
  const rewritten = await rewriteBarrelImports(content, akanConfig2.barrelImports, analyzer);
8489
8607
  if (rewritten !== null)
8490
- source = rewritten;
8608
+ source2 = rewritten;
8491
8609
  } catch {}
8492
8610
  }
8493
8611
  let imports;
8494
8612
  try {
8495
- imports = this.#transpiler.scanImports(source);
8613
+ imports = this.#transpiler.scanImports(source2);
8496
8614
  } catch {
8497
8615
  continue;
8498
8616
  }
@@ -8931,7 +9049,7 @@ class DevGeneratedIndexSync {
8931
9049
  const rawModel = moduleSegment.startsWith("_") ? moduleSegment.slice(1) : moduleSegment;
8932
9050
  if (!rawModel)
8933
9051
  return null;
8934
- const modelName = capitalize4(rawModel);
9052
+ const modelName = capitalize5(rawModel);
8935
9053
  const allowedTypes = isScalar ? SCALAR_UI_TYPES : moduleSegment.startsWith("_") ? SERVICE_UI_TYPES : MODULE_UI_TYPES;
8936
9054
  const fileTypes = [];
8937
9055
  for (const type of allowedTypes) {
@@ -8948,7 +9066,7 @@ export const ${modelName} = { ${fileTypes.join(", ")} };`;
8948
9066
  }
8949
9067
  }
8950
9068
  var exists = async (file) => stat3(file).then(() => true).catch(() => false);
8951
- var capitalize4 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
9069
+ var capitalize5 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
8952
9070
  var formatError = (err) => err instanceof Error ? err.message : String(err);
8953
9071
  // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
8954
9072
  import { mkdir as mkdir7 } from "fs/promises";
@@ -9025,8 +9143,8 @@ class FontOptimizer {
9025
9143
  if (faceCss.length > 0)
9026
9144
  this.#cssParts.push(...faceCss, this.#buildRootVariableRule(font));
9027
9145
  }
9028
- #extractFontsExport(source, filePath) {
9029
- const sourceFile2 = ts6.createSourceFile(filePath, source, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TSX);
9146
+ #extractFontsExport(source2, filePath) {
9147
+ const sourceFile2 = ts6.createSourceFile(filePath, source2, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TSX);
9030
9148
  const fonts = [];
9031
9149
  for (const statement of sourceFile2.statements) {
9032
9150
  if (!ts6.isVariableStatement(statement))
@@ -9582,13 +9700,13 @@ function createUseClientBundlePlugin(options = {}) {
9582
9700
  build.onLoad({ filter: /\.(tsx|ts|jsx|js)$/ }, async (args) => {
9583
9701
  if (args.path.includes("/node_modules/"))
9584
9702
  return;
9585
- let source;
9703
+ let source2;
9586
9704
  try {
9587
- source = await Bun.file(args.path).text();
9705
+ source2 = await Bun.file(args.path).text();
9588
9706
  } catch {
9589
9707
  return;
9590
9708
  }
9591
- const stubbed = transformUseClient(source, {
9709
+ const stubbed = transformUseClient(source2, {
9592
9710
  path: args.path,
9593
9711
  workspaceRoot: options.workspaceRoot
9594
9712
  });
@@ -9646,7 +9764,7 @@ class PagesBundleBuilder {
9646
9764
  PagesBundleBuilder.createServerUseClientFetchPlugin(),
9647
9765
  await createExternalizeFrameworkPlugin({ app: this.#app, extra: akanConfig2.externalLibs }),
9648
9766
  akanConfig2.barrelImports.length > 0 ? await createBarrelImportsPlugin(this.#app, {
9649
- pipeAfter: (source, args) => transformUseClient(source, {
9767
+ pipeAfter: (source2, args) => transformUseClient(source2, {
9650
9768
  path: args.path,
9651
9769
  workspaceRoot
9652
9770
  })
@@ -9687,7 +9805,7 @@ class PagesBundleBuilder {
9687
9805
  ...Object.fromEntries(Object.entries(this.#app.getPublicEnv()).map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)]))
9688
9806
  };
9689
9807
  }
9690
- static createPagesEntryPlugin(source) {
9808
+ static createPagesEntryPlugin(source2) {
9691
9809
  return {
9692
9810
  name: "akan-pages-entry",
9693
9811
  setup(build) {
@@ -9696,7 +9814,7 @@ class PagesBundleBuilder {
9696
9814
  namespace: "akan-virtual"
9697
9815
  }));
9698
9816
  build.onLoad({ filter: /^akan-pages-entry$/, namespace: "akan-virtual" }, () => ({
9699
- contents: source,
9817
+ contents: source2,
9700
9818
  loader: "tsx"
9701
9819
  }));
9702
9820
  }
@@ -9718,19 +9836,19 @@ class PagesBundleBuilder {
9718
9836
  name: "akan-server-use-client-fetch",
9719
9837
  setup(build) {
9720
9838
  build.onLoad({ filter: /[/\\]lib[/\\]useClient\.(ts|tsx|js|jsx)$/ }, async (args) => {
9721
- const source = await Bun.file(args.path).text();
9722
- const transformed = PagesBundleBuilder.transformServerUseClientFetchSource(source);
9723
- if (transformed === source)
9839
+ const source2 = await Bun.file(args.path).text();
9840
+ const transformed = PagesBundleBuilder.transformServerUseClientFetchSource(source2);
9841
+ if (transformed === source2)
9724
9842
  return;
9725
9843
  return { contents: transformed, loader: loaderFor4(args.path) };
9726
9844
  });
9727
9845
  }
9728
9846
  };
9729
9847
  }
9730
- static transformServerUseClientFetchSource(source) {
9731
- if (!source.includes(`with { type: "macro" }`) || !source.includes("FetchClient.build"))
9732
- return source;
9733
- return source.replace(/import\s+\{\s*getSerializedSignal\s*\}\s+from\s+["']\.\/sig["']\s+with\s+\{\s*type\s*:\s*["']macro["']\s*\};/, `import { fetch as serverFetch } from "./sig";`).replace(/const\s+fetchProto\s*=\s*FetchClient\.build<[^;]+;/, "const fetchProto = FetchClient.build<typeof signal>(cnst, serverFetch.serializedSignal, { Err: pageProto.Err, base: serverFetch });");
9848
+ static transformServerUseClientFetchSource(source2) {
9849
+ if (!source2.includes(`with { type: "macro" }`) || !source2.includes("FetchClient.build"))
9850
+ return source2;
9851
+ return source2.replace(/import\s+\{\s*getSerializedSignal\s*\}\s+from\s+["']\.\/sig["']\s+with\s+\{\s*type\s*:\s*["']macro["']\s*\};/, `import { fetch as serverFetch } from "./sig";`).replace(/const\s+fetchProto\s*=\s*FetchClient\.build<[^;]+;/, "const fetchProto = FetchClient.build<typeof signal>(cnst, serverFetch.serializedSignal, { Err: pageProto.Err, base: serverFetch });");
9734
9852
  }
9735
9853
  }
9736
9854
  function loaderFor4(absPath) {
@@ -10496,8 +10614,8 @@ class Builder {
10496
10614
  #executor;
10497
10615
  #distExecutor;
10498
10616
  #pkgJson;
10499
- constructor({ executor, distExecutor, pkgJson }) {
10500
- this.#executor = executor;
10617
+ constructor({ executor: executor2, distExecutor, pkgJson }) {
10618
+ this.#executor = executor2;
10501
10619
  this.#distExecutor = distExecutor;
10502
10620
  this.#pkgJson = pkgJson;
10503
10621
  }
@@ -10623,7 +10741,7 @@ import os from "os";
10623
10741
  import path38 from "path";
10624
10742
  import { select as select2 } from "@inquirer/prompts";
10625
10743
  import { MobileProject } from "@trapezedev/project";
10626
- import { capitalize as capitalize5 } from "akanjs/common";
10744
+ import { capitalize as capitalize6 } from "akanjs/common";
10627
10745
 
10628
10746
  // pkgs/@akanjs/devkit/fileEditor.ts
10629
10747
  class FileEditor {
@@ -11714,7 +11832,7 @@ ${error.message}`;
11714
11832
  this.#setPermissionsInAndroid(["POST_NOTIFICATIONS"]);
11715
11833
  }
11716
11834
  async#setPermissionInIos(permissions) {
11717
- const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize5(key)}`, value]));
11835
+ const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize6(key)}`, value]));
11718
11836
  await Promise.all([
11719
11837
  this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
11720
11838
  this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
@@ -11806,8 +11924,8 @@ import chalk6 from "chalk";
11806
11924
  import { program } from "commander";
11807
11925
 
11808
11926
  // pkgs/@akanjs/devkit/commandDecorators/dependencyBuilder.ts
11809
- var capitalize6 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
11810
- var createDependencyKey = (refName, kind) => `${refName}${capitalize6(kind)}`;
11927
+ var capitalize7 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
11928
+ var createDependencyKey = (refName, kind) => `${refName}${capitalize7(kind)}`;
11811
11929
 
11812
11930
  class CommandContainer {
11813
11931
  static #instances = new Map;
@@ -12287,13 +12405,13 @@ var getInternalArgumentValue = async (argMeta, value, workspace) => {
12287
12405
  ...libNames.map((name2) => ({ name: name2, value: { type: "lib", name: name2 } }))
12288
12406
  ]
12289
12407
  });
12290
- const executor = type === "app" ? AppExecutor.from(workspace, name) : LibExecutor.from(workspace, name);
12291
- const modules = await executor.getModules();
12408
+ const executor2 = type === "app" ? AppExecutor.from(workspace, name) : LibExecutor.from(workspace, name);
12409
+ const modules = await executor2.getModules();
12292
12410
  const moduleName = await select3({
12293
12411
  message: `Select the module name`,
12294
- choices: modules.map((name2) => ({ name: `${executor.name}:${name2}`, value: name2 }))
12412
+ choices: modules.map((name2) => ({ name: `${executor2.name}:${name2}`, value: name2 }))
12295
12413
  });
12296
- return ModuleExecutor.from(executor, moduleName);
12414
+ return ModuleExecutor.from(executor2, moduleName);
12297
12415
  } else
12298
12416
  throw new Error(`Invalid system type: ${argMeta.type}`);
12299
12417
  };
@@ -12552,18 +12670,18 @@ import * as ts7 from "typescript";
12552
12670
  var tsTranspiler = new Bun.Transpiler({ loader: "ts" });
12553
12671
  var tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
12554
12672
  var getTranspiler = (filePath) => filePath.endsWith(".tsx") ? tsxTranspiler : tsTranspiler;
12555
- var scanModuleSpecifiers = (source, filePath, includeExports) => {
12556
- const scannedImports = getTranspiler(filePath).scanImports(source).map((imp) => imp.path).filter(Boolean);
12673
+ var scanModuleSpecifiers = (source2, filePath, includeExports) => {
12674
+ const scannedImports = getTranspiler(filePath).scanImports(source2).map((imp) => imp.path).filter(Boolean);
12557
12675
  if (includeExports) {
12558
12676
  const specifiers = new Set(scannedImports);
12559
12677
  const typeOnlyModuleRegex = /\b(?:import|export)\s+type\s+[\s\S]*?\s+from\s*["']([^"']+)["']/g;
12560
- for (const match of source.matchAll(typeOnlyModuleRegex)) {
12678
+ for (const match of source2.matchAll(typeOnlyModuleRegex)) {
12561
12679
  const importPath = match[1];
12562
12680
  if (importPath)
12563
12681
  specifiers.add(importPath);
12564
12682
  }
12565
12683
  const exportFromRegex = /\bexport\s+(?:type\s+)?(?:\*|{[\s\S]*?})\s+from\s*["']([^"']+)["']/g;
12566
- for (const match of source.matchAll(exportFromRegex)) {
12684
+ for (const match of source2.matchAll(exportFromRegex)) {
12567
12685
  const importPath = match[1];
12568
12686
  if (importPath)
12569
12687
  specifiers.add(importPath);
@@ -12572,7 +12690,7 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
12572
12690
  }
12573
12691
  const importSpecifiers = new Set;
12574
12692
  const importDeclarationRegex = /\bimport\s+(?:type\s+)?(?:["']([^"']+)["']|[\s\S]*?\s+from\s*["']([^"']+)["'])/g;
12575
- for (const match of source.matchAll(importDeclarationRegex)) {
12693
+ for (const match of source2.matchAll(importDeclarationRegex)) {
12576
12694
  const importPath = match[1] ?? match[2];
12577
12695
  if (importPath && (scannedImports.includes(importPath) || match[0].startsWith("import type"))) {
12578
12696
  importSpecifiers.add(importPath);
@@ -12595,8 +12713,8 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
12595
12713
  if (analyzedFiles.has(filePath))
12596
12714
  return;
12597
12715
  analyzedFiles.add(filePath);
12598
- const source = readFileSync4(filePath, "utf-8");
12599
- for (const importPath of scanModuleSpecifiers(source, filePath, false)) {
12716
+ const source2 = readFileSync4(filePath, "utf-8");
12717
+ for (const importPath of scanModuleSpecifiers(source2, filePath, false)) {
12600
12718
  if (!importPath.startsWith("."))
12601
12719
  continue;
12602
12720
  const resolved = ts7.resolveModuleName(importPath, filePath, parsedConfig.options, ts7.sys).resolvedModule?.resolvedFileName;
@@ -12645,21 +12763,21 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
12645
12763
  if (analyzedFiles.has(filePath))
12646
12764
  return;
12647
12765
  analyzedFiles.add(filePath);
12648
- const source = program2.getSourceFile(filePath);
12649
- if (!source)
12766
+ const source2 = program2.getSourceFile(filePath);
12767
+ if (!source2)
12650
12768
  return;
12651
12769
  if (!sourceLineCache.has(filePath)) {
12652
- sourceLineCache.set(filePath, source.getFullText().split(`
12770
+ sourceLineCache.set(filePath, source2.getFullText().split(`
12653
12771
  `));
12654
12772
  }
12655
12773
  const sourceLines = sourceLineCache.get(filePath);
12656
12774
  function visit(node) {
12657
- if (!source)
12775
+ if (!source2)
12658
12776
  return;
12659
12777
  if (ts7.isPropertyAccessExpression(node)) {
12660
12778
  const left = node.expression;
12661
12779
  const right = node.name;
12662
- const { line } = ts7.getLineAndCharacterOfPosition(source, node.getStart());
12780
+ const { line } = ts7.getLineAndCharacterOfPosition(source2, node.getStart());
12663
12781
  if (ts7.isIdentifier(left) && sourceLines && sourceLines.length > line && sourceLines[line] && (sourceLines[line]?.includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
12664
12782
  const symbol = getCachedSymbol(right);
12665
12783
  if (symbol?.declarations && symbol.declarations.length > 0) {
@@ -12710,7 +12828,7 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
12710
12828
  }
12711
12829
  ts7.forEachChild(node, visit);
12712
12830
  }
12713
- visit(source);
12831
+ visit(source2);
12714
12832
  }
12715
12833
  for (const filePath of filesToAnalyze) {
12716
12834
  analyzeFileProperties(filePath);