@lumenflow/cli 3.1.2 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -35
- package/dist/agent-issues-query.js +13 -8
- package/dist/agent-log-issue.js +15 -4
- package/dist/agent-session-end.js +15 -4
- package/dist/agent-session.js +18 -6
- package/dist/backlog-prune.js +1 -1
- package/dist/commands/integrate.js +32 -18
- package/dist/config-get.js +27 -15
- package/dist/config-set.js +104 -37
- package/dist/delegation-list.js +1 -1
- package/dist/doctor.js +19 -13
- package/dist/file-delete.js +1 -1
- package/dist/file-edit.js +1 -1
- package/dist/file-read.js +1 -1
- package/dist/file-write.js +1 -1
- package/dist/flow-bottlenecks.js +1 -1
- package/dist/flow-report.js +10 -9
- package/dist/gates.js +3 -2
- package/dist/git-branch.js +1 -1
- package/dist/git-diff.js +1 -1
- package/dist/git-log.js +1 -1
- package/dist/init.js +238 -42
- package/dist/initiative-add-wu.js +1 -1
- package/dist/initiative-bulk-assign-wus.js +1 -1
- package/dist/initiative-create.js +2 -2
- package/dist/initiative-edit.js +1 -1
- package/dist/initiative-list.js +1 -1
- package/dist/initiative-plan.js +1 -3
- package/dist/initiative-status.js +47 -6
- package/dist/lane-edit.js +19 -10
- package/dist/lane-health.js +13 -24
- package/dist/lane-lock.js +4 -5
- package/dist/lane-setup.js +5 -5
- package/dist/lane-status.js +4 -5
- package/dist/lane-suggest.js +9 -7
- package/dist/lane-validate.js +4 -5
- package/dist/lumenflow-upgrade.js +17 -11
- package/dist/mem-checkpoint.js +1 -1
- package/dist/mem-cleanup.js +6 -23
- package/dist/mem-context.js +1 -1
- package/dist/mem-create.js +1 -1
- package/dist/mem-delete.js +1 -1
- package/dist/mem-export.js +1 -1
- package/dist/mem-inbox.js +1 -1
- package/dist/mem-init.js +1 -1
- package/dist/mem-ready.js +1 -1
- package/dist/mem-recover.js +1 -1
- package/dist/mem-signal.js +1 -1
- package/dist/mem-start.js +1 -1
- package/dist/mem-summarize.js +8 -7
- package/dist/mem-triage.js +7 -5
- package/dist/metrics-cli.js +1 -1
- package/dist/metrics-snapshot.js +1 -1
- package/dist/onboard.js +295 -120
- package/dist/orchestrate-init-status.js +12 -7
- package/dist/orchestrate-initiative.js +23 -12
- package/dist/orchestrate-monitor.js +20 -8
- package/dist/pack-scaffold.js +1 -1
- package/dist/plan-create.js +1 -3
- package/dist/plan-edit.js +1 -3
- package/dist/plan-link.js +1 -3
- package/dist/plan-promote.js +1 -3
- package/dist/release.js +1 -3
- package/dist/signal-cleanup.js +4 -18
- package/dist/state-bootstrap.js +11 -8
- package/dist/state-cleanup.js +5 -19
- package/dist/state-doctor.js +213 -9
- package/dist/task-claim.js +1 -1
- package/dist/validate.js +1 -1
- package/dist/workspace-init.js +61 -61
- package/dist/wu-block.js +1 -1
- package/dist/wu-brief.js +1 -1
- package/dist/wu-claim.js +1 -1
- package/dist/wu-cleanup.js +1 -1
- package/dist/wu-create.js +3 -3
- package/dist/wu-delegate.js +1 -1
- package/dist/wu-deps.js +1 -1
- package/dist/wu-done.js +66 -34
- package/dist/wu-edit.js +1 -1
- package/dist/wu-infer-lane.js +1 -1
- package/dist/wu-preflight.js +1 -1
- package/dist/wu-prep.js +1 -1
- package/dist/wu-proto.js +1 -1
- package/dist/wu-prune.js +1 -1
- package/dist/wu-recover.js +1 -1
- package/dist/wu-release.js +1 -1
- package/dist/wu-repair.js +1 -1
- package/dist/wu-sandbox.js +40 -27
- package/dist/wu-status.js +1 -1
- package/dist/wu-unblock.js +1 -1
- package/dist/wu-unlock-lane.js +1 -1
- package/dist/wu-validate.js +1 -1
- package/package.json +12 -8
- package/packs/software-delivery/constants.ts +10 -0
- package/packs/software-delivery/extensions.ts +140 -0
- package/packs/software-delivery/gate-policies.ts +134 -0
- package/packs/software-delivery/index.ts +8 -0
- package/packs/software-delivery/manifest-schema.ts +236 -0
- package/packs/software-delivery/manifest.ts +417 -0
- package/packs/software-delivery/manifest.yaml +711 -0
- package/packs/software-delivery/pack-registration.ts +113 -0
- package/packs/software-delivery/tool-impl/agent-tools.ts +263 -0
- package/packs/software-delivery/tool-impl/delegation-tools.ts +66 -0
- package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +219 -0
- package/packs/software-delivery/tool-impl/git-runner.ts +113 -0
- package/packs/software-delivery/tool-impl/git-tools.ts +316 -0
- package/packs/software-delivery/tool-impl/index.ts +15 -0
- package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +720 -0
- package/packs/software-delivery/tool-impl/lane-lock.ts +246 -0
- package/packs/software-delivery/tool-impl/memory-tools.ts +415 -0
- package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +21 -0
- package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +328 -0
- package/packs/software-delivery/tool-impl/runtime-native-tools.ts +687 -0
- package/packs/software-delivery/tool-impl/worker-loader.ts +52 -0
- package/packs/software-delivery/tool-impl/worktree-tools.ts +46 -0
- package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +759 -0
- package/packs/software-delivery/tools/delegation-tools.ts +23 -0
- package/packs/software-delivery/tools/git-tools.ts +55 -0
- package/packs/software-delivery/tools/index.ts +8 -0
- package/packs/software-delivery/tools/lane-lock-tool.ts +37 -0
- package/packs/software-delivery/tools/types.ts +71 -0
- package/packs/software-delivery/tools/worktree-tools.ts +49 -0
- package/templates/core/LUMENFLOW.md.template +3 -3
- package/templates/core/ai/onboarding/agent-invocation-guide.md.template +1 -1
- package/templates/core/ai/onboarding/lumenflow-force-usage.md.template +1 -1
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +5 -5
- package/templates/core/ai/onboarding/starting-prompt.md.template +3 -3
- package/templates/core/ai/onboarding/vendor-support.md.template +1 -1
- package/templates/core/ai/onboarding/wu-create-checklist.md.template +1 -1
- package/dist/agent-issues-query.js.map +0 -1
- package/dist/agent-log-issue.js.map +0 -1
- package/dist/agent-session-end.js.map +0 -1
- package/dist/agent-session.js.map +0 -1
- package/dist/backlog-prune.js.map +0 -1
- package/dist/cli-entry-point.js +0 -149
- package/dist/cli-entry-point.js.map +0 -1
- package/dist/commands/integrate.js.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/config-get.js.map +0 -1
- package/dist/config-set.js.map +0 -1
- package/dist/delegation-list.js.map +0 -1
- package/dist/deps-add.js +0 -259
- package/dist/deps-add.js.map +0 -1
- package/dist/deps-remove.js +0 -105
- package/dist/deps-remove.js.map +0 -1
- package/dist/docs-sync.js.map +0 -1
- package/dist/doctor.js.map +0 -1
- package/dist/file-delete.js.map +0 -1
- package/dist/file-edit.js.map +0 -1
- package/dist/file-read.js.map +0 -1
- package/dist/file-write.js.map +0 -1
- package/dist/flow-bottlenecks.js.map +0 -1
- package/dist/flow-report.js.map +0 -1
- package/dist/formatters.js +0 -151
- package/dist/formatters.js.map +0 -1
- package/dist/gate-defaults.js +0 -131
- package/dist/gate-defaults.js.map +0 -1
- package/dist/gate-registry.js +0 -73
- package/dist/gate-registry.js.map +0 -1
- package/dist/gates-graceful-degradation.js +0 -153
- package/dist/gates-graceful-degradation.js.map +0 -1
- package/dist/gates-plan-resolvers.js +0 -152
- package/dist/gates-plan-resolvers.js.map +0 -1
- package/dist/gates-runners.js +0 -509
- package/dist/gates-runners.js.map +0 -1
- package/dist/gates-types.js +0 -4
- package/dist/gates-types.js.map +0 -1
- package/dist/gates-utils.js +0 -323
- package/dist/gates-utils.js.map +0 -1
- package/dist/gates.js.map +0 -1
- package/dist/git-branch.js.map +0 -1
- package/dist/git-diff.js.map +0 -1
- package/dist/git-log.js.map +0 -1
- package/dist/git-status.js.map +0 -1
- package/dist/guard-locked.js +0 -172
- package/dist/guard-locked.js.map +0 -1
- package/dist/guard-main-branch.js +0 -217
- package/dist/guard-main-branch.js.map +0 -1
- package/dist/guard-worktree-commit.js +0 -163
- package/dist/guard-worktree-commit.js.map +0 -1
- package/dist/hooks/auto-checkpoint-utils.js +0 -54
- package/dist/hooks/auto-checkpoint-utils.js.map +0 -1
- package/dist/hooks/enforcement-checks.js +0 -399
- package/dist/hooks/enforcement-checks.js.map +0 -1
- package/dist/hooks/enforcement-generator.js +0 -139
- package/dist/hooks/enforcement-generator.js.map +0 -1
- package/dist/hooks/enforcement-sync.js +0 -385
- package/dist/hooks/enforcement-sync.js.map +0 -1
- package/dist/hooks/generators/auto-checkpoint.js +0 -125
- package/dist/hooks/generators/auto-checkpoint.js.map +0 -1
- package/dist/hooks/generators/enforce-worktree.js +0 -190
- package/dist/hooks/generators/enforce-worktree.js.map +0 -1
- package/dist/hooks/generators/index.js +0 -18
- package/dist/hooks/generators/index.js.map +0 -1
- package/dist/hooks/generators/pre-compact-checkpoint.js +0 -136
- package/dist/hooks/generators/pre-compact-checkpoint.js.map +0 -1
- package/dist/hooks/generators/require-wu.js +0 -117
- package/dist/hooks/generators/require-wu.js.map +0 -1
- package/dist/hooks/generators/session-start-recovery.js +0 -103
- package/dist/hooks/generators/session-start-recovery.js.map +0 -1
- package/dist/hooks/generators/signal-utils.js +0 -54
- package/dist/hooks/generators/signal-utils.js.map +0 -1
- package/dist/hooks/generators/warn-incomplete.js +0 -67
- package/dist/hooks/generators/warn-incomplete.js.map +0 -1
- package/dist/hooks/index.js +0 -10
- package/dist/hooks/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init-detection.js +0 -232
- package/dist/init-detection.js.map +0 -1
- package/dist/init-lane-validation.js +0 -143
- package/dist/init-lane-validation.js.map +0 -1
- package/dist/init-scaffolding.js +0 -158
- package/dist/init-scaffolding.js.map +0 -1
- package/dist/init-templates.js +0 -1982
- package/dist/init-templates.js.map +0 -1
- package/dist/init.js.map +0 -1
- package/dist/initiative-add-wu.js.map +0 -1
- package/dist/initiative-bulk-assign-wus.js.map +0 -1
- package/dist/initiative-create.js.map +0 -1
- package/dist/initiative-edit.js.map +0 -1
- package/dist/initiative-list.js.map +0 -1
- package/dist/initiative-plan.js.map +0 -1
- package/dist/initiative-remove-wu.js.map +0 -1
- package/dist/initiative-status.js.map +0 -1
- package/dist/lane-edit.js.map +0 -1
- package/dist/lane-health.js.map +0 -1
- package/dist/lane-lifecycle-process.js +0 -366
- package/dist/lane-lifecycle-process.js.map +0 -1
- package/dist/lane-lock.js.map +0 -1
- package/dist/lane-setup.js.map +0 -1
- package/dist/lane-status.js.map +0 -1
- package/dist/lane-suggest.js.map +0 -1
- package/dist/lane-validate.js.map +0 -1
- package/dist/lifecycle-regression-harness.js +0 -181
- package/dist/lifecycle-regression-harness.js.map +0 -1
- package/dist/lumenflow-upgrade.js.map +0 -1
- package/dist/mem-checkpoint.js.map +0 -1
- package/dist/mem-cleanup.js.map +0 -1
- package/dist/mem-context.js.map +0 -1
- package/dist/mem-create.js.map +0 -1
- package/dist/mem-delete.js.map +0 -1
- package/dist/mem-export.js.map +0 -1
- package/dist/mem-inbox.js.map +0 -1
- package/dist/mem-index.js +0 -214
- package/dist/mem-index.js.map +0 -1
- package/dist/mem-init.js.map +0 -1
- package/dist/mem-profile.js +0 -210
- package/dist/mem-profile.js.map +0 -1
- package/dist/mem-promote.js +0 -257
- package/dist/mem-promote.js.map +0 -1
- package/dist/mem-ready.js.map +0 -1
- package/dist/mem-recover.js.map +0 -1
- package/dist/mem-signal.js.map +0 -1
- package/dist/mem-start.js.map +0 -1
- package/dist/mem-summarize.js.map +0 -1
- package/dist/mem-triage.js.map +0 -1
- package/dist/merge-block.js +0 -225
- package/dist/merge-block.js.map +0 -1
- package/dist/metrics-cli.js.map +0 -1
- package/dist/metrics-snapshot.js.map +0 -1
- package/dist/onboard.js.map +0 -1
- package/dist/onboarding-smoke-test.js +0 -418
- package/dist/onboarding-smoke-test.js.map +0 -1
- package/dist/orchestrate-init-status.js.map +0 -1
- package/dist/orchestrate-initiative.js.map +0 -1
- package/dist/orchestrate-monitor.js.map +0 -1
- package/dist/pack-author.js.map +0 -1
- package/dist/pack-hash.js.map +0 -1
- package/dist/pack-install.js.map +0 -1
- package/dist/pack-publish.js.map +0 -1
- package/dist/pack-scaffold.js.map +0 -1
- package/dist/pack-search.js.map +0 -1
- package/dist/pack-validate.js.map +0 -1
- package/dist/plan-create.js.map +0 -1
- package/dist/plan-edit.js.map +0 -1
- package/dist/plan-link.js.map +0 -1
- package/dist/plan-promote.js.map +0 -1
- package/dist/public-manifest.js +0 -920
- package/dist/public-manifest.js.map +0 -1
- package/dist/release.js.map +0 -1
- package/dist/rotate-progress.js +0 -253
- package/dist/rotate-progress.js.map +0 -1
- package/dist/session-coordinator.js +0 -303
- package/dist/session-coordinator.js.map +0 -1
- package/dist/shared-validators.js +0 -81
- package/dist/shared-validators.js.map +0 -1
- package/dist/signal-cleanup.js.map +0 -1
- package/dist/state-bootstrap.js.map +0 -1
- package/dist/state-cleanup.js.map +0 -1
- package/dist/state-doctor-fix.js +0 -226
- package/dist/state-doctor-fix.js.map +0 -1
- package/dist/state-doctor-stamps.js +0 -23
- package/dist/state-doctor-stamps.js.map +0 -1
- package/dist/state-doctor.js.map +0 -1
- package/dist/strict-progress.js +0 -255
- package/dist/strict-progress.js.map +0 -1
- package/dist/sync-templates.js.map +0 -1
- package/dist/task-claim.js.map +0 -1
- package/dist/trace-gen.js +0 -401
- package/dist/trace-gen.js.map +0 -1
- package/dist/validate-agent-skills.js +0 -223
- package/dist/validate-agent-skills.js.map +0 -1
- package/dist/validate-agent-sync.js +0 -151
- package/dist/validate-agent-sync.js.map +0 -1
- package/dist/validate-backlog-sync.js +0 -77
- package/dist/validate-backlog-sync.js.map +0 -1
- package/dist/validate-skills-spec.js +0 -211
- package/dist/validate-skills-spec.js.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/validator-defaults.js +0 -107
- package/dist/validator-defaults.js.map +0 -1
- package/dist/validator-registry.js +0 -71
- package/dist/validator-registry.js.map +0 -1
- package/dist/workspace-init.js.map +0 -1
- package/dist/wu-block.js.map +0 -1
- package/dist/wu-brief.js.map +0 -1
- package/dist/wu-claim-branch.js +0 -123
- package/dist/wu-claim-branch.js.map +0 -1
- package/dist/wu-claim-cloud.js +0 -79
- package/dist/wu-claim-cloud.js.map +0 -1
- package/dist/wu-claim-mode.js +0 -82
- package/dist/wu-claim-mode.js.map +0 -1
- package/dist/wu-claim-output.js +0 -85
- package/dist/wu-claim-output.js.map +0 -1
- package/dist/wu-claim-repair-guidance.js +0 -12
- package/dist/wu-claim-repair-guidance.js.map +0 -1
- package/dist/wu-claim-resume-handler.js +0 -87
- package/dist/wu-claim-resume-handler.js.map +0 -1
- package/dist/wu-claim-state.js +0 -581
- package/dist/wu-claim-state.js.map +0 -1
- package/dist/wu-claim-validation.js +0 -457
- package/dist/wu-claim-validation.js.map +0 -1
- package/dist/wu-claim-worktree.js +0 -223
- package/dist/wu-claim-worktree.js.map +0 -1
- package/dist/wu-claim.js.map +0 -1
- package/dist/wu-cleanup-cloud.js +0 -78
- package/dist/wu-cleanup-cloud.js.map +0 -1
- package/dist/wu-cleanup.js.map +0 -1
- package/dist/wu-code-path-coverage.js +0 -83
- package/dist/wu-code-path-coverage.js.map +0 -1
- package/dist/wu-create-cloud.js +0 -30
- package/dist/wu-create-cloud.js.map +0 -1
- package/dist/wu-create-content.js +0 -264
- package/dist/wu-create-content.js.map +0 -1
- package/dist/wu-create-readiness.js +0 -59
- package/dist/wu-create-readiness.js.map +0 -1
- package/dist/wu-create-validation.js +0 -128
- package/dist/wu-create-validation.js.map +0 -1
- package/dist/wu-create.js.map +0 -1
- package/dist/wu-delegate.js.map +0 -1
- package/dist/wu-delete.js.map +0 -1
- package/dist/wu-deps.js.map +0 -1
- package/dist/wu-done-auto-cleanup.js +0 -203
- package/dist/wu-done-auto-cleanup.js.map +0 -1
- package/dist/wu-done-check.js +0 -38
- package/dist/wu-done-check.js.map +0 -1
- package/dist/wu-done-cloud.js +0 -48
- package/dist/wu-done-cloud.js.map +0 -1
- package/dist/wu-done-decay.js +0 -86
- package/dist/wu-done-decay.js.map +0 -1
- package/dist/wu-done.js.map +0 -1
- package/dist/wu-edit-operations.js +0 -399
- package/dist/wu-edit-operations.js.map +0 -1
- package/dist/wu-edit-validators.js +0 -282
- package/dist/wu-edit-validators.js.map +0 -1
- package/dist/wu-edit.js.map +0 -1
- package/dist/wu-infer-lane.js.map +0 -1
- package/dist/wu-preflight.js.map +0 -1
- package/dist/wu-prep.js.map +0 -1
- package/dist/wu-proto.js.map +0 -1
- package/dist/wu-prune.js.map +0 -1
- package/dist/wu-recover.js.map +0 -1
- package/dist/wu-release.js.map +0 -1
- package/dist/wu-repair.js.map +0 -1
- package/dist/wu-sandbox.js.map +0 -1
- package/dist/wu-spawn-completion.js +0 -33
- package/dist/wu-spawn-completion.js.map +0 -1
- package/dist/wu-spawn-prompt-builders.js +0 -1197
- package/dist/wu-spawn-prompt-builders.js.map +0 -1
- package/dist/wu-spawn-strategy-resolver.js +0 -322
- package/dist/wu-spawn-strategy-resolver.js.map +0 -1
- package/dist/wu-spawn.js +0 -59
- package/dist/wu-spawn.js.map +0 -1
- package/dist/wu-state-cloud.js +0 -41
- package/dist/wu-state-cloud.js.map +0 -1
- package/dist/wu-status.js.map +0 -1
- package/dist/wu-unblock.js.map +0 -1
- package/dist/wu-unlock-lane.js.map +0 -1
- package/dist/wu-validate.js.map +0 -1
package/dist/onboard.js
CHANGED
|
@@ -20,34 +20,299 @@ import * as fs from 'node:fs';
|
|
|
20
20
|
import * as path from 'node:path';
|
|
21
21
|
import { execFileSync } from 'node:child_process';
|
|
22
22
|
import { createWUParser } from '@lumenflow/core';
|
|
23
|
-
import {
|
|
23
|
+
import { WorkspaceControlPlaneConfigSchema, } from '@lumenflow/kernel';
|
|
24
24
|
import YAML from 'yaml';
|
|
25
|
-
import { buildWorkspaceConfig, generateWorkspaceYaml } from './workspace-init.js';
|
|
25
|
+
import { buildWorkspaceConfig, CANONICAL_BOOTSTRAP_COMMAND, DEFAULT_DENY_OVERLAYS, DEFAULT_LANE_TITLE, DEFAULT_PROJECT_NAME, DEFAULT_SANDBOX_NETWORK_PROFILE, WORKSPACE_FILENAME, generateWorkspaceYaml, } from './workspace-init.js';
|
|
26
26
|
import { DEFAULT_REGISTRY_URL, installPackFromRegistry } from './pack-install.js';
|
|
27
27
|
import { runCLI } from './cli-entry-point.js';
|
|
28
28
|
// --- Constants ---
|
|
29
29
|
export const LOG_PREFIX = '[onboard]';
|
|
30
|
+
const LEGACY_MARKER = 'legacy';
|
|
31
|
+
const LEGACY_ONBOARD_ENTRYPOINT = 'onboard';
|
|
32
|
+
const LEGACY_ONBOARD_ALIAS = 'lumenflow-onboard';
|
|
33
|
+
const LEGACY_ONBOARD_CONNECT_ENTRYPOINT = `${LEGACY_ONBOARD_ENTRYPOINT} connect`;
|
|
34
|
+
const CANONICAL_CLOUD_CONNECT_COMMAND = 'npx lumenflow cloud connect';
|
|
35
|
+
const LEGACY_ONBOARD_MESSAGE_PREFIX = `${LOG_PREFIX} ${LEGACY_MARKER} entrypoint`;
|
|
30
36
|
const NODE_BINARY = 'node';
|
|
31
37
|
const GIT_BINARY = 'git';
|
|
32
38
|
const DEFAULT_DOMAIN_PACK_VERSION = 'latest';
|
|
39
|
+
const DOMAIN_IDS = {
|
|
40
|
+
SOFTWARE_DELIVERY: 'software-delivery',
|
|
41
|
+
INFRA: 'infra',
|
|
42
|
+
CUSTOM: 'custom',
|
|
43
|
+
};
|
|
44
|
+
const DOMAIN_PACK_IDS = {
|
|
45
|
+
SOFTWARE_DELIVERY: 'software-delivery',
|
|
46
|
+
INFRA: 'infra',
|
|
47
|
+
};
|
|
48
|
+
const DEFAULT_ONBOARD_LANE_TITLE = DEFAULT_LANE_TITLE;
|
|
49
|
+
const DOMAIN_DEFAULT_PACKS = {
|
|
50
|
+
[DOMAIN_IDS.SOFTWARE_DELIVERY]: [DOMAIN_PACK_IDS.SOFTWARE_DELIVERY],
|
|
51
|
+
[DOMAIN_IDS.INFRA]: [DOMAIN_PACK_IDS.INFRA],
|
|
52
|
+
[DOMAIN_IDS.CUSTOM]: [],
|
|
53
|
+
};
|
|
54
|
+
const DOMAIN_DEFAULT_LANES = {
|
|
55
|
+
[DOMAIN_IDS.SOFTWARE_DELIVERY]: ['Backend', 'Frontend', 'DevOps'],
|
|
56
|
+
[DOMAIN_IDS.INFRA]: ['Provisioning', 'Networking', 'Security'],
|
|
57
|
+
[DOMAIN_IDS.CUSTOM]: [DEFAULT_ONBOARD_LANE_TITLE],
|
|
58
|
+
};
|
|
59
|
+
const DOMAIN_EMPTY_PACK_ID = 'none';
|
|
60
|
+
const ONBOARD_DEFAULT_DOMAIN = DOMAIN_IDS.SOFTWARE_DELIVERY;
|
|
61
|
+
const ONBOARD_FALLBACK_PROJECT_NAME = DEFAULT_PROJECT_NAME;
|
|
62
|
+
const ONBOARD_SUBCOMMAND_CONNECT = 'connect';
|
|
63
|
+
const CLOUD_CONNECT_LOG_PREFIX = '[cloud connect]';
|
|
64
|
+
const CLOUD_CONNECT_DEFAULT_TOKEN_ENV = 'LUMENFLOW_CONTROL_PLANE_TOKEN';
|
|
65
|
+
const CLOUD_CONNECT_DEFAULT_SYNC_INTERVAL_SECONDS = 30;
|
|
66
|
+
const CLOUD_CONNECT_POLICY_MODES = {
|
|
67
|
+
AUTHORITATIVE: 'authoritative',
|
|
68
|
+
TIGHTEN_ONLY: 'tighten-only',
|
|
69
|
+
DEV_OVERRIDE: 'dev-override',
|
|
70
|
+
};
|
|
71
|
+
const CLOUD_CONNECT_DEFAULT_POLICY_MODE = CLOUD_CONNECT_POLICY_MODES.TIGHTEN_ONLY;
|
|
72
|
+
const CLOUD_CONNECT_ALLOWED_POLICY_MODES = new Set([
|
|
73
|
+
CLOUD_CONNECT_POLICY_MODES.AUTHORITATIVE,
|
|
74
|
+
CLOUD_CONNECT_POLICY_MODES.TIGHTEN_ONLY,
|
|
75
|
+
CLOUD_CONNECT_POLICY_MODES.DEV_OVERRIDE,
|
|
76
|
+
]);
|
|
77
|
+
const CLOUD_CONNECT_ALLOWED_POLICY_MODE_NAMES = new Set([
|
|
78
|
+
...CLOUD_CONNECT_ALLOWED_POLICY_MODES,
|
|
79
|
+
]);
|
|
80
|
+
const CLOUD_CONNECT_SECURE_PROTOCOL = 'https:';
|
|
81
|
+
const CLOUD_CONNECT_LOCAL_PROTOCOL = 'http:';
|
|
82
|
+
const CLOUD_CONNECT_LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
|
|
83
|
+
const CLOUD_CONNECT_ENV_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
84
|
+
const CLOUD_CONNECT_HELP_HINT = 'Example: npx lumenflow cloud connect --endpoint https://cp.example --org-id org-1 --project-id project-1 --token-env LUMENFLOW_CONTROL_PLANE_TOKEN';
|
|
85
|
+
const YAML_TRAILING_NEWLINE = '\n';
|
|
86
|
+
export function buildLegacyOnboardGuidance(entrypoint = LEGACY_ONBOARD_ENTRYPOINT) {
|
|
87
|
+
return (`${LEGACY_ONBOARD_MESSAGE_PREFIX} "${entrypoint}" is retired. ` +
|
|
88
|
+
`Use "${CANONICAL_BOOTSTRAP_COMMAND}" for bootstrap-all onboarding.`);
|
|
89
|
+
}
|
|
90
|
+
function buildLegacyCloudConnectGuidance(entrypoint = LEGACY_ONBOARD_CONNECT_ENTRYPOINT) {
|
|
91
|
+
return (`${LEGACY_ONBOARD_MESSAGE_PREFIX} "${entrypoint}" is retired. ` +
|
|
92
|
+
`Use "${CANONICAL_CLOUD_CONNECT_COMMAND}" instead.`);
|
|
93
|
+
}
|
|
33
94
|
/** Domain pack IDs mapped to human-readable descriptions */
|
|
34
95
|
export const DOMAIN_CHOICES = [
|
|
35
96
|
{
|
|
36
|
-
value:
|
|
97
|
+
value: DOMAIN_IDS.SOFTWARE_DELIVERY,
|
|
37
98
|
label: 'Software Delivery',
|
|
38
99
|
hint: 'Git tools, worktree isolation, quality gates, lane locking',
|
|
39
100
|
},
|
|
40
101
|
{
|
|
41
|
-
value:
|
|
102
|
+
value: DOMAIN_IDS.INFRA,
|
|
42
103
|
label: 'Infrastructure',
|
|
43
104
|
hint: 'Terraform, Ansible, cloud resource management',
|
|
44
105
|
},
|
|
45
106
|
{
|
|
46
|
-
value:
|
|
107
|
+
value: DOMAIN_IDS.CUSTOM,
|
|
47
108
|
label: 'Custom (empty)',
|
|
48
109
|
hint: 'Start with an empty workspace and add packs manually',
|
|
49
110
|
},
|
|
50
111
|
];
|
|
112
|
+
const CLOUD_CONNECT_OPTIONS = {
|
|
113
|
+
endpoint: {
|
|
114
|
+
name: 'endpoint',
|
|
115
|
+
flags: '--endpoint <url>',
|
|
116
|
+
description: 'Cloud control-plane endpoint URL',
|
|
117
|
+
},
|
|
118
|
+
orgId: {
|
|
119
|
+
name: 'orgId',
|
|
120
|
+
flags: '--org-id <id>',
|
|
121
|
+
description: 'Cloud organization identifier',
|
|
122
|
+
},
|
|
123
|
+
projectId: {
|
|
124
|
+
name: 'projectId',
|
|
125
|
+
flags: '--project-id <id>',
|
|
126
|
+
description: 'Cloud project identifier',
|
|
127
|
+
},
|
|
128
|
+
tokenEnv: {
|
|
129
|
+
name: 'tokenEnv',
|
|
130
|
+
flags: '--token-env <name>',
|
|
131
|
+
description: `Environment variable containing cloud auth token (default: ${CLOUD_CONNECT_DEFAULT_TOKEN_ENV})`,
|
|
132
|
+
},
|
|
133
|
+
policyMode: {
|
|
134
|
+
name: 'policyMode',
|
|
135
|
+
flags: '--policy-mode <mode>',
|
|
136
|
+
description: 'Policy mode: authoritative, tighten-only, dev-override',
|
|
137
|
+
},
|
|
138
|
+
syncInterval: {
|
|
139
|
+
name: 'syncInterval',
|
|
140
|
+
flags: '--sync-interval <seconds>',
|
|
141
|
+
description: 'Control-plane sync interval in seconds (positive integer)',
|
|
142
|
+
},
|
|
143
|
+
output: {
|
|
144
|
+
name: 'output',
|
|
145
|
+
flags: '--output, -o <dir>',
|
|
146
|
+
description: 'Workspace root directory (default: current directory)',
|
|
147
|
+
},
|
|
148
|
+
force: {
|
|
149
|
+
name: 'force',
|
|
150
|
+
flags: '--force, -f',
|
|
151
|
+
description: 'Overwrite existing control_plane section in workspace.yaml',
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
function isRecord(value) {
|
|
155
|
+
return typeof value === 'object' && value !== null;
|
|
156
|
+
}
|
|
157
|
+
function parsePositiveInt(value, fieldName) {
|
|
158
|
+
const parsedValue = typeof value === 'number' ? value : Number(value);
|
|
159
|
+
if (!Number.isInteger(parsedValue) || parsedValue <= 0) {
|
|
160
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid ${fieldName}: expected a positive integer`);
|
|
161
|
+
}
|
|
162
|
+
return parsedValue;
|
|
163
|
+
}
|
|
164
|
+
function parsePolicyMode(value) {
|
|
165
|
+
if (typeof value !== 'string' || !CLOUD_CONNECT_ALLOWED_POLICY_MODE_NAMES.has(value)) {
|
|
166
|
+
const allowedValues = [...CLOUD_CONNECT_ALLOWED_POLICY_MODES].join(', ');
|
|
167
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --policy-mode "${String(value)}". Valid values: ${allowedValues}`);
|
|
168
|
+
}
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
function validateEndpoint(endpoint) {
|
|
172
|
+
let parsedEndpoint;
|
|
173
|
+
try {
|
|
174
|
+
parsedEndpoint = new URL(endpoint);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid endpoint "${endpoint}": expected a valid URL`);
|
|
178
|
+
}
|
|
179
|
+
const isSecureProtocol = parsedEndpoint.protocol === CLOUD_CONNECT_SECURE_PROTOCOL;
|
|
180
|
+
const isLocalHost = CLOUD_CONNECT_LOCAL_HOSTS.has(parsedEndpoint.hostname);
|
|
181
|
+
const isLocalHttp = parsedEndpoint.protocol === CLOUD_CONNECT_LOCAL_PROTOCOL && isLocalHost === true;
|
|
182
|
+
if (!isSecureProtocol && !isLocalHttp) {
|
|
183
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Endpoint must use https (or http for localhost only): ${endpoint}`);
|
|
184
|
+
}
|
|
185
|
+
const normalizedEndpoint = parsedEndpoint.toString();
|
|
186
|
+
return normalizedEndpoint.endsWith('/')
|
|
187
|
+
? normalizedEndpoint.slice(0, normalizedEndpoint.length - 1)
|
|
188
|
+
: normalizedEndpoint;
|
|
189
|
+
}
|
|
190
|
+
function validateTokenEnvName(tokenEnv) {
|
|
191
|
+
if (!CLOUD_CONNECT_ENV_NAME_PATTERN.test(tokenEnv)) {
|
|
192
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --token-env "${tokenEnv}": expected an uppercase environment variable name`);
|
|
193
|
+
}
|
|
194
|
+
return tokenEnv;
|
|
195
|
+
}
|
|
196
|
+
function ensureTokenValue(tokenEnv, env) {
|
|
197
|
+
const tokenValue = env[tokenEnv];
|
|
198
|
+
if (!tokenValue || tokenValue.trim().length === 0) {
|
|
199
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Missing token env "${tokenEnv}". Export it before connect. ${CLOUD_CONNECT_HELP_HINT}`);
|
|
200
|
+
}
|
|
201
|
+
return tokenValue;
|
|
202
|
+
}
|
|
203
|
+
function parseCloudConnectCliOptions() {
|
|
204
|
+
const opts = createWUParser({
|
|
205
|
+
name: 'cloud-connect',
|
|
206
|
+
description: 'Connect workspace.yaml to LumenFlow cloud control plane',
|
|
207
|
+
options: [
|
|
208
|
+
CLOUD_CONNECT_OPTIONS.endpoint,
|
|
209
|
+
CLOUD_CONNECT_OPTIONS.orgId,
|
|
210
|
+
CLOUD_CONNECT_OPTIONS.projectId,
|
|
211
|
+
CLOUD_CONNECT_OPTIONS.tokenEnv,
|
|
212
|
+
CLOUD_CONNECT_OPTIONS.policyMode,
|
|
213
|
+
CLOUD_CONNECT_OPTIONS.syncInterval,
|
|
214
|
+
CLOUD_CONNECT_OPTIONS.output,
|
|
215
|
+
CLOUD_CONNECT_OPTIONS.force,
|
|
216
|
+
],
|
|
217
|
+
required: [
|
|
218
|
+
CLOUD_CONNECT_OPTIONS.endpoint.name,
|
|
219
|
+
CLOUD_CONNECT_OPTIONS.orgId.name,
|
|
220
|
+
CLOUD_CONNECT_OPTIONS.projectId.name,
|
|
221
|
+
],
|
|
222
|
+
});
|
|
223
|
+
const tokenEnvRaw = opts.tokenEnv ?? CLOUD_CONNECT_DEFAULT_TOKEN_ENV;
|
|
224
|
+
const policyModeRaw = opts.policyMode ?? CLOUD_CONNECT_DEFAULT_POLICY_MODE;
|
|
225
|
+
const syncIntervalRaw = opts.syncInterval ??
|
|
226
|
+
CLOUD_CONNECT_DEFAULT_SYNC_INTERVAL_SECONDS;
|
|
227
|
+
return {
|
|
228
|
+
targetDir: (opts.output ?? process.cwd()).trim(),
|
|
229
|
+
endpoint: validateEndpoint(String(opts.endpoint)),
|
|
230
|
+
orgId: String(opts.orgId).trim(),
|
|
231
|
+
projectId: String(opts.projectId).trim(),
|
|
232
|
+
tokenEnv: validateTokenEnvName(tokenEnvRaw.trim()),
|
|
233
|
+
policyMode: parsePolicyMode(policyModeRaw),
|
|
234
|
+
syncInterval: parsePositiveInt(syncIntervalRaw, '--sync-interval'),
|
|
235
|
+
force: Boolean(opts.force),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function validateWorkspaceRootPath(targetDir) {
|
|
239
|
+
if (!targetDir || targetDir.trim().length === 0) {
|
|
240
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --output: path must be non-empty`);
|
|
241
|
+
}
|
|
242
|
+
return path.resolve(targetDir);
|
|
243
|
+
}
|
|
244
|
+
function readWorkspaceDocument(workspacePath) {
|
|
245
|
+
if (!fs.existsSync(workspacePath)) {
|
|
246
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} not found at ${workspacePath}. Run "lumenflow init" first to bootstrap a workspace.`);
|
|
247
|
+
}
|
|
248
|
+
const rawContent = fs.readFileSync(workspacePath, 'utf-8');
|
|
249
|
+
const parsedYaml = YAML.parse(rawContent);
|
|
250
|
+
if (!isRecord(parsedYaml)) {
|
|
251
|
+
throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} is malformed: expected YAML object at document root`);
|
|
252
|
+
}
|
|
253
|
+
return parsedYaml;
|
|
254
|
+
}
|
|
255
|
+
function buildControlPlaneConfig(input) {
|
|
256
|
+
const controlPlaneCandidate = {
|
|
257
|
+
endpoint: input.endpoint,
|
|
258
|
+
org_id: input.orgId,
|
|
259
|
+
project_id: input.projectId,
|
|
260
|
+
sync_interval: input.syncInterval,
|
|
261
|
+
policy_mode: input.policyMode,
|
|
262
|
+
auth: {
|
|
263
|
+
token_env: input.tokenEnv,
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
return WorkspaceControlPlaneConfigSchema.parse(controlPlaneCandidate);
|
|
267
|
+
}
|
|
268
|
+
export async function connectWorkspaceToCloud(options) {
|
|
269
|
+
try {
|
|
270
|
+
const workspaceRoot = validateWorkspaceRootPath(options.targetDir);
|
|
271
|
+
const workspacePath = path.join(workspaceRoot, WORKSPACE_FILENAME);
|
|
272
|
+
const workspaceDoc = readWorkspaceDocument(workspacePath);
|
|
273
|
+
const runtimeEnv = options.env ?? process.env;
|
|
274
|
+
ensureTokenValue(options.tokenEnv, runtimeEnv);
|
|
275
|
+
if (workspaceDoc.control_plane && !options.force) {
|
|
276
|
+
return {
|
|
277
|
+
success: false,
|
|
278
|
+
workspacePath,
|
|
279
|
+
error: `${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} already has control_plane configuration. ` +
|
|
280
|
+
'Use --force to overwrite.',
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
const controlPlaneConfig = buildControlPlaneConfig(options);
|
|
284
|
+
workspaceDoc.control_plane = controlPlaneConfig;
|
|
285
|
+
const serializedWorkspace = YAML.stringify(workspaceDoc);
|
|
286
|
+
const normalizedYaml = serializedWorkspace.endsWith(YAML_TRAILING_NEWLINE)
|
|
287
|
+
? serializedWorkspace
|
|
288
|
+
: `${serializedWorkspace}${YAML_TRAILING_NEWLINE}`;
|
|
289
|
+
fs.writeFileSync(workspacePath, normalizedYaml, 'utf-8');
|
|
290
|
+
return {
|
|
291
|
+
success: true,
|
|
292
|
+
workspacePath,
|
|
293
|
+
controlPlaneConfig,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
error: error instanceof Error ? error.message : String(error),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export async function runCloudConnectCli() {
|
|
304
|
+
const connectOptions = parseCloudConnectCliOptions();
|
|
305
|
+
const result = await connectWorkspaceToCloud(connectOptions);
|
|
306
|
+
if (!result.success) {
|
|
307
|
+
console.error(result.error ?? `${CLOUD_CONNECT_LOG_PREFIX} Cloud connect failed`);
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
console.log(`${CLOUD_CONNECT_LOG_PREFIX} Updated ${WORKSPACE_FILENAME}`);
|
|
311
|
+
console.log(`${CLOUD_CONNECT_LOG_PREFIX} Endpoint: ${connectOptions.endpoint}`);
|
|
312
|
+
console.log(`${CLOUD_CONNECT_LOG_PREFIX} Org ID: ${connectOptions.orgId}`);
|
|
313
|
+
console.log(`${CLOUD_CONNECT_LOG_PREFIX} Project ID: ${connectOptions.projectId}`);
|
|
314
|
+
console.log(`${CLOUD_CONNECT_LOG_PREFIX} Token env: ${connectOptions.tokenEnv}`);
|
|
315
|
+
}
|
|
51
316
|
/**
|
|
52
317
|
* Get version of a CLI tool by running it with a version flag.
|
|
53
318
|
* Returns 'not found' if the tool is not available.
|
|
@@ -77,7 +342,7 @@ function getToolVersion(binary, args) {
|
|
|
77
342
|
export async function detectEnvironment(targetDir) {
|
|
78
343
|
const nodeVersion = getToolVersion(NODE_BINARY, ['--version']);
|
|
79
344
|
const gitVersion = getToolVersion(GIT_BINARY, ['--version']);
|
|
80
|
-
const workspacePath = path.join(targetDir,
|
|
345
|
+
const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
|
|
81
346
|
const existingWorkspace = fs.existsSync(workspacePath);
|
|
82
347
|
return {
|
|
83
348
|
node: {
|
|
@@ -98,14 +363,7 @@ export async function detectEnvironment(targetDir) {
|
|
|
98
363
|
* @returns Array of pack IDs to include
|
|
99
364
|
*/
|
|
100
365
|
function getPacksForDomain(domain) {
|
|
101
|
-
|
|
102
|
-
case 'software-delivery':
|
|
103
|
-
return ['software-delivery'];
|
|
104
|
-
case 'infra':
|
|
105
|
-
return ['infra'];
|
|
106
|
-
case 'custom':
|
|
107
|
-
return [];
|
|
108
|
-
}
|
|
366
|
+
return [...DOMAIN_DEFAULT_PACKS[domain]];
|
|
109
367
|
}
|
|
110
368
|
/**
|
|
111
369
|
* Build lane configuration for a given domain.
|
|
@@ -114,14 +372,7 @@ function getPacksForDomain(domain) {
|
|
|
114
372
|
* @returns Array of lane titles
|
|
115
373
|
*/
|
|
116
374
|
function getLanesForDomain(domain) {
|
|
117
|
-
|
|
118
|
-
case 'software-delivery':
|
|
119
|
-
return ['Backend', 'Frontend', 'DevOps'];
|
|
120
|
-
case 'infra':
|
|
121
|
-
return ['Provisioning', 'Networking', 'Security'];
|
|
122
|
-
case 'custom':
|
|
123
|
-
return ['Default'];
|
|
124
|
-
}
|
|
375
|
+
return [...DOMAIN_DEFAULT_LANES[domain]];
|
|
125
376
|
}
|
|
126
377
|
/**
|
|
127
378
|
* Convert a string to kebab-case.
|
|
@@ -140,12 +391,12 @@ function toKebabCase(input) {
|
|
|
140
391
|
* @returns Result of workspace generation
|
|
141
392
|
*/
|
|
142
393
|
export async function generateWorkspaceForDomain(targetDir, options) {
|
|
143
|
-
const workspacePath = path.join(targetDir,
|
|
394
|
+
const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
|
|
144
395
|
// Check for existing file
|
|
145
396
|
if (fs.existsSync(workspacePath) && !options.force) {
|
|
146
397
|
return {
|
|
147
398
|
success: false,
|
|
148
|
-
error: `${
|
|
399
|
+
error: `${WORKSPACE_FILENAME} already exists at ${workspacePath}. Use --force to overwrite.`,
|
|
149
400
|
};
|
|
150
401
|
}
|
|
151
402
|
const lanes = getLanesForDomain(options.domain);
|
|
@@ -154,8 +405,8 @@ export async function generateWorkspaceForDomain(targetDir, options) {
|
|
|
154
405
|
const config = buildWorkspaceConfig({
|
|
155
406
|
projectName: options.projectName,
|
|
156
407
|
lanes,
|
|
157
|
-
sandboxProfile:
|
|
158
|
-
deniedPaths: [
|
|
408
|
+
sandboxProfile: DEFAULT_SANDBOX_NETWORK_PROFILE,
|
|
409
|
+
deniedPaths: [...DEFAULT_DENY_OVERLAYS],
|
|
159
410
|
cloudConnect: false,
|
|
160
411
|
});
|
|
161
412
|
// Installable packs are added in AC4 via installDomainPack.
|
|
@@ -191,7 +442,7 @@ export async function installDomainPack(targetDir, options) {
|
|
|
191
442
|
const packs = getPacksForDomain(options.domain);
|
|
192
443
|
if (packs.length === 0) {
|
|
193
444
|
return {
|
|
194
|
-
packId:
|
|
445
|
+
packId: DOMAIN_EMPTY_PACK_ID,
|
|
195
446
|
skipped: true,
|
|
196
447
|
reason: `No packs to install for custom domain. Add packs manually with: pnpm pack:install --id <pack-id>`,
|
|
197
448
|
};
|
|
@@ -225,7 +476,7 @@ export async function installDomainPack(targetDir, options) {
|
|
|
225
476
|
let installedVersion;
|
|
226
477
|
let installedIntegrity;
|
|
227
478
|
try {
|
|
228
|
-
const workspacePath = path.join(targetDir,
|
|
479
|
+
const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
|
|
229
480
|
const workspaceRaw = fs.readFileSync(workspacePath, 'utf-8');
|
|
230
481
|
const parsed = YAML.parse(workspaceRaw);
|
|
231
482
|
const installedPack = (parsed.packs ?? []).find((entry) => entry.id === packId);
|
|
@@ -284,7 +535,7 @@ export async function launchDashboard(targetDir, options = {}) {
|
|
|
284
535
|
* @returns Onboard result
|
|
285
536
|
*/
|
|
286
537
|
export async function runOnboard(options) {
|
|
287
|
-
const { targetDir, projectName =
|
|
538
|
+
const { targetDir, projectName = ONBOARD_FALLBACK_PROJECT_NAME, domain = ONBOARD_DEFAULT_DOMAIN, force = false, skipPackInstall = false, skipDashboard = false, registryUrl = DEFAULT_REGISTRY_URL, fetchFn = globalThis.fetch, } = options;
|
|
288
539
|
const errors = [];
|
|
289
540
|
const result = {
|
|
290
541
|
success: false,
|
|
@@ -344,7 +595,7 @@ export async function runOnboard(options) {
|
|
|
344
595
|
*
|
|
345
596
|
* This is the main entry point for interactive mode.
|
|
346
597
|
*/
|
|
347
|
-
async function
|
|
598
|
+
async function _runInteractiveOnboard(targetDir, force) {
|
|
348
599
|
// Dynamic import to avoid loading @clack/prompts in non-interactive mode
|
|
349
600
|
const clack = await import('@clack/prompts');
|
|
350
601
|
clack.intro('Welcome to LumenFlow');
|
|
@@ -367,8 +618,8 @@ async function runInteractiveOnboard(targetDir, force) {
|
|
|
367
618
|
// Step 2: Project name
|
|
368
619
|
const projectName = await clack.text({
|
|
369
620
|
message: 'Project name',
|
|
370
|
-
placeholder:
|
|
371
|
-
defaultValue:
|
|
621
|
+
placeholder: ONBOARD_FALLBACK_PROJECT_NAME,
|
|
622
|
+
defaultValue: ONBOARD_FALLBACK_PROJECT_NAME,
|
|
372
623
|
validate: (value) => {
|
|
373
624
|
if (!value?.trim())
|
|
374
625
|
return 'Project name is required';
|
|
@@ -406,7 +657,7 @@ async function runInteractiveOnboard(targetDir, force) {
|
|
|
406
657
|
}
|
|
407
658
|
spinner.stop('workspace.yaml created');
|
|
408
659
|
// Step 5: Install pack (AC4)
|
|
409
|
-
if (domain !==
|
|
660
|
+
if (domain !== DOMAIN_IDS.CUSTOM) {
|
|
410
661
|
spinner.start(`Installing ${domain} pack...`);
|
|
411
662
|
const installResult = await installDomainPack(targetDir, {
|
|
412
663
|
domain: domain,
|
|
@@ -422,108 +673,32 @@ async function runInteractiveOnboard(targetDir, force) {
|
|
|
422
673
|
const dashResult = await launchDashboard(targetDir);
|
|
423
674
|
// Final summary
|
|
424
675
|
clack.note([
|
|
425
|
-
`Workspace: ${
|
|
676
|
+
`Workspace: ${WORKSPACE_FILENAME}`,
|
|
426
677
|
`Domain: ${domain}`,
|
|
427
678
|
`Dashboard: ${dashResult.instruction}`,
|
|
428
679
|
'',
|
|
429
680
|
'Next steps:',
|
|
430
681
|
' 1. Run "lumenflow init" to scaffold agent config files',
|
|
431
|
-
|
|
682
|
+
` 2. Create your first task: pnpm wu:create --lane "${DEFAULT_LANE_TITLE}" --title "My first task"`,
|
|
432
683
|
' 3. Claim it: pnpm wu:claim --id WU-1',
|
|
433
684
|
].join('\n'), 'Setup complete');
|
|
434
685
|
clack.outro('Happy building!');
|
|
435
686
|
}
|
|
436
687
|
// --- CLI entry point ---
|
|
437
|
-
const ONBOARD_OPTIONS = {
|
|
438
|
-
yes: {
|
|
439
|
-
name: 'yes',
|
|
440
|
-
flags: '--yes, -y',
|
|
441
|
-
description: 'Accept all defaults non-interactively',
|
|
442
|
-
},
|
|
443
|
-
domain: {
|
|
444
|
-
name: 'domain',
|
|
445
|
-
flags: '--domain <domain>',
|
|
446
|
-
description: 'Domain pack: software-delivery, infra, or custom',
|
|
447
|
-
},
|
|
448
|
-
projectName: {
|
|
449
|
-
name: 'projectName',
|
|
450
|
-
flags: '--project-name <name>',
|
|
451
|
-
description: 'Project name (default: directory name or "my-project")',
|
|
452
|
-
},
|
|
453
|
-
output: {
|
|
454
|
-
name: 'output',
|
|
455
|
-
flags: '--output, -o <dir>',
|
|
456
|
-
description: 'Output directory (default: current directory)',
|
|
457
|
-
},
|
|
458
|
-
force: {
|
|
459
|
-
name: 'force',
|
|
460
|
-
flags: '--force, -f',
|
|
461
|
-
description: 'Overwrite existing workspace.yaml',
|
|
462
|
-
},
|
|
463
|
-
skipPackInstall: {
|
|
464
|
-
name: 'skipPackInstall',
|
|
465
|
-
flags: '--skip-pack-install',
|
|
466
|
-
description: 'Skip pack installation step',
|
|
467
|
-
},
|
|
468
|
-
skipDashboard: {
|
|
469
|
-
name: 'skipDashboard',
|
|
470
|
-
flags: '--skip-dashboard',
|
|
471
|
-
description: 'Skip dashboard launch step',
|
|
472
|
-
},
|
|
473
|
-
};
|
|
474
688
|
/**
|
|
475
689
|
* CLI main entry point for lumenflow onboard
|
|
476
690
|
*/
|
|
477
691
|
export async function main() {
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
ONBOARD_OPTIONS.force,
|
|
487
|
-
ONBOARD_OPTIONS.skipPackInstall,
|
|
488
|
-
ONBOARD_OPTIONS.skipDashboard,
|
|
489
|
-
],
|
|
490
|
-
});
|
|
491
|
-
const targetDir = opts.output ?? process.cwd();
|
|
492
|
-
const force = Boolean(opts.force);
|
|
493
|
-
const useDefaults = Boolean(opts.yes);
|
|
494
|
-
const domain = opts.domain ?? 'software-delivery';
|
|
495
|
-
const projectName = opts.projectName ?? path.basename(path.resolve(targetDir));
|
|
496
|
-
const skipPackInstall = Boolean(opts.skipPackInstall);
|
|
497
|
-
const skipDashboard = Boolean(opts.skipDashboard);
|
|
498
|
-
if (useDefaults) {
|
|
499
|
-
// Non-interactive mode
|
|
500
|
-
const result = await runOnboard({
|
|
501
|
-
targetDir,
|
|
502
|
-
nonInteractive: true,
|
|
503
|
-
projectName,
|
|
504
|
-
domain,
|
|
505
|
-
force,
|
|
506
|
-
skipPackInstall,
|
|
507
|
-
skipDashboard,
|
|
508
|
-
});
|
|
509
|
-
if (!result.success) {
|
|
510
|
-
console.error(`${LOG_PREFIX} Onboarding failed:`);
|
|
511
|
-
for (const error of result.errors) {
|
|
512
|
-
console.error(` - ${error}`);
|
|
513
|
-
}
|
|
514
|
-
process.exit(1);
|
|
515
|
-
}
|
|
516
|
-
console.log(`${LOG_PREFIX} Workspace created at ${targetDir}/${WORKSPACE_FILE_NAME}`);
|
|
517
|
-
console.log(`${LOG_PREFIX} Domain: ${domain}`);
|
|
518
|
-
if (!skipPackInstall && result.packInstalled === false) {
|
|
519
|
-
console.warn(`${LOG_PREFIX} Warning: Pack install did not complete. Retry with: pnpm pack:install --id ${domain} --source registry --version ${DEFAULT_DOMAIN_PACK_VERSION}`);
|
|
520
|
-
}
|
|
521
|
-
console.log(`${LOG_PREFIX} Next: run "lumenflow init" to scaffold agent config files`);
|
|
522
|
-
}
|
|
523
|
-
else {
|
|
524
|
-
// Interactive mode with @clack/prompts
|
|
525
|
-
await runInteractiveOnboard(targetDir, force);
|
|
692
|
+
const invokedBinary = path.basename(process.argv[1] ?? LEGACY_ONBOARD_ENTRYPOINT, '.js');
|
|
693
|
+
const invokedEntrypoint = invokedBinary === LEGACY_ONBOARD_ALIAS ? LEGACY_ONBOARD_ALIAS : LEGACY_ONBOARD_ENTRYPOINT;
|
|
694
|
+
const subcommand = process.argv[2];
|
|
695
|
+
if (subcommand === ONBOARD_SUBCOMMAND_CONNECT) {
|
|
696
|
+
console.warn(buildLegacyCloudConnectGuidance(`${invokedEntrypoint} ${ONBOARD_SUBCOMMAND_CONNECT}`));
|
|
697
|
+
process.argv.splice(2, 1);
|
|
698
|
+
await runCloudConnectCli();
|
|
699
|
+
return;
|
|
526
700
|
}
|
|
701
|
+
console.warn(buildLegacyOnboardGuidance(invokedEntrypoint));
|
|
527
702
|
}
|
|
528
703
|
// Run if executed directly
|
|
529
704
|
if (import.meta.main) {
|
|
@@ -15,11 +15,10 @@ import { existsSync, readdirSync } from 'node:fs';
|
|
|
15
15
|
import { loadInitiativeWUs, calculateProgress, formatProgress, getLaneAvailability, resolveLaneConfigsFromConfig, } from '@lumenflow/initiatives';
|
|
16
16
|
import { EXIT_CODES, LUMENFLOW_PATHS } from '@lumenflow/core/wu-constants';
|
|
17
17
|
import { getConfig } from '@lumenflow/core/config';
|
|
18
|
+
import { getErrorMessage, ProcessExitError } from '@lumenflow/core/error-handler';
|
|
18
19
|
import chalk from 'chalk';
|
|
20
|
+
import { runCLI } from './cli-entry-point.js';
|
|
19
21
|
const LOG_PREFIX = '[orchestrate:init-status]';
|
|
20
|
-
function getErrorMessage(error) {
|
|
21
|
-
return error instanceof Error ? error.message : String(error);
|
|
22
|
-
}
|
|
23
22
|
function normalizeLifecycleStatus(value) {
|
|
24
23
|
return typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
25
24
|
}
|
|
@@ -113,12 +112,18 @@ const program = new Command()
|
|
|
113
112
|
console.log(formatLaneAvailability(availability, laneConfigs));
|
|
114
113
|
}
|
|
115
114
|
catch (err) {
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
if (err instanceof ProcessExitError) {
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
const message = `${LOG_PREFIX} Error: ${getErrorMessage(err)}`;
|
|
119
|
+
console.error(chalk.red(message));
|
|
120
|
+
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
118
121
|
}
|
|
119
122
|
});
|
|
120
|
-
|
|
123
|
+
export async function main() {
|
|
124
|
+
await program.parseAsync(process.argv);
|
|
125
|
+
}
|
|
121
126
|
if (import.meta.main) {
|
|
122
|
-
|
|
127
|
+
void runCLI(main);
|
|
123
128
|
}
|
|
124
129
|
//# sourceMappingURL=orchestrate-init-status.js.map
|
|
@@ -16,9 +16,8 @@ import chalk from 'chalk';
|
|
|
16
16
|
import { loadInitiativeWUs, loadMultipleInitiatives, buildExecutionPlanWithLockPolicy, resolveLaneConfigsFromConfig, formatExecutionPlan, formatExecutionPlanWithEmbeddedSpawns, calculateProgress, formatProgress, buildCheckpointWave, formatCheckpointOutput, validateCheckpointFlags, resolveCheckpointModeAsync, LOG_PREFIX, } from '@lumenflow/initiatives';
|
|
17
17
|
import { EXIT_CODES } from '@lumenflow/core/wu-constants';
|
|
18
18
|
import { getConfig } from '@lumenflow/core/config';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
import { getErrorMessage, ProcessExitError } from '@lumenflow/core/error-handler';
|
|
20
|
+
import { runCLI } from './cli-entry-point.js';
|
|
22
21
|
const program = new Command()
|
|
23
22
|
.name('orchestrate-initiative')
|
|
24
23
|
.description('Orchestrate initiative execution with parallel agent spawning')
|
|
@@ -34,16 +33,18 @@ const program = new Command()
|
|
|
34
33
|
validateCheckpointFlags({ checkpointPerWave, dryRun, noCheckpoint });
|
|
35
34
|
}
|
|
36
35
|
catch (error) {
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const message = `${LOG_PREFIX} Error: ${getErrorMessage(error)}`;
|
|
37
|
+
console.error(chalk.red(message));
|
|
38
|
+
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
39
39
|
}
|
|
40
40
|
if (!initIds || initIds.length === 0) {
|
|
41
|
-
|
|
41
|
+
const message = `${LOG_PREFIX} Error: --initiative is required`;
|
|
42
|
+
console.error(chalk.red(message));
|
|
42
43
|
console.error('');
|
|
43
44
|
console.error('Usage:');
|
|
44
45
|
console.error(' pnpm orchestrate:initiative --initiative INIT-001');
|
|
45
46
|
console.error(' pnpm orchestrate:initiative --initiative INIT-001 --dry-run');
|
|
46
|
-
|
|
47
|
+
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
47
48
|
}
|
|
48
49
|
try {
|
|
49
50
|
console.log(chalk.cyan(`${LOG_PREFIX} Loading initiative(s): ${initIds.join(', ')}`));
|
|
@@ -70,8 +71,9 @@ const program = new Command()
|
|
|
70
71
|
const checkpointDecision = await resolveCheckpointModeAsync({ checkpointPerWave, noCheckpoint, dryRun }, wus);
|
|
71
72
|
if (checkpointDecision.enabled) {
|
|
72
73
|
if (initIds.length > 1) {
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
const message = `${LOG_PREFIX} Error: Checkpoint mode only supports single initiative`;
|
|
75
|
+
console.error(chalk.red(message));
|
|
76
|
+
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
75
77
|
}
|
|
76
78
|
const waveData = buildCheckpointWave(initIds[0], { dryRun });
|
|
77
79
|
if (!waveData) {
|
|
@@ -139,9 +141,18 @@ const program = new Command()
|
|
|
139
141
|
console.log(chalk.cyan('Copy the spawn XML above to execute agents.'));
|
|
140
142
|
}
|
|
141
143
|
catch (error) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
if (error instanceof ProcessExitError) {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
const message = `${LOG_PREFIX} Error: ${getErrorMessage(error)}`;
|
|
148
|
+
console.error(chalk.red(message));
|
|
149
|
+
throw new ProcessExitError(message, EXIT_CODES.ERROR);
|
|
144
150
|
}
|
|
145
151
|
});
|
|
146
|
-
|
|
152
|
+
export async function main() {
|
|
153
|
+
await program.parseAsync(process.argv);
|
|
154
|
+
}
|
|
155
|
+
if (import.meta.main) {
|
|
156
|
+
void runCLI(main);
|
|
157
|
+
}
|
|
147
158
|
//# sourceMappingURL=orchestrate-initiative.js.map
|