@atlashub/smartstack-cli 4.45.0 → 4.47.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/package.json +1 -1
- package/templates/skills/business-analyse-develop/SKILL.md +2 -0
- package/templates/skills/business-analyse-develop/steps/step-00-init.md +2 -0
- package/templates/skills/business-analyse-develop/steps/step-01-v4-execute.md +10 -2
- package/templates/skills/business-analyse-handoff/references/acceptance-criteria.md +55 -21
- package/templates/skills/business-analyse-handoff/steps/step-00-validate.md +12 -17
package/package.json
CHANGED
|
@@ -149,6 +149,8 @@ When the user invokes `/business-analyse-develop`, they are giving you the instr
|
|
|
149
149
|
- Ask the user to choose between supervised/autonomous mode
|
|
150
150
|
- Wait for user input between modules
|
|
151
151
|
- Delegate the loop to sub-agents (except team mode and /apex delegation)
|
|
152
|
+
- Display a progress report then ask "shall I continue?" or present options (1/2/3)
|
|
153
|
+
- Pause because the scope is "large" or "ambitious" — execute ALL of it regardless of size
|
|
152
154
|
|
|
153
155
|
**The ONLY valid stop conditions are:**
|
|
154
156
|
- ALL objectives met / ALL tasks completed (→ report)
|
|
@@ -58,6 +58,8 @@ Ralph-loop is FULLY AUTONOMOUS by default. It executes ALL tasks from start to f
|
|
|
58
58
|
|
|
59
59
|
**DO NOT** ask the user to confirm, choose a mode, or approve execution.
|
|
60
60
|
**DO NOT** set max_iterations = 1 or any reduced value.
|
|
61
|
+
**DO NOT** display a progress report and then ask "shall I continue?" or present numbered options.
|
|
62
|
+
**DO NOT** pause because the scope seems large — 500+ files across 11 modules is NORMAL. Execute ALL of it.
|
|
61
63
|
|
|
62
64
|
The loop runs autonomously until:
|
|
63
65
|
- ALL tasks are completed (success)
|
|
@@ -7,6 +7,12 @@ next_step: steps/step-02-v4-verify.md
|
|
|
7
7
|
|
|
8
8
|
# Step 01-v4: Continuous Module Execution
|
|
9
9
|
|
|
10
|
+
## EXECUTION GUARANTEE — AUTONOMY RULES (MANDATORY)
|
|
11
|
+
|
|
12
|
+
> **NEVER stop between modules.** NEVER ask "shall I continue?". NEVER present options (1/2/3).
|
|
13
|
+
> **NEVER pause after a progress report.** Progress reports are LOG OUTPUT ONLY — print them and IMMEDIATELY continue to the next module.
|
|
14
|
+
> **The user invoked /business-analyse-develop to execute ALL modules to completion.** That is your mandate. Any stop that is not: all-complete, dead-end, or Ctrl+C is a **VIOLATION**.
|
|
15
|
+
|
|
10
16
|
## YOUR TASK
|
|
11
17
|
|
|
12
18
|
For each module in topological order, delegate the ENTIRE module implementation to `/apex -d` in a continuous session. Run quality gates at natural checkpoints. Let server-side compaction manage context.
|
|
@@ -102,12 +108,14 @@ grep -rn "Assert.True(true)\|Assert.Pass()\|// TODO\|throw new NotImplementedExc
|
|
|
102
108
|
|
|
103
109
|
If found → delegate fix to apex: "Replace stub tests with real implementations"
|
|
104
110
|
|
|
105
|
-
### 7. Module Complete
|
|
111
|
+
### 7. Module Complete — CONTINUE IMMEDIATELY
|
|
106
112
|
|
|
107
113
|
When ALL gates pass for a module:
|
|
108
114
|
1. Log checkpoint: `"Module {moduleCode}: ALL GATES PASS"`
|
|
109
115
|
2. Optionally append to progress.txt (human checkpoint)
|
|
110
|
-
3.
|
|
116
|
+
3. **IMMEDIATELY** advance to next module in queue — DO NOT pause, DO NOT ask user, DO NOT present options
|
|
117
|
+
|
|
118
|
+
> **ANTI-STOP GUARD:** After logging the progress report, your VERY NEXT action MUST be starting the next module delegation (`/apex -d`). If there are no more modules, go to step-02-v4-verify. Outputting a progress report and then waiting for user input is a **VIOLATION** of the execution guarantee.
|
|
111
119
|
|
|
112
120
|
---
|
|
113
121
|
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
| `entities.json` | Entity definitions | `entities[]` | — |
|
|
17
17
|
| `rules.json` | Business rules | `rules[]` | `businessRules[]` |
|
|
18
18
|
| `usecases.json` | Use cases | `useCases[]` | `usecases[]` (lowercase) |
|
|
19
|
-
| `permissions.json` | Roles and permission matrix | `permissionPaths[]` | `permissionSet.permissions[]`, `
|
|
20
|
-
| `screens.json` | UI screen specifications | `screens[]` | `sections[].resources[]` |
|
|
19
|
+
| `permissions.json` | Roles and permission matrix | `permissionPaths[]` | `permissionSet.permissions[]`, `basePermissions[]`, `actions[]`, `permissions[]` |
|
|
20
|
+
| `screens.json` | UI screen specifications | `screens[]` | `sections[].resources[]`, `sections[]`, `wireframes[]` |
|
|
21
21
|
|
|
22
22
|
The validation script **assembles** these files before checking.
|
|
23
23
|
|
|
@@ -66,17 +66,30 @@ const fs = require('fs');
|
|
|
66
66
|
const path = require('path');
|
|
67
67
|
const dir = process.argv[1];
|
|
68
68
|
|
|
69
|
-
// Load index.json
|
|
70
|
-
|
|
69
|
+
// Load index.json (optional — may not exist at module level)
|
|
70
|
+
let index = {};
|
|
71
|
+
const indexPath = path.join(dir, 'index.json');
|
|
72
|
+
if (fs.existsSync(indexPath)) {
|
|
73
|
+
index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
|
74
|
+
}
|
|
71
75
|
const files = index.files || {};
|
|
72
76
|
|
|
73
|
-
// Load flat files
|
|
77
|
+
// Load flat files: try index.json refs first, fallback to direct file load
|
|
74
78
|
function loadFile(key) {
|
|
79
|
+
// Strategy 1: resolve via index.json > files references
|
|
75
80
|
const ref = files[key];
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
if (ref && ref.path) {
|
|
82
|
+
const filePath = path.join(dir, ref.path);
|
|
83
|
+
if (fs.existsSync(filePath)) {
|
|
84
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Strategy 2: direct file load (module dirs without index.json)
|
|
88
|
+
const directPath = path.join(dir, key + '.json');
|
|
89
|
+
if (fs.existsSync(directPath)) {
|
|
90
|
+
return JSON.parse(fs.readFileSync(directPath, 'utf-8'));
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
const entitiesData = loadFile('entities') || {};
|
|
@@ -91,19 +104,40 @@ const hasReferencedEntities = (entitiesData.referencedEntities || []).length > 0
|
|
|
91
104
|
const useCases = usecasesData.useCases || usecasesData.usecases || [];
|
|
92
105
|
const rules = rulesData.rules || rulesData.businessRules || [];
|
|
93
106
|
|
|
94
|
-
// Permissions:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
// Permissions: try all known variants, extract into flat array
|
|
108
|
+
function extractPermissions(data) {
|
|
109
|
+
if (data.permissionPaths && data.permissionPaths.length > 0) return data.permissionPaths;
|
|
110
|
+
if (data.permissionSet && data.permissionSet.permissions && data.permissionSet.permissions.length > 0) {
|
|
111
|
+
return data.permissionSet.permissions.map(function(p) { return p.code || p.path || ''; });
|
|
112
|
+
}
|
|
113
|
+
if (data.basePermissions && data.basePermissions.length > 0) {
|
|
114
|
+
return data.basePermissions.map(function(p) { return p.code || p.path || ''; });
|
|
115
|
+
}
|
|
116
|
+
if (data.actions && data.actions.length > 0) {
|
|
117
|
+
return data.actions.map(function(a) { return a.code || ''; });
|
|
118
|
+
}
|
|
119
|
+
if (data.permissions && data.permissions.length > 0) {
|
|
120
|
+
return data.permissions.map(function(p) { return typeof p === 'string' ? p : (p.code || p.path || ''); });
|
|
121
|
+
}
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
const permissions = extractPermissions(permissionsData);
|
|
125
|
+
|
|
126
|
+
// Screens: canonical screens[] OR sections[] (with or without .resources sub-array)
|
|
127
|
+
function extractScreens(data) {
|
|
128
|
+
if (data.screens && data.screens.length > 0) return data.screens;
|
|
129
|
+
if (data.sections && data.sections.length > 0) {
|
|
130
|
+
// sections may contain resources[] or be screens themselves
|
|
131
|
+
var fromResources = data.sections.reduce(function(acc, s) { return acc.concat(s.resources || []); }, []);
|
|
132
|
+
return fromResources.length > 0 ? fromResources : data.sections;
|
|
133
|
+
}
|
|
134
|
+
if (data.wireframes && data.wireframes.length > 0) return data.wireframes;
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const allScreens = extractScreens(screensData);
|
|
105
138
|
|
|
106
|
-
|
|
139
|
+
// Status: from index.json if present, or 'specified' if module has thematic files but no index.json
|
|
140
|
+
const status = (index.metadata && index.metadata.status) || (Object.keys(index).length === 0 ? 'specified' : 'unknown');
|
|
107
141
|
|
|
108
142
|
const fails = [];
|
|
109
143
|
|
|
@@ -71,32 +71,27 @@ FOR each module:
|
|
|
71
71
|
|
|
72
72
|
### 4. Load Flat Files Per Module
|
|
73
73
|
|
|
74
|
-
For each module, load the separate JSON files
|
|
74
|
+
For each module, load the separate JSON files directly (index.json may not exist at module level):
|
|
75
75
|
|
|
76
76
|
```javascript
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
const permissionsData = READ(moduleDir + '/permissions.json');
|
|
84
|
-
const screensData = READ(moduleDir + '/screens.json');
|
|
77
|
+
// Load thematic files directly from module directory
|
|
78
|
+
const entitiesData = READ(moduleDir + '/entities.json') || {};
|
|
79
|
+
const usecasesData = READ(moduleDir + '/usecases.json') || {};
|
|
80
|
+
const rulesData = READ(moduleDir + '/rules.json') || {};
|
|
81
|
+
const permissionsData = READ(moduleDir + '/permissions.json') || {};
|
|
82
|
+
const screensData = READ(moduleDir + '/screens.json') || {};
|
|
85
83
|
|
|
86
84
|
// NORMALISATION: tolerate ba-writer + LLM field name variants
|
|
85
|
+
// See acceptance-criteria.md for the full extraction functions
|
|
87
86
|
const moduleData = {
|
|
88
|
-
index: READ(moduleDir + '/index.json'),
|
|
89
87
|
entities: entitiesData.entities || [],
|
|
90
88
|
hasReferencedEntities: (entitiesData.referencedEntities || []).length > 0,
|
|
91
89
|
useCases: usecasesData.useCases || usecasesData.usecases || [],
|
|
92
90
|
rules: rulesData.rules || rulesData.businessRules || [],
|
|
93
|
-
permissions: permissionsData
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
screens: (screensData.screens || []).length > 0
|
|
98
|
-
? screensData.screens
|
|
99
|
-
: (screensData.sections || []).flatMap(s => s.resources || [])
|
|
91
|
+
permissions: extractPermissions(permissionsData),
|
|
92
|
+
// tries: permissionPaths > permissionSet.permissions > basePermissions > actions > permissions
|
|
93
|
+
screens: extractScreens(screensData),
|
|
94
|
+
// tries: screens > sections[].resources > sections > wireframes
|
|
100
95
|
};
|
|
101
96
|
```
|
|
102
97
|
|