@msn-control/liftoff 0.5.0 → 0.6.0
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/assets/locks/frontend/package-lock.json +224 -168
- package/assets/locks/frontend/package.json +1 -1
- package/assets/locks/node-backend/package-lock.json +85 -31
- package/assets/locks/node-backend/package.json +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +137 -8
- package/dist/commands.js.map +1 -1
- package/dist/file-system.d.ts +7 -0
- package/dist/file-system.js +15 -3
- package/dist/file-system.js.map +1 -1
- package/dist/interactive.d.ts +6 -1
- package/dist/interactive.js +76 -5
- package/dist/interactive.js.map +1 -1
- package/dist/reconcile.d.ts +2 -0
- package/dist/reconcile.js +5 -0
- package/dist/reconcile.js.map +1 -1
- package/dist/templates.js +3 -1
- package/dist/templates.js.map +1 -1
- package/dist/update-impact.d.ts +23 -0
- package/dist/update-impact.js +127 -0
- package/dist/update-impact.js.map +1 -0
- package/docs/cli-reference.md +18 -2
- package/docs/configuration-and-manifests.md +3 -2
- package/docs/existing-repositories.md +5 -1
- package/docs/safety-and-consent.md +22 -7
- package/docs/troubleshooting.md +13 -6
- package/package.json +3 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { manifestDisplayPath } from './file-system.js';
|
|
2
|
+
export const dependencyDefinitionLogicalNames = Object.freeze([
|
|
3
|
+
'backend-pyproject',
|
|
4
|
+
'function-worker-requirements',
|
|
5
|
+
'node-backend-package',
|
|
6
|
+
'node-backend-lock',
|
|
7
|
+
'go-backend-module',
|
|
8
|
+
'go-backend-checksums',
|
|
9
|
+
'frontend-package',
|
|
10
|
+
'frontend-lock',
|
|
11
|
+
'power-apps-package',
|
|
12
|
+
'power-apps-lock'
|
|
13
|
+
]);
|
|
14
|
+
const dependencyDefinitionLogicalNameSet = new Set(dependencyDefinitionLogicalNames);
|
|
15
|
+
function comparePortable(left, right) {
|
|
16
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
17
|
+
}
|
|
18
|
+
function displayEntry(entry) {
|
|
19
|
+
const current = manifestDisplayPath(entry.pathParts);
|
|
20
|
+
return entry.previousPathParts
|
|
21
|
+
? `${manifestDisplayPath(entry.previousPathParts)} => ${current}`
|
|
22
|
+
: current;
|
|
23
|
+
}
|
|
24
|
+
function freezeSorted(values) {
|
|
25
|
+
return Object.freeze(values.sort(comparePortable));
|
|
26
|
+
}
|
|
27
|
+
function isActionable(entry) {
|
|
28
|
+
return entry.status !== 'orphan' &&
|
|
29
|
+
(entry.status !== 'unchanged' || entry.refreshHash === true);
|
|
30
|
+
}
|
|
31
|
+
export function buildUpdateImpact(entries) {
|
|
32
|
+
const creates = [];
|
|
33
|
+
const restores = [];
|
|
34
|
+
const replacements = [];
|
|
35
|
+
const moves = [];
|
|
36
|
+
const recordedStateRefreshes = [];
|
|
37
|
+
const conflicts = [];
|
|
38
|
+
const managedPathsRemoved = [];
|
|
39
|
+
const managedPathsRemovedOnOverwrite = [];
|
|
40
|
+
const orphansPreserved = [];
|
|
41
|
+
const dependencyDefinitions = [];
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
switch (entry.status) {
|
|
44
|
+
case 'new':
|
|
45
|
+
creates.push(manifestDisplayPath(entry.pathParts));
|
|
46
|
+
break;
|
|
47
|
+
case 'missing':
|
|
48
|
+
restores.push(manifestDisplayPath(entry.pathParts));
|
|
49
|
+
break;
|
|
50
|
+
case 'upgrade':
|
|
51
|
+
replacements.push(manifestDisplayPath(entry.pathParts));
|
|
52
|
+
break;
|
|
53
|
+
case 'moved':
|
|
54
|
+
if (entry.cleanMove) {
|
|
55
|
+
moves.push(displayEntry(entry));
|
|
56
|
+
if (entry.previousPathParts) {
|
|
57
|
+
managedPathsRemoved.push(manifestDisplayPath(entry.previousPathParts));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (entry.sourceModified && entry.previousPathParts) {
|
|
62
|
+
conflicts.push(manifestDisplayPath(entry.previousPathParts));
|
|
63
|
+
}
|
|
64
|
+
if (entry.destinationOccupied && !entry.destinationMatches) {
|
|
65
|
+
conflicts.push(manifestDisplayPath(entry.pathParts));
|
|
66
|
+
}
|
|
67
|
+
if (entry.previousPathParts) {
|
|
68
|
+
managedPathsRemovedOnOverwrite.push(manifestDisplayPath(entry.previousPathParts));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'conflict':
|
|
73
|
+
conflicts.push(manifestDisplayPath(entry.pathParts));
|
|
74
|
+
break;
|
|
75
|
+
case 'orphan':
|
|
76
|
+
orphansPreserved.push(manifestDisplayPath(entry.pathParts));
|
|
77
|
+
break;
|
|
78
|
+
case 'unchanged':
|
|
79
|
+
if (entry.refreshHash) {
|
|
80
|
+
recordedStateRefreshes.push(manifestDisplayPath(entry.pathParts));
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
if (isActionable(entry) &&
|
|
85
|
+
dependencyDefinitionLogicalNameSet.has(entry.logicalName)) {
|
|
86
|
+
dependencyDefinitions.push(manifestDisplayPath(entry.pathParts));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const frozenCreates = freezeSorted(creates);
|
|
90
|
+
const frozenRestores = freezeSorted(restores);
|
|
91
|
+
const frozenReplacements = freezeSorted(replacements);
|
|
92
|
+
const frozenMoves = freezeSorted(moves);
|
|
93
|
+
const frozenRefreshes = freezeSorted(recordedStateRefreshes);
|
|
94
|
+
const frozenConflicts = freezeSorted(conflicts);
|
|
95
|
+
const frozenManagedPaths = freezeSorted(managedPathsRemoved);
|
|
96
|
+
const frozenManagedOverwritePaths = freezeSorted(managedPathsRemovedOnOverwrite);
|
|
97
|
+
const frozenOrphans = freezeSorted(orphansPreserved);
|
|
98
|
+
const frozenDependencyDefinitions = freezeSorted(dependencyDefinitions);
|
|
99
|
+
const safeActionCount = frozenCreates.length +
|
|
100
|
+
frozenRestores.length +
|
|
101
|
+
frozenReplacements.length +
|
|
102
|
+
frozenMoves.length +
|
|
103
|
+
frozenRefreshes.length;
|
|
104
|
+
const hasSafeActions = safeActionCount > 0;
|
|
105
|
+
const hasActionableChanges = hasSafeActions || frozenConflicts.length > 0;
|
|
106
|
+
return Object.freeze({
|
|
107
|
+
creates: frozenCreates,
|
|
108
|
+
restores: frozenRestores,
|
|
109
|
+
replacements: frozenReplacements,
|
|
110
|
+
moves: frozenMoves,
|
|
111
|
+
recordedStateRefreshes: frozenRefreshes,
|
|
112
|
+
conflicts: frozenConflicts,
|
|
113
|
+
managedPathsRemoved: frozenManagedPaths,
|
|
114
|
+
managedPathsRemovedOnOverwrite: frozenManagedOverwritePaths,
|
|
115
|
+
orphansPreserved: frozenOrphans,
|
|
116
|
+
dependencyDefinitions: frozenDependencyDefinitions,
|
|
117
|
+
safeActionCount,
|
|
118
|
+
localOrUserOwnedFilesAtRisk: frozenConflicts.length,
|
|
119
|
+
manifestWillUpdate: hasActionableChanges,
|
|
120
|
+
installsDependencies: false,
|
|
121
|
+
deletesOrphans: false,
|
|
122
|
+
retainsBackupAfterSuccess: false,
|
|
123
|
+
hasSafeActions,
|
|
124
|
+
hasActionableChanges
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=update-impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-impact.js","sourceRoot":"","sources":["../src/update-impact.ts"],"names":[],"mappings":"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"}
|
package/docs/cli-reference.md
CHANGED
|
@@ -24,7 +24,7 @@ plan -> init or migrate -> validate and doctor -> update -> dev and infra helper
|
|
|
24
24
|
| `liftoff migrate <source>` | Creates a new sibling scaffold and filtered source copy without changing the source |
|
|
25
25
|
| `liftoff validate [project]` | Validates manifest identity, durable files, workload metadata, and framework markers |
|
|
26
26
|
| `liftoff doctor [project]` | Runs read-only workload-derived project and workstation diagnostics |
|
|
27
|
-
| `liftoff update [project]` | Reports
|
|
27
|
+
| `liftoff update [project]` | Reports drift and, in an interactive terminal, explains impact and asks before applying |
|
|
28
28
|
| `liftoff update --apply` | Applies safe changes, preserves unforced conflicts, and records the resulting manifest |
|
|
29
29
|
| `liftoff dev` | Prints workload-appropriate local development commands; it does not execute them |
|
|
30
30
|
| `liftoff infra` | Prints OpenTofu guidance for API workloads and reports infrastructure as not applicable for Power Apps |
|
|
@@ -69,6 +69,22 @@ liftoff update --apply
|
|
|
69
69
|
liftoff update --apply --force
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
With interactive input and output, plain `liftoff update` first reports drift
|
|
73
|
+
and its impact. Safe managed changes use a default-No confirmation. Local or
|
|
74
|
+
user-owned conflicts are listed separately and require another default-No
|
|
75
|
+
confirmation before replacement. Liftoff collects both decisions before any
|
|
76
|
+
preflight or write.
|
|
77
|
+
|
|
78
|
+
With redirected input or output, plain update remains a read-only check and
|
|
79
|
+
prints the explicit apply command. `--json` also remains prompt-free and
|
|
80
|
+
read-only unless combined with `--apply`. Explicit `--apply` and
|
|
81
|
+
`--apply --force` bypass prompts for automation.
|
|
82
|
+
|
|
83
|
+
The impact summary identifies affected dependency definitions, but update does
|
|
84
|
+
not install dependencies. Orphans are reported without deletion. Transaction
|
|
85
|
+
snapshots restore a failed update, but Liftoff retains no backup after a
|
|
86
|
+
successful overwrite; commit or copy local work first.
|
|
87
|
+
|
|
72
88
|
`--force` is valid only with `--apply`. It overwrites reported file conflicts;
|
|
73
89
|
it does not permit workload, API stack, GenAI pattern, framework, selected
|
|
74
90
|
agent, or user-supplied Power Apps starter identity changes.
|
|
@@ -89,7 +105,7 @@ Exit codes:
|
|
|
89
105
|
|
|
90
106
|
- `0`: success or a clean check.
|
|
91
107
|
- `1`: invalid input, unsafe state, or command failure.
|
|
92
|
-
- `2`: a read-only check found drift.
|
|
108
|
+
- `2`: a read-only check or declined interactive update found drift.
|
|
93
109
|
|
|
94
110
|
Raw installer, framework, and dependency child stdout and stderr are forwarded
|
|
95
111
|
unchanged.
|
|
@@ -67,8 +67,9 @@ Readers support schemas v2, v3, and v4:
|
|
|
67
67
|
- V3 normalizes flat GenAI or API identity plus framework and agent metadata.
|
|
68
68
|
- V4 represents the discriminated workload model, including Power Apps.
|
|
69
69
|
|
|
70
|
-
A
|
|
71
|
-
|
|
70
|
+
A non-interactive or JSON check, or a declined interactive update, leaves an
|
|
71
|
+
old manifest byte-for-byte unchanged. A successful explicit or interactively
|
|
72
|
+
accepted apply writes v4 only after the file transaction succeeds. Skipped
|
|
72
73
|
conflicts retain their recorded hashes.
|
|
73
74
|
|
|
74
75
|
## Artifact ownership
|
|
@@ -68,7 +68,11 @@ liftoff update
|
|
|
68
68
|
liftoff update --apply
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
In an interactive terminal, plain update reports drift and impact, then asks
|
|
72
|
+
with a default of No before applying safe managed changes. Local or user-owned
|
|
73
|
+
conflicts require a separate default-No overwrite decision. Redirected and
|
|
74
|
+
JSON checks remain read-only and prompt-free; use `--apply` for explicit
|
|
75
|
+
automation consent.
|
|
72
76
|
|
|
73
77
|
## Existing non-Liftoff application
|
|
74
78
|
|
|
@@ -50,24 +50,39 @@ Individual project files use temporary-file replacement. Initialization keeps
|
|
|
50
50
|
backups for replaced files and records created files and directories. A handled
|
|
51
51
|
merge failure restores or removes those entries in reverse order.
|
|
52
52
|
|
|
53
|
-
`liftoff update --apply` preflights all
|
|
54
|
-
file, move, delete, and manifest mutations
|
|
55
|
-
transaction. Schema upgrades are committed only after
|
|
56
|
-
succeed. A corrected retry converges from the restored
|
|
53
|
+
An accepted interactive update or `liftoff update --apply` preflights all
|
|
54
|
+
affected paths and applies generated file, move, delete, and manifest mutations
|
|
55
|
+
as one rollback-capable transaction. Schema upgrades are committed only after
|
|
56
|
+
the other mutations succeed. A corrected retry converges from the restored
|
|
57
|
+
state.
|
|
57
58
|
|
|
58
59
|
If automatic rollback itself cannot safely restore a path because another
|
|
59
60
|
process changed it, Liftoff reports the incomplete rollback rather than
|
|
60
61
|
overwriting unknown bytes.
|
|
61
62
|
|
|
63
|
+
Update snapshots exist only for rollback after a failed transaction. Liftoff
|
|
64
|
+
does not retain them as backups after success.
|
|
65
|
+
|
|
62
66
|
## Update ownership
|
|
63
67
|
|
|
64
|
-
`liftoff update`
|
|
68
|
+
Plain `liftoff update` always reports drift before any write:
|
|
65
69
|
|
|
66
70
|
- Clean generated files remain unchanged.
|
|
67
|
-
-
|
|
71
|
+
- In an interactive terminal, new, missing, untouched-upgrade, clean-move, and
|
|
72
|
+
recorded-state changes are summarized and offered through a default-No
|
|
73
|
+
confirmation.
|
|
74
|
+
- With redirected input or output, or with `--json`, update remains a
|
|
75
|
+
prompt-free read-only check unless `--apply` is explicitly supplied.
|
|
68
76
|
- Developer edits that also differ from the current template are conflicts.
|
|
69
|
-
-
|
|
77
|
+
- Safe-update consent does not authorize conflicts. Interactive conflicts are
|
|
78
|
+
listed by portable relative path and require a separate default-No overwrite
|
|
79
|
+
confirmation; automation uses `--apply --force`.
|
|
70
80
|
- Orphans are reported and left on disk for manual review.
|
|
81
|
+
- Dependency definitions may be updated, but update never installs
|
|
82
|
+
dependencies.
|
|
83
|
+
|
|
84
|
+
All interactive decisions are collected before preflight or mutation.
|
|
85
|
+
Declining the safe update changes nothing and leaves drift exit code 2.
|
|
71
86
|
|
|
72
87
|
Power Apps reconciliation reads only the packaged immutable starter. It does
|
|
73
88
|
not fetch the upstream repository. Workload kind and user-edited starter
|
package/docs/troubleshooting.md
CHANGED
|
@@ -67,14 +67,21 @@ hand-edited unsafe path.
|
|
|
67
67
|
|
|
68
68
|
## Update reports conflicts or orphans
|
|
69
69
|
|
|
70
|
-
`liftoff update`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
-
|
|
74
|
-
|
|
70
|
+
In an interactive terminal, `liftoff update` shows an impact summary and asks
|
|
71
|
+
before applying safe managed changes. The default answer is No.
|
|
72
|
+
|
|
73
|
+
- Local or user-owned conflicts are listed separately and require their own
|
|
74
|
+
default-No overwrite confirmation.
|
|
75
|
+
- With redirected input or output, review the report and apply safe changes
|
|
76
|
+
with `liftoff update --apply`.
|
|
77
|
+
- For prompt-free conflict replacement, use `liftoff update --apply --force`
|
|
78
|
+
only after reviewing every listed path.
|
|
75
79
|
- Orphans are never deleted automatically.
|
|
80
|
+
- Update reports dependency-definition impact but does not install
|
|
81
|
+
dependencies.
|
|
76
82
|
|
|
77
|
-
Commit local work before
|
|
83
|
+
Commit or copy local work before overwriting. Transaction rollback protects a
|
|
84
|
+
failed update, but Liftoff keeps no backup after success.
|
|
78
85
|
|
|
79
86
|
## Power Apps dependencies or CLI are missing
|
|
80
87
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@msn-control/liftoff",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Interactive CLI for governed GenAI, API, and Power Apps code app projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-only",
|
|
@@ -44,8 +44,10 @@
|
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsc -p tsconfig.json",
|
|
46
46
|
"test": "vitest run",
|
|
47
|
+
"audit:template-dependencies": "node scripts/audit-template-dependencies.mjs",
|
|
47
48
|
"refresh:power-apps-starter": "node scripts/refresh-power-apps-starter.mjs",
|
|
48
49
|
"smoke:package": "npm run build && node scripts/package-smoke-test.mjs",
|
|
50
|
+
"verify:standard-node-templates": "npm run build && node scripts/verify-standard-node-templates.mjs",
|
|
49
51
|
"verify:power-apps-starter": "npm run build && node scripts/verify-power-apps-starter.mjs",
|
|
50
52
|
"verify:release-identity": "npm run build && node scripts/verify-release-identity.mjs",
|
|
51
53
|
"verify:published": "npm run build && node scripts/verify-published-package.mjs",
|