burhan-mop 0.1.1 → 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/.MOP/PROTOCOL.md CHANGED
@@ -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
 
@@ -5,6 +5,39 @@ import { fileURLToPath } from 'node:url';
5
5
 
6
6
  const here = dirname(fileURLToPath(import.meta.url));
7
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
+ ];
8
41
 
9
42
  function parseArgs(argv) {
10
43
  const out = { _: [] };
@@ -14,7 +47,11 @@ function parseArgs(argv) {
14
47
  out._.push(item);
15
48
  continue;
16
49
  }
17
- const key = item.slice(2);
50
+ const [key, inlineValue] = item.slice(2).split('=', 2);
51
+ if (inlineValue !== undefined) {
52
+ out[key] = inlineValue;
53
+ continue;
54
+ }
18
55
  const next = argv[i + 1];
19
56
  if (!next || next.startsWith('--')) {
20
57
  out[key] = true;
@@ -26,82 +63,178 @@ function parseArgs(argv) {
26
63
  return out;
27
64
  }
28
65
 
29
- function copyPath(source, target, force = false) {
30
- if (!existsSync(source)) return { source, target, status: 'missing-source' };
31
- if (existsSync(target) && !force) return { source, target, status: 'skipped-existing' };
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' };
32
114
  mkdirSync(dirname(target), { recursive: true });
33
115
  cpSync(source, target, { recursive: true, force: true });
34
- return { source, target, status: 'installed' };
116
+ return { entry, source, target, status: 'installed' };
35
117
  }
36
118
 
37
- function install(args) {
119
+ function buildInstallReport(args) {
38
120
  const targetRoot = resolve(String(args.target || process.cwd()));
39
121
  const force = args.force === true;
40
- const entries = [
41
- 'AGENTS.md',
42
- 'CLAUDE.md',
43
- 'GEMINI.md',
44
- '.MOP',
45
- '.agents',
46
- '.claude',
47
- '.claude-flow',
48
- '.codex',
49
- '.gemini',
50
- '.mcp.json'
51
- ];
52
- const results = entries.map((entry) => copyPath(
122
+ const results = installEntries.map((entry) => copyPath(
123
+ entry,
53
124
  join(packageRoot, entry),
54
125
  join(targetRoot, entry),
55
126
  force
56
127
  ));
57
- console.log(JSON.stringify({
58
- ok: true,
128
+ const summary = summarize(results);
129
+ return {
130
+ ok: summary.missing === 0,
59
131
  command: 'npx burhan-mop install',
60
132
  target: targetRoot,
61
133
  force,
62
134
  results,
135
+ summary,
63
136
  next: [
64
137
  'Run /mop-setup in the target project.',
65
138
  'For team mode, initialize autosycn after setup.',
66
139
  'Use: node .MOP/scripts/mop-workflow.mjs help --actor <codename> --task "lepas ni buat apa?"'
67
140
  ]
68
- }, null, 2));
69
- }
70
-
71
- function doctor() {
72
- const required = [
73
- 'AGENTS.md',
74
- 'CLAUDE.md',
75
- 'GEMINI.md',
76
- '.MOP/STATE.json',
77
- '.MOP/PROTOCOL.md',
78
- '.MOP/scripts/mop-core.mjs',
79
- '.MOP/scripts/mop-workflow.mjs',
80
- '.agents/skills/mop-help/SKILL.md'
81
- ];
82
- const results = required.map((entry) => {
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) => {
83
180
  const path = join(process.cwd(), entry);
181
+ const exists = existsSync(path);
84
182
  return {
85
183
  entry,
86
- exists: existsSync(path),
87
- type: existsSync(path) ? (statSync(path).isDirectory() ? 'dir' : 'file') : 'missing'
184
+ exists,
185
+ type: exists ? (statSync(path).isDirectory() ? 'dir' : 'file') : 'missing'
88
186
  };
89
187
  });
90
- console.log(JSON.stringify({
188
+ return {
91
189
  ok: results.every((item) => item.exists),
92
190
  cwd: process.cwd(),
93
191
  results
94
- }, null, 2));
192
+ };
95
193
  }
96
194
 
97
- function listPackage() {
98
- console.log(JSON.stringify({
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 = {
99
220
  packageRoot,
100
221
  entries: readdirSync(packageRoot, { withFileTypes: true }).map((item) => ({
101
222
  name: item.name,
102
223
  type: item.isDirectory() ? 'dir' : 'file'
103
224
  }))
104
- }, null, 2));
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'));
105
238
  }
106
239
 
107
240
  function main() {
@@ -109,11 +242,11 @@ function main() {
109
242
  const args = parseArgs(rest);
110
243
  if (command === 'install') return install(args);
111
244
  if (command === 'doctor') return doctor(args);
112
- if (command === 'package') return listPackage();
245
+ if (command === 'package') return listPackage(args);
113
246
  console.log(`Usage:
114
- npx burhan-mop install [--target PATH] [--force]
115
- npx burhan-mop doctor
116
- npx burhan-mop package`);
247
+ npx burhan-mop install [--target PATH] [--force] [--json]
248
+ npx burhan-mop doctor [--json]
249
+ npx burhan-mop package [--json]`);
117
250
  }
118
251
 
119
252
  try {
package/README.bm.md ADDED
@@ -0,0 +1,152 @@
1
+ <h1 align="center">BURHAN-MOP</h1>
2
+
3
+ <p align="center">
4
+ <strong>MOP portable AI MemoryCore untuk Claude, Codex / ChatGPT, Gemini, dan Antigravity.</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/burhan-mop">
9
+ <img src="https://img.shields.io/npm/v/burhan-mop?style=for-the-badge&label=NPM" alt="npm version">
10
+ </a>
11
+ <a href="https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP">
12
+ <img src="https://img.shields.io/badge/GitHub-BURHAN--MOP-181717?style=for-the-badge&logo=github" alt="GitHub repository">
13
+ </a>
14
+ <img src="https://img.shields.io/badge/Node-%3E%3D20-1FAE4B?style=for-the-badge&logo=node.js&logoColor=white" alt="Node 20+">
15
+ <img src="https://img.shields.io/badge/License-UNLICENSED-9CA3AF?style=for-the-badge" alt="License">
16
+ </p>
17
+
18
+ <p align="center">
19
+ <img src="https://img.shields.io/badge/Claude-ready-5A45FF?style=flat-square" alt="Claude ready">
20
+ <img src="https://img.shields.io/badge/Codex-ready-111111?style=flat-square" alt="Codex ready">
21
+ <img src="https://img.shields.io/badge/Gemini-ready-4285F4?style=flat-square" alt="Gemini ready">
22
+ <img src="https://img.shields.io/badge/Antigravity-ready-00A67E?style=flat-square" alt="Antigravity ready">
23
+ <img src="https://img.shields.io/badge/MOP_Workflow-BMAD_inspired-FFB000?style=flat-square" alt="MOP workflow">
24
+ </p>
25
+
26
+ <p align="center">
27
+ <a href="./README.md">English</a>
28
+ |
29
+ <strong>Bahasa Melayu</strong>
30
+ </p>
31
+
32
+ ---
33
+
34
+ ## Apa Itu BURHAN-MOP?
35
+
36
+ BURHAN-MOP ialah **MOP (Memory of Planet) core** yang portable untuk workspace
37
+ coding AI. Ia bagi semua AI provider sumber kebenaran yang sama: memory project,
38
+ peraturan agent, workflow gate, folder artifact, autosycn, dan setup deploy.
39
+
40
+ Maksudnya mudah: pasang sekali, kemudian Claude, Codex / ChatGPT, Gemini, dan
41
+ Antigravity boleh masuk project yang sama dengan context yang sama.
42
+
43
+ ## Install
44
+
45
+ Jalankan dalam root project:
46
+
47
+ ```bash
48
+ npx burhan-mop install
49
+ npx burhan-mop doctor
50
+ ```
51
+
52
+ Install ke folder lain:
53
+
54
+ ```bash
55
+ npx burhan-mop install --target "C:\path\to\project"
56
+ ```
57
+
58
+ Paksa overwrite install sedia ada:
59
+
60
+ ```bash
61
+ npx burhan-mop install --force
62
+ ```
63
+
64
+ Installer akan tunjuk terminal UI yang kemas secara default. Untuk automation,
65
+ guna JSON:
66
+
67
+ ```bash
68
+ npx burhan-mop install --json
69
+ npx burhan-mop doctor --json
70
+ ```
71
+
72
+ Selepas install, buka AI coding chat dalam project itu dan jalankan:
73
+
74
+ ```text
75
+ /mop-setup
76
+ ```
77
+
78
+ ## Apa Yang Dipasang
79
+
80
+ | Path | Fungsi |
81
+ | --- | --- |
82
+ | `.MOP/` | State, protocol, script, workflow config, dan template artifact MOP. |
83
+ | `AGENTS.md` | Arahan neutral untuk Codex / ChatGPT coding agents. |
84
+ | `CLAUDE.md` | Entry point dan rules untuk Claude Code. |
85
+ | `GEMINI.md` | Entry point untuk Gemini CLI. |
86
+ | `.agents/` | Agent dan skill yang sesuai untuk Antigravity. |
87
+ | `.codex/`, `.gemini/`, `.claude/` | Config dan skill surface ikut provider. |
88
+
89
+ ## Fungsi Utama
90
+
91
+ | Fungsi | Apa dia buat |
92
+ | --- | --- |
93
+ | Auth Gate | First action mesti setup/login. AI tidak terus bekerja sebelum gate lulus. |
94
+ | Agent Router | Pilih satu primary agent dan tambah support agent bila perlu. |
95
+ | Party Mode | Tunjuk perbincangan agent-to-agent untuk keputusan multi-role. |
96
+ | MOP Workflow | Flow inspirasi BMAD dari idea sampai release dengan readiness gate. |
97
+ | Artifacts | Simpan plan, spec, review, dan release notes dalam `.MOP/artifacts/`. |
98
+ | Autosycn | Commit dan push guna identiti user sebenar, bukan identiti AI tool. |
99
+ | Auto Deploy | Setup optional untuk GitHub, Docker, dan Vercel. |
100
+
101
+ ## Flow Sesi Pertama
102
+
103
+ ```text
104
+ 1. AI baca .MOP/STATE.json
105
+ 2. Jika belum setup, AI suruh jalankan /mop-setup
106
+ 3. Setup tanya nama project, owner, codename, password, mode, bahasa, dan GitHub
107
+ 4. Selepas login, setiap task lalu Agent Router
108
+ 5. Task kompleks guna MOP Workflow dan readiness gate sebelum coding
109
+ ```
110
+
111
+ ## Command Berguna
112
+
113
+ ```bash
114
+ npx burhan-mop install
115
+ npx burhan-mop doctor
116
+ npx burhan-mop package
117
+ ```
118
+
119
+ Helper dalam project:
120
+
121
+ ```bash
122
+ node .MOP/scripts/mop-core.mjs status
123
+ node .MOP/scripts/mop-core.mjs validate
124
+ node .MOP/scripts/mop-workflow.mjs help --actor <codename> --task "<task>"
125
+ node .MOP/scripts/mop-autosycn.mjs run --actor <codename> --reason "<apa berubah>"
126
+ ```
127
+
128
+ ## Workflow Team
129
+
130
+ Dalam team mode, kerja akan push ke branch user dulu:
131
+
132
+ ```text
133
+ dev/<codename> -> BURHAN-MOP review -> main
134
+ ```
135
+
136
+ BURHAN-MOP bertindak sebagai merge guardian. Ia semak branch, validate state,
137
+ dan merge hanya bila workflow selamat.
138
+
139
+ ## Release
140
+
141
+ | Item | Nilai |
142
+ | --- | --- |
143
+ | npm package | [`burhan-mop`](https://www.npmjs.com/package/burhan-mop) |
144
+ | command latest | `npx burhan-mop install` |
145
+ | GitHub release | [`v0.1.2`](https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP/releases/tag/v0.1.2) |
146
+ | Node | `>=20` |
147
+
148
+ ## Links
149
+
150
+ - npm: https://www.npmjs.com/package/burhan-mop
151
+ - GitHub: https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP
152
+ - English README: [README.md](./README.md)