burhan-mop 0.1.0 → 0.1.2
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/{.memoryofplanet → .MOP}/PROTOCOL.md +40 -37
- package/{.memoryofplanet → .MOP}/STATE.json +11 -11
- package/{.memoryofplanet → .MOP}/config/defaults.json +2 -2
- package/.MOP/scripts/burhan-mop.mjs +257 -0
- package/{.memoryofplanet → .MOP}/scripts/mop-auto-deploy.mjs +5 -6
- package/{.memoryofplanet → .MOP}/scripts/mop-autosycn.mjs +24 -24
- package/{.memoryofplanet → .MOP}/scripts/mop-core.mjs +24 -24
- package/{.memoryofplanet → .MOP}/scripts/mop-workflow.mjs +17 -17
- package/.agents/AGENTS.md +7 -6
- package/.agents/skills/auto-deploy/SKILL.md +2 -2
- package/.agents/skills/autosycn/SKILL.md +10 -10
- package/.agents/skills/mop-help/SKILL.md +4 -4
- package/.agents/skills/ruflo-core/SKILL.md +2 -3
- package/.claude/skills/auto-deploy/SKILL.md +2 -2
- package/.claude/skills/autosycn/SKILL.md +7 -7
- package/.claude/skills/mop-help/SKILL.md +4 -4
- package/.codex/config.toml +1 -1
- package/AGENTS.md +10 -9
- package/CLAUDE.md +10 -9
- package/GEMINI.md +3 -3
- package/README.bm.md +152 -0
- package/README.md +68 -1013
- package/bin/burhan-mop.mjs +1 -1
- package/bin/mop-core.mjs +1 -1
- package/bin/mop-workflow.mjs +1 -1
- package/package.json +8 -7
- package/.memoryofplanet/scripts/burhan-mop.mjs +0 -124
- /package/{.memoryofplanet → .MOP}/config/team.json +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/adversarial-review.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/architecture.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/decision-log.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/handoff.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/implementation-notes.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/prd.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/product-brief.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/readiness-report.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/release-notes.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/review.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/story.md +0 -0
- /package/{.memoryofplanet → .MOP}/templates/artifacts/ux-spec.md +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MOP Core Protocol
|
|
2
2
|
|
|
3
3
|
This is the source of truth for setup, authentication, member state, and agent
|
|
4
|
-
naming in
|
|
4
|
+
naming in MOP.
|
|
5
5
|
|
|
6
6
|
## First Action Gate
|
|
7
7
|
|
|
8
8
|
Before any assistant answers questions or edits files in this core, read
|
|
9
|
-
`.
|
|
9
|
+
`.MOP/STATE.json`.
|
|
10
10
|
|
|
11
11
|
- If `initialized` is `false`, output:
|
|
12
|
-
`
|
|
12
|
+
`MOP belum di-setup. Jalankan /mop-setup.`
|
|
13
13
|
Then run the setup wizard only.
|
|
14
14
|
- If `initialized` is `true` and `activeMember` is empty, output:
|
|
15
15
|
`Codename dan password.`
|
|
@@ -40,7 +40,7 @@ Use this order:
|
|
|
40
40
|
After confirmation, run:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
node .
|
|
43
|
+
node .MOP/scripts/mop-core.mjs setup --project-name "<name>" --name "<display>" --codename <codename> --password "<password>" --mode <solo|team> --conversation-language "<lang>" --coding-language "<lang>" --git-email "<github-verified-email>" [--git-name "<display>"] [--github-username "<github-login>"] [--github-url "<url>"] [--join-mode <mode>]
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
## Agent Naming Ceremony
|
|
@@ -69,7 +69,7 @@ only when their expertise is genuinely needed, with no fixed maximum.
|
|
|
69
69
|
Use:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
node .
|
|
72
|
+
node .MOP/scripts/mop-core.mjs agent route --actor <codename> --task "<user task>"
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
Routing rules:
|
|
@@ -152,7 +152,7 @@ agent: <from-name> (<from-role>)
|
|
|
152
152
|
|
|
153
153
|
## MOP Workflow
|
|
154
154
|
|
|
155
|
-
MOP Workflow is BMAD-inspired
|
|
155
|
+
MOP Workflow is BMAD-inspired and MOP-native. It is the default
|
|
156
156
|
structure for complex work:
|
|
157
157
|
|
|
158
158
|
`idea -> brief -> prd -> ux-spec -> architecture -> story -> readiness -> implementation -> review -> release`
|
|
@@ -161,9 +161,9 @@ Use the workflow helper when the user asks what to do next, asks for a plan, or
|
|
|
161
161
|
requests implementation:
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
|
-
node .
|
|
165
|
-
node .
|
|
166
|
-
node .
|
|
164
|
+
node .MOP/scripts/mop-workflow.mjs help --actor <codename> --task "<user task>"
|
|
165
|
+
node .MOP/scripts/mop-workflow.mjs next --actor <codename> --task "<user task>"
|
|
166
|
+
node .MOP/scripts/mop-workflow.mjs status --actor <codename>
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
The workflow helper returns the suggested phase, lead agent role, party roles,
|
|
@@ -171,12 +171,12 @@ next artifact, and gate status. The primary agent still owns the answer.
|
|
|
171
171
|
|
|
172
172
|
## Artifacts
|
|
173
173
|
|
|
174
|
-
Complex work should create durable artifacts under `.
|
|
174
|
+
Complex work should create durable artifacts under `.MOP/artifacts/`.
|
|
175
175
|
Artifacts are grouped by category so planning, reviews, releases, and decisions
|
|
176
176
|
do not mix together:
|
|
177
177
|
|
|
178
178
|
```text
|
|
179
|
-
.
|
|
179
|
+
.MOP/artifacts/<category>/<artifact-slug>/<type>.md
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
Default categories:
|
|
@@ -208,7 +208,7 @@ Available artifact types:
|
|
|
208
208
|
Create artifacts with:
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
-
node .
|
|
211
|
+
node .MOP/scripts/mop-workflow.mjs artifact create --actor <codename> --type <type> --title "<title>"
|
|
212
212
|
```
|
|
213
213
|
|
|
214
214
|
Use `--category <name>` only when the default type category is not suitable.
|
|
@@ -232,14 +232,14 @@ for a monorepo or multiple apps.
|
|
|
232
232
|
|
|
233
233
|
Customization is layered and non-bypassing:
|
|
234
234
|
|
|
235
|
-
1. defaults: `.
|
|
236
|
-
2. team: `.
|
|
237
|
-
3. member: `.
|
|
235
|
+
1. defaults: `.MOP/config/defaults.json`
|
|
236
|
+
2. team: `.MOP/config/team.json`
|
|
237
|
+
3. member: `.MOP/config/members/<codename>.json`
|
|
238
238
|
|
|
239
239
|
Show merged config with:
|
|
240
240
|
|
|
241
241
|
```bash
|
|
242
|
-
node .
|
|
242
|
+
node .MOP/scripts/mop-workflow.mjs config show --actor <codename>
|
|
243
243
|
```
|
|
244
244
|
|
|
245
245
|
Customization may tune workflow preferences, party mode verbosity, and preferred
|
|
@@ -251,7 +251,7 @@ BURHAN-MOP review.
|
|
|
251
251
|
Before coding or making implementation changes, run:
|
|
252
252
|
|
|
253
253
|
```bash
|
|
254
|
-
node .
|
|
254
|
+
node .MOP/scripts/mop-workflow.mjs gate readiness --actor <codename> --task "<user task>" [--artifact <path>]
|
|
255
255
|
```
|
|
256
256
|
|
|
257
257
|
If status is not `ready`, ask clarification or update the required artifact
|
|
@@ -263,7 +263,7 @@ Use adversarial review before implementation for risky work, before merge, or
|
|
|
263
263
|
when the user asks for review:
|
|
264
264
|
|
|
265
265
|
```bash
|
|
266
|
-
node .
|
|
266
|
+
node .MOP/scripts/mop-workflow.mjs review adversarial --actor <codename> --target "<plan, artifact, file, or task>"
|
|
267
267
|
```
|
|
268
268
|
|
|
269
269
|
Adversarial review must challenge assumptions, find failure modes, surface
|
|
@@ -287,9 +287,12 @@ apply.
|
|
|
287
287
|
The package installer command is:
|
|
288
288
|
|
|
289
289
|
```bash
|
|
290
|
-
npx burhan-mop install
|
|
290
|
+
npx burhan-mop install [--target <project-folder>] [--force] [--json]
|
|
291
291
|
```
|
|
292
292
|
|
|
293
|
+
The default output is a clean terminal UI. Use `--json` for CI, scripts, and
|
|
294
|
+
other automation that needs machine-readable output.
|
|
295
|
+
|
|
293
296
|
The short package command works after the package is published to npm. Before
|
|
294
297
|
an npm publish, install directly from GitHub:
|
|
295
298
|
|
|
@@ -300,10 +303,10 @@ npx --yes github:BURHANDEV-ENTERPRISE/BURHAN-MOP install
|
|
|
300
303
|
Local equivalent:
|
|
301
304
|
|
|
302
305
|
```bash
|
|
303
|
-
node .
|
|
306
|
+
node .MOP/scripts/burhan-mop.mjs install --target <project-folder>
|
|
304
307
|
```
|
|
305
308
|
|
|
306
|
-
Installer copies provider entrypoints,
|
|
309
|
+
Installer copies provider entrypoints, MOP state, skills, workflow
|
|
307
310
|
config, and artifact templates. Existing files are skipped unless `--force` is
|
|
308
311
|
used.
|
|
309
312
|
|
|
@@ -319,19 +322,19 @@ Then ask:
|
|
|
319
322
|
Save the answer with:
|
|
320
323
|
|
|
321
324
|
```bash
|
|
322
|
-
node .
|
|
325
|
+
node .MOP/scripts/mop-core.mjs agent activate --actor <codename> --role <role> --title "<title>" --name "<agent-name>"
|
|
323
326
|
```
|
|
324
327
|
|
|
325
328
|
Check the current active agent with:
|
|
326
329
|
|
|
327
330
|
```bash
|
|
328
|
-
node .
|
|
331
|
+
node .MOP/scripts/mop-core.mjs agent current --actor <codename>
|
|
329
332
|
```
|
|
330
333
|
|
|
331
334
|
Switch to an existing owned agent with:
|
|
332
335
|
|
|
333
336
|
```bash
|
|
334
|
-
node .
|
|
337
|
+
node .MOP/scripts/mop-core.mjs agent use --actor <codename> --name "<agent-name>"
|
|
335
338
|
```
|
|
336
339
|
|
|
337
340
|
All durable memory and ledger entries must include the active agent when one is
|
|
@@ -346,7 +349,7 @@ available to the active member:
|
|
|
346
349
|
3. Save the name with:
|
|
347
350
|
|
|
348
351
|
```bash
|
|
349
|
-
node .
|
|
352
|
+
node .MOP/scripts/mop-core.mjs agent activate --actor <codename> --role <role> --title "<title>" --name "<agent-name>"
|
|
350
353
|
```
|
|
351
354
|
|
|
352
355
|
## Shared Agent Rule
|
|
@@ -366,15 +369,15 @@ changes. It is intentionally identity-safe.
|
|
|
366
369
|
Before first push for a member, configure the real Git identity:
|
|
367
370
|
|
|
368
371
|
```bash
|
|
369
|
-
node .
|
|
372
|
+
node .MOP/scripts/mop-core.mjs member git-identity --actor <codename> --name "<display name>" --email "<github-verified-email>" --github-username "<github-login>"
|
|
370
373
|
```
|
|
371
374
|
|
|
372
375
|
Then run:
|
|
373
376
|
|
|
374
377
|
```bash
|
|
375
|
-
node .
|
|
376
|
-
node .
|
|
377
|
-
node .
|
|
378
|
+
node .MOP/scripts/mop-autosycn.mjs init --actor <owner-codename> --url "<github-url>"
|
|
379
|
+
node .MOP/scripts/mop-autosycn.mjs preflight --actor <codename>
|
|
380
|
+
node .MOP/scripts/mop-autosycn.mjs run --actor <codename> --reason "<what changed>"
|
|
378
381
|
```
|
|
379
382
|
|
|
380
383
|
Autosycn must:
|
|
@@ -423,13 +426,13 @@ Only activate deployment after explicit confirmation.
|
|
|
423
426
|
|
|
424
427
|
## File Layout
|
|
425
428
|
|
|
426
|
-
- `.
|
|
427
|
-
- `.
|
|
428
|
-
- `.
|
|
429
|
-
- `.
|
|
430
|
-
- `.
|
|
431
|
-
- `.
|
|
432
|
-
- `.
|
|
429
|
+
- `.MOP/STATE.json` - durable project/member/agent state.
|
|
430
|
+
- `.MOP/PROTOCOL.md` - this protocol.
|
|
431
|
+
- `.MOP/scripts/mop-core.mjs` - setup/login/agent helper.
|
|
432
|
+
- `.MOP/scripts/mop-workflow.mjs` - workflow/help/artifact/readiness/review helper.
|
|
433
|
+
- `.MOP/scripts/burhan-mop.mjs` - installer CLI for `npx burhan-mop install`.
|
|
434
|
+
- `.MOP/scripts/mop-autosycn.mjs` - identity-safe autosycn helper.
|
|
435
|
+
- `.MOP/scripts/mop-auto-deploy.mjs` - opt-in deployment helper.
|
|
433
436
|
- `AGENTS.md` - Codex and provider-neutral entrypoint.
|
|
434
437
|
- `CLAUDE.md` - Claude Code entrypoint.
|
|
435
438
|
- `GEMINI.md` - Gemini CLI entrypoint.
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"workflow": {
|
|
59
59
|
"enabled": true,
|
|
60
60
|
"name": "MOP Workflow",
|
|
61
|
-
"style": "BMAD-inspired,
|
|
61
|
+
"style": "BMAD-inspired, MOP-native",
|
|
62
62
|
"currentPhase": null,
|
|
63
63
|
"phaseOrder": [
|
|
64
64
|
"idea",
|
|
@@ -202,8 +202,8 @@
|
|
|
202
202
|
},
|
|
203
203
|
"artifacts": {
|
|
204
204
|
"enabled": true,
|
|
205
|
-
"directory": ".
|
|
206
|
-
"templateDirectory": ".
|
|
205
|
+
"directory": ".MOP/artifacts",
|
|
206
|
+
"templateDirectory": ".MOP/templates/artifacts",
|
|
207
207
|
"layout": "category/artifact-slug/type.md",
|
|
208
208
|
"defaultCategory": "general",
|
|
209
209
|
"folderByType": {
|
|
@@ -243,9 +243,9 @@
|
|
|
243
243
|
"member"
|
|
244
244
|
],
|
|
245
245
|
"files": {
|
|
246
|
-
"defaults": ".
|
|
247
|
-
"team": ".
|
|
248
|
-
"memberPattern": ".
|
|
246
|
+
"defaults": ".MOP/config/defaults.json",
|
|
247
|
+
"team": ".MOP/config/team.json",
|
|
248
|
+
"memberPattern": ".MOP/config/members/<codename>.json"
|
|
249
249
|
},
|
|
250
250
|
"rules": [
|
|
251
251
|
"Defaults define safe project behavior.",
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
"config",
|
|
277
277
|
"scripts",
|
|
278
278
|
".github",
|
|
279
|
-
".
|
|
279
|
+
".MOP",
|
|
280
280
|
".agents",
|
|
281
281
|
".claude",
|
|
282
282
|
".codex",
|
|
@@ -335,10 +335,10 @@
|
|
|
335
335
|
"enabled": true,
|
|
336
336
|
"packageName": "burhan-mop",
|
|
337
337
|
"command": "npx burhan-mop install",
|
|
338
|
-
"entrypoint": ".
|
|
338
|
+
"entrypoint": ".MOP/scripts/burhan-mop.mjs",
|
|
339
339
|
"installTargets": [
|
|
340
340
|
"provider entrypoints",
|
|
341
|
-
"
|
|
341
|
+
"MOP state",
|
|
342
342
|
"skills",
|
|
343
343
|
"workflow config",
|
|
344
344
|
"artifact templates"
|
|
@@ -511,7 +511,7 @@
|
|
|
511
511
|
"role": "memory",
|
|
512
512
|
"title": "Memory Keeper",
|
|
513
513
|
"kind": "memory",
|
|
514
|
-
"purpose": "Save, recall, summarize, search, and clean long-term
|
|
514
|
+
"purpose": "Save, recall, summarize, search, and clean long-term MOP records."
|
|
515
515
|
},
|
|
516
516
|
{
|
|
517
517
|
"role": "ux",
|
|
@@ -555,7 +555,7 @@
|
|
|
555
555
|
"at": "2026-06-11T00:00:00.000Z",
|
|
556
556
|
"actor": "system",
|
|
557
557
|
"kind": "state-created",
|
|
558
|
-
"summary": "
|
|
558
|
+
"summary": "MOP state scaffold created; setup pending."
|
|
559
559
|
}
|
|
560
560
|
]
|
|
561
561
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"includeGateStatus": true
|
|
15
15
|
},
|
|
16
16
|
"artifacts": {
|
|
17
|
-
"directory": ".
|
|
18
|
-
"templateDirectory": ".
|
|
17
|
+
"directory": ".MOP/artifacts",
|
|
18
|
+
"templateDirectory": ".MOP/templates/artifacts",
|
|
19
19
|
"layout": "category/artifact-slug/type.md",
|
|
20
20
|
"defaultCategory": "general",
|
|
21
21
|
"folderByType": {
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const packageRoot = resolve(here, '..', '..');
|
|
8
|
+
const colorEnabled = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
9
|
+
const colors = {
|
|
10
|
+
reset: '\x1b[0m',
|
|
11
|
+
bold: '\x1b[1m',
|
|
12
|
+
dim: '\x1b[2m',
|
|
13
|
+
green: '\x1b[32m',
|
|
14
|
+
yellow: '\x1b[33m',
|
|
15
|
+
red: '\x1b[31m',
|
|
16
|
+
cyan: '\x1b[36m',
|
|
17
|
+
gray: '\x1b[90m'
|
|
18
|
+
};
|
|
19
|
+
const installEntries = [
|
|
20
|
+
'AGENTS.md',
|
|
21
|
+
'CLAUDE.md',
|
|
22
|
+
'GEMINI.md',
|
|
23
|
+
'.MOP',
|
|
24
|
+
'.agents',
|
|
25
|
+
'.claude',
|
|
26
|
+
'.claude-flow',
|
|
27
|
+
'.codex',
|
|
28
|
+
'.gemini',
|
|
29
|
+
'.mcp.json'
|
|
30
|
+
];
|
|
31
|
+
const doctorEntries = [
|
|
32
|
+
'AGENTS.md',
|
|
33
|
+
'CLAUDE.md',
|
|
34
|
+
'GEMINI.md',
|
|
35
|
+
'.MOP/STATE.json',
|
|
36
|
+
'.MOP/PROTOCOL.md',
|
|
37
|
+
'.MOP/scripts/mop-core.mjs',
|
|
38
|
+
'.MOP/scripts/mop-workflow.mjs',
|
|
39
|
+
'.agents/skills/mop-help/SKILL.md'
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
function parseArgs(argv) {
|
|
43
|
+
const out = { _: [] };
|
|
44
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
45
|
+
const item = argv[i];
|
|
46
|
+
if (!item.startsWith('--')) {
|
|
47
|
+
out._.push(item);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const [key, inlineValue] = item.slice(2).split('=', 2);
|
|
51
|
+
if (inlineValue !== undefined) {
|
|
52
|
+
out[key] = inlineValue;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const next = argv[i + 1];
|
|
56
|
+
if (!next || next.startsWith('--')) {
|
|
57
|
+
out[key] = true;
|
|
58
|
+
} else {
|
|
59
|
+
out[key] = next;
|
|
60
|
+
i += 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function paint(name, value) {
|
|
67
|
+
if (!colorEnabled) return value;
|
|
68
|
+
return `${colors[name]}${value}${colors.reset}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function rule() {
|
|
72
|
+
console.log(paint('gray', '-'.repeat(66)));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function header(title, subtitle) {
|
|
76
|
+
console.log('');
|
|
77
|
+
rule();
|
|
78
|
+
console.log(paint('bold', title));
|
|
79
|
+
console.log(paint('cyan', subtitle));
|
|
80
|
+
rule();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function asJson(args) {
|
|
84
|
+
return args.json === true || args.format === 'json';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function statusBadge(status) {
|
|
88
|
+
if (status === 'installed') return paint('green', '[OK]');
|
|
89
|
+
if (status === 'skipped-existing') return paint('yellow', '[SKIP]');
|
|
90
|
+
if (status === 'missing-source') return paint('red', '[MISS]');
|
|
91
|
+
return paint('gray', '[INFO]');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function statusLabel(status) {
|
|
95
|
+
if (status === 'installed') return 'installed';
|
|
96
|
+
if (status === 'skipped-existing') return 'already exists';
|
|
97
|
+
if (status === 'missing-source') return 'template missing';
|
|
98
|
+
return status;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function summarize(results) {
|
|
102
|
+
return results.reduce((summary, item) => {
|
|
103
|
+
if (item.status === 'installed') summary.installed += 1;
|
|
104
|
+
else if (item.status === 'skipped-existing') summary.skipped += 1;
|
|
105
|
+
else if (item.status === 'missing-source') summary.missing += 1;
|
|
106
|
+
else summary.other += 1;
|
|
107
|
+
return summary;
|
|
108
|
+
}, { installed: 0, skipped: 0, missing: 0, other: 0 });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function copyPath(entry, source, target, force = false) {
|
|
112
|
+
if (!existsSync(source)) return { entry, source, target, status: 'missing-source' };
|
|
113
|
+
if (existsSync(target) && !force) return { entry, source, target, status: 'skipped-existing' };
|
|
114
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
115
|
+
cpSync(source, target, { recursive: true, force: true });
|
|
116
|
+
return { entry, source, target, status: 'installed' };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function buildInstallReport(args) {
|
|
120
|
+
const targetRoot = resolve(String(args.target || process.cwd()));
|
|
121
|
+
const force = args.force === true;
|
|
122
|
+
const results = installEntries.map((entry) => copyPath(
|
|
123
|
+
entry,
|
|
124
|
+
join(packageRoot, entry),
|
|
125
|
+
join(targetRoot, entry),
|
|
126
|
+
force
|
|
127
|
+
));
|
|
128
|
+
const summary = summarize(results);
|
|
129
|
+
return {
|
|
130
|
+
ok: summary.missing === 0,
|
|
131
|
+
command: 'npx burhan-mop install',
|
|
132
|
+
target: targetRoot,
|
|
133
|
+
force,
|
|
134
|
+
results,
|
|
135
|
+
summary,
|
|
136
|
+
next: [
|
|
137
|
+
'Run /mop-setup in the target project.',
|
|
138
|
+
'For team mode, initialize autosycn after setup.',
|
|
139
|
+
'Use: node .MOP/scripts/mop-workflow.mjs help --actor <codename> --task "lepas ni buat apa?"'
|
|
140
|
+
]
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function renderInstall(report) {
|
|
145
|
+
header('BURHAN-MOP installer', 'Portable AI MemoryCore for Claude, Codex / ChatGPT, Gemini, and Antigravity');
|
|
146
|
+
console.log(`${paint('bold', 'Target')} : ${report.target}`);
|
|
147
|
+
console.log(`${paint('bold', 'Mode')} : ${report.force ? 'force overwrite' : 'safe install'}`);
|
|
148
|
+
rule();
|
|
149
|
+
for (const item of report.results) {
|
|
150
|
+
console.log(`${statusBadge(item.status)} ${item.entry.padEnd(28)} ${statusLabel(item.status)}`);
|
|
151
|
+
}
|
|
152
|
+
rule();
|
|
153
|
+
console.log(`${paint('bold', 'Summary')}: ${report.summary.installed} installed, ${report.summary.skipped} skipped, ${report.summary.missing} missing`);
|
|
154
|
+
if (report.summary.skipped > 0) {
|
|
155
|
+
console.log(paint('yellow', 'Tip: existing files were kept. Use --force only when you want to overwrite them.'));
|
|
156
|
+
}
|
|
157
|
+
if (report.summary.missing > 0) {
|
|
158
|
+
console.log(paint('red', 'Some package templates are missing. Reinstall or report this package build.'));
|
|
159
|
+
}
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log(paint('bold', 'Next'));
|
|
162
|
+
report.next.forEach((item, index) => {
|
|
163
|
+
console.log(` ${index + 1}. ${item}`);
|
|
164
|
+
});
|
|
165
|
+
console.log('');
|
|
166
|
+
console.log(paint('dim', 'Automation JSON: npx burhan-mop install --json'));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function install(args) {
|
|
170
|
+
const report = buildInstallReport(args);
|
|
171
|
+
if (asJson(args)) {
|
|
172
|
+
console.log(JSON.stringify(report, null, 2));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
renderInstall(report);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function buildDoctorReport() {
|
|
179
|
+
const results = doctorEntries.map((entry) => {
|
|
180
|
+
const path = join(process.cwd(), entry);
|
|
181
|
+
const exists = existsSync(path);
|
|
182
|
+
return {
|
|
183
|
+
entry,
|
|
184
|
+
exists,
|
|
185
|
+
type: exists ? (statSync(path).isDirectory() ? 'dir' : 'file') : 'missing'
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
ok: results.every((item) => item.exists),
|
|
190
|
+
cwd: process.cwd(),
|
|
191
|
+
results
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function renderDoctor(report) {
|
|
196
|
+
header('BURHAN-MOP doctor', 'Workspace health check');
|
|
197
|
+
console.log(`${paint('bold', 'Project')}: ${report.cwd}`);
|
|
198
|
+
rule();
|
|
199
|
+
for (const item of report.results) {
|
|
200
|
+
const badge = item.exists ? paint('green', '[OK]') : paint('red', '[MISS]');
|
|
201
|
+
console.log(`${badge} ${item.entry.padEnd(38)} ${item.type}`);
|
|
202
|
+
}
|
|
203
|
+
rule();
|
|
204
|
+
console.log(`${paint('bold', 'Status')}: ${report.ok ? paint('green', 'ready') : paint('red', 'missing files')}`);
|
|
205
|
+
console.log('');
|
|
206
|
+
console.log(paint('dim', 'Automation JSON: npx burhan-mop doctor --json'));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function doctor(args) {
|
|
210
|
+
const report = buildDoctorReport();
|
|
211
|
+
if (asJson(args)) {
|
|
212
|
+
console.log(JSON.stringify(report, null, 2));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
renderDoctor(report);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function listPackage(args) {
|
|
219
|
+
const report = {
|
|
220
|
+
packageRoot,
|
|
221
|
+
entries: readdirSync(packageRoot, { withFileTypes: true }).map((item) => ({
|
|
222
|
+
name: item.name,
|
|
223
|
+
type: item.isDirectory() ? 'dir' : 'file'
|
|
224
|
+
}))
|
|
225
|
+
};
|
|
226
|
+
if (asJson(args)) {
|
|
227
|
+
console.log(JSON.stringify(report, null, 2));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
header('BURHAN-MOP package', 'Published package contents');
|
|
231
|
+
console.log(`${paint('bold', 'Root')}: ${report.packageRoot}`);
|
|
232
|
+
rule();
|
|
233
|
+
for (const item of report.entries) {
|
|
234
|
+
console.log(`${item.type.padEnd(4)} ${item.name}`);
|
|
235
|
+
}
|
|
236
|
+
console.log('');
|
|
237
|
+
console.log(paint('dim', 'Automation JSON: npx burhan-mop package --json'));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function main() {
|
|
241
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
242
|
+
const args = parseArgs(rest);
|
|
243
|
+
if (command === 'install') return install(args);
|
|
244
|
+
if (command === 'doctor') return doctor(args);
|
|
245
|
+
if (command === 'package') return listPackage(args);
|
|
246
|
+
console.log(`Usage:
|
|
247
|
+
npx burhan-mop install [--target PATH] [--force] [--json]
|
|
248
|
+
npx burhan-mop doctor [--json]
|
|
249
|
+
npx burhan-mop package [--json]`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
main();
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.error(error.message);
|
|
256
|
+
process.exitCode = 1;
|
|
257
|
+
}
|
|
@@ -102,7 +102,7 @@ function defer(args) {
|
|
|
102
102
|
|
|
103
103
|
function enable(args) {
|
|
104
104
|
const state = readState();
|
|
105
|
-
if (!state.initialized) throw new Error('
|
|
105
|
+
if (!state.initialized) throw new Error('MOP is not initialized.');
|
|
106
106
|
const actor = requireArg(args, 'actor');
|
|
107
107
|
if (!state.members?.[actor]) throw new Error(`Unknown actor: ${actor}`);
|
|
108
108
|
const confirm = String(args.confirm || '').toLowerCase();
|
|
@@ -138,10 +138,10 @@ function main() {
|
|
|
138
138
|
if (command === 'enable') return enable(args);
|
|
139
139
|
|
|
140
140
|
console.log(`Usage:
|
|
141
|
-
node .
|
|
142
|
-
node .
|
|
143
|
-
node .
|
|
144
|
-
node .
|
|
141
|
+
node .MOP/scripts/mop-auto-deploy.mjs status
|
|
142
|
+
node .MOP/scripts/mop-auto-deploy.mjs ask
|
|
143
|
+
node .MOP/scripts/mop-auto-deploy.mjs defer --actor <codename> --answer nanti
|
|
144
|
+
node .MOP/scripts/mop-auto-deploy.mjs enable --actor <codename> --provider github|docker|vercel|all --confirm yes`);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
try {
|
|
@@ -150,4 +150,3 @@ try {
|
|
|
150
150
|
console.error(error.message);
|
|
151
151
|
process.exitCode = 1;
|
|
152
152
|
}
|
|
153
|
-
|