burhan-mop 0.1.6 → 0.1.7
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 +20 -8
- package/.MOP/STATE.json +12 -1
- package/.MOP/scripts/mop-autosycn.mjs +51 -11
- package/.MOP/scripts/mop-core.mjs +59 -14
- package/.agents/AGENTS.md +4 -0
- package/AGENTS.md +5 -2
- package/CLAUDE.md +3 -0
- package/GEMINI.md +3 -0
- package/README.bm.md +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
package/.MOP/PROTOCOL.md
CHANGED
|
@@ -31,7 +31,8 @@ Use this order:
|
|
|
31
31
|
7. Coding/adventure language.
|
|
32
32
|
8. GitHub project link. Required for `team`, optional for `solo`.
|
|
33
33
|
9. GitHub username.
|
|
34
|
-
10. Git commit email.
|
|
34
|
+
10. Git commit email. Default to `github-noreply` so MOP derives the active
|
|
35
|
+
GitHub account email as `ID+USERNAME@users.noreply.github.com`.
|
|
35
36
|
11. If `team`, ask join mode: `open`, `owner-approved`, or `invite`.
|
|
36
37
|
12. Ask auto deploy: `Nak aktifkan auto deploy sekarang? Pilih provider:
|
|
37
38
|
GitHub, Docker, Vercel.` If the user says later/no, answer with the defer
|
|
@@ -40,7 +41,7 @@ Use this order:
|
|
|
40
41
|
After confirmation, run:
|
|
41
42
|
|
|
42
43
|
```bash
|
|
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
|
|
44
|
+
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-noreply [--git-name "<display>"] [--github-username "<github-login>"] [--github-url "<url>"] [--join-mode <mode>]
|
|
44
45
|
```
|
|
45
46
|
|
|
46
47
|
## Agent Naming Ceremony
|
|
@@ -431,10 +432,13 @@ In team mode, an agent name is the identity.
|
|
|
431
432
|
Autosycn is always available and should be used after meaningful state or file
|
|
432
433
|
changes. It is intentionally identity-safe.
|
|
433
434
|
|
|
434
|
-
Before first push for a member, configure the real
|
|
435
|
+
Before first push for a member, configure the real GitHub identity. Default to
|
|
436
|
+
GitHub noreply so commits attach to the active user account without exposing
|
|
437
|
+
private email:
|
|
435
438
|
|
|
436
439
|
```bash
|
|
437
|
-
|
|
440
|
+
gh auth login
|
|
441
|
+
node .MOP/scripts/mop-core.mjs member git-identity --actor <codename> --name "<display name>" --email github-noreply --github-username "<github-login>"
|
|
438
442
|
```
|
|
439
443
|
|
|
440
444
|
Then run:
|
|
@@ -455,6 +459,13 @@ Autosycn must:
|
|
|
455
459
|
- Commit with `GIT_AUTHOR_NAME`, `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`, and
|
|
456
460
|
`GIT_COMMITTER_EMAIL` set from member state.
|
|
457
461
|
- Set local `git config user.name` and `user.email` before commit/merge.
|
|
462
|
+
- For member commits, derive `user.email` from the active GitHub CLI account as
|
|
463
|
+
`ID+USERNAME@users.noreply.github.com` when
|
|
464
|
+
`autosync.githubIdentity.useNoreplyForMemberCommits` is enabled.
|
|
465
|
+
- Refuse to commit or push if `gh api user` is authenticated as a different
|
|
466
|
+
GitHub username than the active member's configured `githubUsername`.
|
|
467
|
+
- Use the member GitHub identity for setup, preflight, memory, and work branch
|
|
468
|
+
commits. Use `BURHAN-MOP` only for merge guardian commits.
|
|
458
469
|
- In team mode, `main` is the trunk and each user works on `dev/<codename>`.
|
|
459
470
|
- Push to `dev/<codename>` in team mode and `main` in solo mode.
|
|
460
471
|
- After a team push, BURHAN-MOP reviews `dev/<codename>` and merges it into
|
|
@@ -469,10 +480,11 @@ Autosycn must:
|
|
|
469
480
|
- If `githubUsername` is configured, refuse to push unless `gh api user`
|
|
470
481
|
verifies the same account.
|
|
471
482
|
|
|
472
|
-
Important: GitHub commit attribution comes from commit email.
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
483
|
+
Important: GitHub commit attribution comes from commit email. MOP uses the
|
|
484
|
+
active GitHub account noreply email for member commits by default. GitHub push
|
|
485
|
+
actor comes from the credential or SSH key used by `git push`; no script can
|
|
486
|
+
fake that. If GitHub shows the wrong pusher, fix `gh auth login`, Git
|
|
487
|
+
Credential Manager, or the SSH key account.
|
|
476
488
|
|
|
477
489
|
## Default Skill: auto-deploy
|
|
478
490
|
|
package/.MOP/STATE.json
CHANGED
|
@@ -399,7 +399,18 @@
|
|
|
399
399
|
}
|
|
400
400
|
},
|
|
401
401
|
"requireUserGitEmail": true,
|
|
402
|
-
"verifyGhUserWhenConfigured": true
|
|
402
|
+
"verifyGhUserWhenConfigured": true,
|
|
403
|
+
"githubIdentity": {
|
|
404
|
+
"requireMatchedGhUser": true,
|
|
405
|
+
"useNoreplyForMemberCommits": true,
|
|
406
|
+
"noreplyFormat": "id-plus-login",
|
|
407
|
+
"rules": [
|
|
408
|
+
"Member commits must use the active member GitHub account, not an AI or guardian identity.",
|
|
409
|
+
"When gh is authenticated, derive member commit email as ID+USERNAME@users.noreply.github.com.",
|
|
410
|
+
"Refuse autosycn if the active gh account does not match the member githubUsername.",
|
|
411
|
+
"BURHAN-MOP identity is reserved for merge guardian commits only."
|
|
412
|
+
]
|
|
413
|
+
}
|
|
403
414
|
},
|
|
404
415
|
"members": {},
|
|
405
416
|
"installedSkills": [
|
|
@@ -247,22 +247,59 @@ function getMember(state, actor) {
|
|
|
247
247
|
return member;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
function githubIdentityPolicy(state) {
|
|
251
|
+
return state.autosync?.githubIdentity || {
|
|
252
|
+
requireMatchedGhUser: true,
|
|
253
|
+
useNoreplyForMemberCommits: true,
|
|
254
|
+
noreplyFormat: 'id-plus-login'
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function currentGhUser() {
|
|
259
|
+
const result = runOptional('gh', ['api', 'user', '--jq', '{login:.login,id:.id,email:.email}']);
|
|
260
|
+
if (!result.ok) return null;
|
|
261
|
+
try {
|
|
262
|
+
return JSON.parse(result.stdout || '{}');
|
|
263
|
+
} catch {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function githubNoreplyEmail(user) {
|
|
269
|
+
if (!user?.login || !user?.id) return '';
|
|
270
|
+
return `${user.id}+${user.login}@users.noreply.github.com`;
|
|
271
|
+
}
|
|
272
|
+
|
|
250
273
|
function identityFor(state, actor) {
|
|
251
274
|
const member = getMember(state, actor);
|
|
252
275
|
const identity = member.gitIdentity || {};
|
|
276
|
+
const policy = githubIdentityPolicy(state);
|
|
277
|
+
const gh = currentGhUser();
|
|
253
278
|
const name = identity.name || member.displayName || actor;
|
|
254
|
-
const
|
|
279
|
+
const githubUsername = identity.githubUsername || member.github?.username || gh?.login || '';
|
|
280
|
+
if (gh?.login && githubUsername && policy.requireMatchedGhUser !== false && gh.login.toLowerCase() !== githubUsername.toLowerCase()) {
|
|
281
|
+
throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${githubUsername}. Refusing to commit or push as the wrong user.`);
|
|
282
|
+
}
|
|
283
|
+
let email = identity.email || member.github?.noreplyEmail || '';
|
|
284
|
+
if (policy.useNoreplyForMemberCommits !== false) {
|
|
285
|
+
email = githubNoreplyEmail(gh);
|
|
286
|
+
if (!email) {
|
|
287
|
+
throw new Error('GitHub noreply identity is required for member commits. Run gh auth login as the real user, or set autosync.githubIdentity.useNoreplyForMemberCommits=false.');
|
|
288
|
+
}
|
|
289
|
+
}
|
|
255
290
|
if (!email && state.autosync?.requireUserGitEmail !== false) {
|
|
256
291
|
throw new Error([
|
|
257
292
|
`Missing git email for ${actor}.`,
|
|
258
|
-
'Set a GitHub-verified email or noreply
|
|
259
|
-
`node .MOP/scripts/mop-core.mjs member git-identity --actor ${actor} --name "${name}" --email
|
|
293
|
+
'Set a GitHub-verified email or let MOP derive GitHub noreply from gh:',
|
|
294
|
+
`node .MOP/scripts/mop-core.mjs member git-identity --actor ${actor} --name "${name}" --email github-noreply [--github-username "<username>"]`
|
|
260
295
|
].join(' '));
|
|
261
296
|
}
|
|
262
297
|
return {
|
|
263
298
|
name,
|
|
264
299
|
email,
|
|
265
|
-
githubUsername
|
|
300
|
+
githubUsername,
|
|
301
|
+
githubUserId: gh?.login?.toLowerCase() === githubUsername.toLowerCase() ? gh.id : identity.githubUserId,
|
|
302
|
+
emailSource: policy.useNoreplyForMemberCommits !== false ? 'github-noreply' : (identity.emailSource || 'manual')
|
|
266
303
|
};
|
|
267
304
|
}
|
|
268
305
|
|
|
@@ -335,15 +372,16 @@ function configureRemote(url, replaceRemote = false) {
|
|
|
335
372
|
}
|
|
336
373
|
|
|
337
374
|
function verifyGhUser(identity, state) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
375
|
+
const policy = githubIdentityPolicy(state);
|
|
376
|
+
if (state.autosync?.verifyGhUserWhenConfigured === false && policy.requireMatchedGhUser === false) return 'skipped';
|
|
377
|
+
const gh = currentGhUser();
|
|
378
|
+
if (!gh?.login) {
|
|
341
379
|
throw new Error('GitHub username is configured, but gh could not verify the active account. Run gh auth login as the real user or set autosync.verifyGhUserWhenConfigured=false for SSH-only workflows.');
|
|
342
380
|
}
|
|
343
|
-
if (gh.
|
|
344
|
-
throw new Error(`GitHub CLI authenticated as ${gh.
|
|
381
|
+
if (identity.githubUsername && gh.login.toLowerCase() !== identity.githubUsername.toLowerCase()) {
|
|
382
|
+
throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${identity.githubUsername}. Refusing to push as the wrong account.`);
|
|
345
383
|
}
|
|
346
|
-
return `verified:${gh.
|
|
384
|
+
return `verified:${gh.login}:${githubNoreplyEmail(gh) || 'email-unavailable'}`;
|
|
347
385
|
}
|
|
348
386
|
|
|
349
387
|
function runProjectCommand(command, env) {
|
|
@@ -677,6 +715,7 @@ function status() {
|
|
|
677
715
|
workBranchPrefix: state.autosync?.workBranchPrefix || 'dev',
|
|
678
716
|
autoMergeToMain: state.autosync?.autoMergeToMain !== false,
|
|
679
717
|
mergeGuardian: guardianConfig(state),
|
|
718
|
+
githubIdentity: githubIdentityPolicy(state),
|
|
680
719
|
preflightBeforeWork: state.autosync?.preflightBeforeWork !== false,
|
|
681
720
|
requireUserGitEmail: state.autosync?.requireUserGitEmail !== false,
|
|
682
721
|
initialized: state.initialized,
|
|
@@ -691,7 +730,8 @@ function status() {
|
|
|
691
730
|
displayName: member.displayName,
|
|
692
731
|
gitIdentityConfigured: Boolean(member.gitIdentity?.email || member.github?.noreplyEmail),
|
|
693
732
|
gitName: member.gitIdentity?.name || member.displayName || key,
|
|
694
|
-
gitEmail: member.gitIdentity?.email || member.github?.noreplyEmail || ''
|
|
733
|
+
gitEmail: member.gitIdentity?.email || member.github?.noreplyEmail || '',
|
|
734
|
+
githubUsername: member.gitIdentity?.githubUsername || member.github?.username || ''
|
|
695
735
|
}
|
|
696
736
|
]))
|
|
697
737
|
}, null, 2));
|
|
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFile
|
|
|
3
3
|
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';
|
|
6
|
+
import { spawnSync } from 'node:child_process';
|
|
6
7
|
|
|
7
8
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
9
|
const coreDir = resolve(here, '..');
|
|
@@ -71,6 +72,53 @@ function verifyPassword(password, salt, expectedHex) {
|
|
|
71
72
|
return expected.length === actual.length && timingSafeEqual(actual, expected);
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
function currentGhUser() {
|
|
76
|
+
const result = spawnSync('gh', ['api', 'user', '--jq', '{login:.login,id:.id,email:.email}'], {
|
|
77
|
+
cwd: rootDir,
|
|
78
|
+
encoding: 'utf8'
|
|
79
|
+
});
|
|
80
|
+
if (result.status !== 0) return null;
|
|
81
|
+
try {
|
|
82
|
+
return JSON.parse(result.stdout || '{}');
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function githubNoreplyEmail(user) {
|
|
89
|
+
if (!user?.login || !user?.id) return '';
|
|
90
|
+
return `${user.id}+${user.login}@users.noreply.github.com`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function resolveGitIdentityInput(state, actor, name, emailInput, githubUsernameInput) {
|
|
94
|
+
const policy = state.autosync?.githubIdentity || {};
|
|
95
|
+
const preferNoreply = policy.useNoreplyForMemberCommits !== false;
|
|
96
|
+
const gh = currentGhUser();
|
|
97
|
+
const githubUsername = githubUsernameInput || gh?.login || '';
|
|
98
|
+
if (gh?.login && githubUsername && policy.requireMatchedGhUser !== false && gh.login.toLowerCase() !== githubUsername.toLowerCase()) {
|
|
99
|
+
throw new Error(`GitHub CLI authenticated as ${gh.login}, expected ${githubUsername}. Run gh auth login as the real user.`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let email = String(emailInput || '').trim();
|
|
103
|
+
const wantsNoreply = !email || ['auto', 'github', 'github-noreply', 'noreply'].includes(email.toLowerCase());
|
|
104
|
+
if (preferNoreply && wantsNoreply) {
|
|
105
|
+
email = githubNoreplyEmail(gh);
|
|
106
|
+
if (!email) {
|
|
107
|
+
throw new Error('Cannot derive GitHub noreply email. Run gh auth login or provide --git-email "<github-verified-email>".');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!email && state.autosync?.requireUserGitEmail !== false) {
|
|
111
|
+
throw new Error('Git email is required. Use --git-email github-noreply after gh auth login, or provide a GitHub-verified email.');
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
name,
|
|
115
|
+
email,
|
|
116
|
+
githubUsername,
|
|
117
|
+
githubUserId: gh?.login?.toLowerCase() === githubUsername.toLowerCase() ? gh.id : undefined,
|
|
118
|
+
emailSource: wantsNoreply && email ? 'github-noreply' : 'manual'
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
74
122
|
function activeAgentFor(state, actor) {
|
|
75
123
|
const activeId = state.activeAgents?.[actor];
|
|
76
124
|
if (!activeId) return null;
|
|
@@ -502,7 +550,7 @@ function setup(args) {
|
|
|
502
550
|
const codingLanguage = String(args['coding-language'] || 'English');
|
|
503
551
|
const githubUrl = String(args['github-url'] || '');
|
|
504
552
|
const gitName = String(args['git-name'] || displayName);
|
|
505
|
-
const gitEmail = String(args['git-email'] || '');
|
|
553
|
+
const gitEmail = String(args['git-email'] || 'github-noreply');
|
|
506
554
|
const githubUsername = String(args['github-username'] || '');
|
|
507
555
|
const joinMode = String(args['join-mode'] || 'owner-approved');
|
|
508
556
|
|
|
@@ -510,12 +558,10 @@ function setup(args) {
|
|
|
510
558
|
if (password.length < 8) throw new Error('Password must be at least 8 characters.');
|
|
511
559
|
if (!['solo', 'team'].includes(mode)) throw new Error('Mode must be solo or team.');
|
|
512
560
|
if (mode === 'team' && !githubUrl) throw new Error('Team mode requires --github-url.');
|
|
513
|
-
if (state.autosync?.requireUserGitEmail !== false && !gitEmail) {
|
|
514
|
-
throw new Error('Git email is required so commits are attributed to the real user, not the AI tool.');
|
|
515
|
-
}
|
|
516
561
|
if (!['open', 'owner-approved', 'invite'].includes(joinMode)) {
|
|
517
562
|
throw new Error('Join mode must be open, owner-approved, or invite.');
|
|
518
563
|
}
|
|
564
|
+
const gitIdentity = resolveGitIdentityInput(state, codename, gitName, gitEmail, githubUsername);
|
|
519
565
|
|
|
520
566
|
const { passwordHash, passwordSalt } = hashPassword(password);
|
|
521
567
|
state.initialized = true;
|
|
@@ -545,11 +591,7 @@ function setup(args) {
|
|
|
545
591
|
conversation: conversationLanguage,
|
|
546
592
|
coding: codingLanguage
|
|
547
593
|
},
|
|
548
|
-
gitIdentity
|
|
549
|
-
name: gitName,
|
|
550
|
-
email: gitEmail,
|
|
551
|
-
githubUsername
|
|
552
|
-
},
|
|
594
|
+
gitIdentity,
|
|
553
595
|
joinedAt: now()
|
|
554
596
|
}
|
|
555
597
|
};
|
|
@@ -822,12 +864,12 @@ function memberGitIdentity(args) {
|
|
|
822
864
|
if (!member) throw new Error('Unknown actor.');
|
|
823
865
|
const agent = requireActiveAgent(state, actor);
|
|
824
866
|
const name = String(args.name || member.displayName || actor);
|
|
825
|
-
const email =
|
|
867
|
+
const email = String(args.email || 'github-noreply');
|
|
826
868
|
const githubUsername = String(args['github-username'] || member.gitIdentity?.githubUsername || '');
|
|
827
|
-
member.gitIdentity =
|
|
869
|
+
member.gitIdentity = resolveGitIdentityInput(state, actor, name, email, githubUsername);
|
|
828
870
|
appendLedger(state, actor, 'git-identity', `Updated git identity for ${actor}.`, agent);
|
|
829
871
|
writeState(state);
|
|
830
|
-
console.log(`Git identity set for ${actor}: ${name} <${email}>${githubUsername ? ` github=${githubUsername}` : ''}`);
|
|
872
|
+
console.log(`Git identity set for ${actor}: ${member.gitIdentity.name} <${member.gitIdentity.email}>${member.gitIdentity.githubUsername ? ` github=${member.gitIdentity.githubUsername}` : ''}`);
|
|
831
873
|
}
|
|
832
874
|
|
|
833
875
|
function validate() {
|
|
@@ -843,6 +885,9 @@ function validate() {
|
|
|
843
885
|
if (state.memoryPolicy && typeof state.memoryPolicy !== 'object') errors.push('memoryPolicy must be object');
|
|
844
886
|
if (state.agentRouter && typeof state.agentRouter !== 'object') errors.push('agentRouter must be object');
|
|
845
887
|
if (state.partyMode && typeof state.partyMode !== 'object') errors.push('partyMode must be object');
|
|
888
|
+
if (state.autosync?.githubIdentity && typeof state.autosync.githubIdentity !== 'object') {
|
|
889
|
+
errors.push('autosync.githubIdentity must be object');
|
|
890
|
+
}
|
|
846
891
|
if (state.projectRootPolicy && typeof state.projectRootPolicy !== 'object') errors.push('projectRootPolicy must be object');
|
|
847
892
|
if (state.projectRootPolicy?.rules && !Array.isArray(state.projectRootPolicy.rules)) {
|
|
848
893
|
errors.push('projectRootPolicy.rules must be array');
|
|
@@ -985,9 +1030,9 @@ function main() {
|
|
|
985
1030
|
console.log(`Usage:
|
|
986
1031
|
node .MOP/scripts/mop-core.mjs status
|
|
987
1032
|
node .MOP/scripts/mop-core.mjs validate
|
|
988
|
-
node .MOP/scripts/mop-core.mjs setup --project-name NAME --name DISPLAY --codename CODE --password PASS --mode solo|team --conversation-language LANG --coding-language LANG --git-email EMAIL [--git-name NAME] [--github-username USER] [--github-url URL]
|
|
1033
|
+
node .MOP/scripts/mop-core.mjs setup --project-name NAME --name DISPLAY --codename CODE --password PASS --mode solo|team --conversation-language LANG --coding-language LANG [--git-email github-noreply|EMAIL] [--git-name NAME] [--github-username USER] [--github-url URL]
|
|
989
1034
|
node .MOP/scripts/mop-core.mjs login --codename CODE --password PASS
|
|
990
|
-
node .MOP/scripts/mop-core.mjs member git-identity --actor CODE --name NAME --email EMAIL [--github-username USER]
|
|
1035
|
+
node .MOP/scripts/mop-core.mjs member git-identity --actor CODE --name NAME [--email github-noreply|EMAIL] [--github-username USER]
|
|
991
1036
|
node .MOP/scripts/mop-core.mjs agent activate --actor CODE --role ROLE --title TITLE --name NAME
|
|
992
1037
|
node .MOP/scripts/mop-core.mjs agent use --actor CODE --name NAME
|
|
993
1038
|
node .MOP/scripts/mop-core.mjs agent current --actor CODE
|
package/.agents/AGENTS.md
CHANGED
|
@@ -34,6 +34,10 @@ Before doing anything, read `.MOP/STATE.json` and follow
|
|
|
34
34
|
- For risky changes, run adversarial review before implementation or merge.
|
|
35
35
|
- When a role agent first appears, ask the user to name it before using it as a
|
|
36
36
|
personal agent.
|
|
37
|
+
- Autosycn member commits must use the active member GitHub account. By default,
|
|
38
|
+
MOP derives `ID+USERNAME@users.noreply.github.com` from `gh api user` and
|
|
39
|
+
refuses mismatched GitHub accounts. `BURHAN-MOP` identity is reserved for
|
|
40
|
+
merge guardian commits only.
|
|
37
41
|
|
|
38
42
|
## Operating Rules
|
|
39
43
|
|
package/AGENTS.md
CHANGED
|
@@ -46,8 +46,8 @@ follow `.MOP/PROTOCOL.md`.
|
|
|
46
46
|
|
|
47
47
|
For `/mop-setup`, ask in order: project name (default folder name), owner display
|
|
48
48
|
name, owner codename, password, solo/team, conversation language, coding
|
|
49
|
-
language, GitHub link, GitHub username, Git commit email
|
|
50
|
-
then whether to activate auto-deploy now or later.
|
|
49
|
+
language, GitHub link, GitHub username, Git commit email (`github-noreply` by
|
|
50
|
+
default), join mode if team, then whether to activate auto-deploy now or later.
|
|
51
51
|
|
|
52
52
|
Agent role/template names are not personal AI names. When a role agent is first
|
|
53
53
|
needed, ask the user to name it and save it with `mop-core.mjs agent activate`.
|
|
@@ -62,6 +62,9 @@ agent route instead of answering invisibly.
|
|
|
62
62
|
Default skill: `autosycn`. After meaningful changes, use
|
|
63
63
|
`.MOP/scripts/mop-autosycn.mjs`. It must commit and merge with the
|
|
64
64
|
real member Git identity from state, never with the AI tool identity.
|
|
65
|
+
Member commits must use the active member GitHub account; by default MOP derives
|
|
66
|
+
`ID+USERNAME@users.noreply.github.com` from `gh api user` and refuses mismatched
|
|
67
|
+
GitHub accounts. `BURHAN-MOP` identity is only for merge guardian commits.
|
|
65
68
|
In team mode, run `preflight --actor <codename>` before starting work; work goes
|
|
66
69
|
to `dev/<codename>`. Every small or large change is pushed there first, then
|
|
67
70
|
BURHAN-MOP reviews and merges to `main` only when checks pass.
|
package/CLAUDE.md
CHANGED
|
@@ -47,6 +47,9 @@ agent route instead of answering invisibly.
|
|
|
47
47
|
Default skill: `autosycn`. After meaningful changes, use
|
|
48
48
|
`.MOP/scripts/mop-autosycn.mjs`. It must commit and merge with the
|
|
49
49
|
real member Git identity from state, never with the AI tool identity.
|
|
50
|
+
Member commits must use the active member GitHub account; by default MOP derives
|
|
51
|
+
`ID+USERNAME@users.noreply.github.com` from `gh api user` and refuses mismatched
|
|
52
|
+
GitHub accounts. `BURHAN-MOP` identity is only for merge guardian commits.
|
|
50
53
|
In team mode, run `preflight --actor <codename>` before starting work; work goes
|
|
51
54
|
to `dev/<codename>`. Every small or large change is pushed there first, then
|
|
52
55
|
BURHAN-MOP reviews and merges to `main` only when checks pass.
|
package/GEMINI.md
CHANGED
|
@@ -16,6 +16,9 @@ rules are imported below.
|
|
|
16
16
|
example: `agent: <agent-name> (<agent-role>) to <user>`.
|
|
17
17
|
- Save a one-line memory after meaningful work with
|
|
18
18
|
`mop-core.mjs memory add --actor <codename> --kind conversation --summary "<outcome>"`.
|
|
19
|
+
- Autosycn member commits must use the active member GitHub account. MOP derives
|
|
20
|
+
`ID+USERNAME@users.noreply.github.com` from `gh api user` by default and
|
|
21
|
+
refuses mismatched GitHub accounts.
|
|
19
22
|
- Treat the current workspace root as the project root; do not create a nested
|
|
20
23
|
project wrapper folder for app work unless the user explicitly asks for it.
|
|
21
24
|
- Use `.gemini/settings.json` for context filenames and MCP server setup.
|
package/README.bm.md
CHANGED
|
@@ -142,7 +142,7 @@ dan merge hanya bila workflow selamat.
|
|
|
142
142
|
| --- | --- |
|
|
143
143
|
| npm package | [`burhan-mop`](https://www.npmjs.com/package/burhan-mop) |
|
|
144
144
|
| command latest | `npx burhan-mop install` |
|
|
145
|
-
| GitHub release | [`v0.1.
|
|
145
|
+
| GitHub release | [`v0.1.7`](https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP/releases/tag/v0.1.7) |
|
|
146
146
|
| Node | `>=20` |
|
|
147
147
|
|
|
148
148
|
## Links
|
package/README.md
CHANGED
|
@@ -141,7 +141,7 @@ and merges only when the workflow is safe.
|
|
|
141
141
|
| --- | --- |
|
|
142
142
|
| npm package | [`burhan-mop`](https://www.npmjs.com/package/burhan-mop) |
|
|
143
143
|
| latest command | `npx burhan-mop install` |
|
|
144
|
-
| GitHub release | [`v0.1.
|
|
144
|
+
| GitHub release | [`v0.1.7`](https://github.com/BURHANDEV-ENTERPRISE/BURHAN-MOP/releases/tag/v0.1.7) |
|
|
145
145
|
| Node | `>=20` |
|
|
146
146
|
|
|
147
147
|
## Links
|