hanoman 0.1.26 → 0.1.27
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/dist/build-info.json +3 -3
- package/dist/cli.js +524 -242
- package/dist/server.js +506 -180
- package/package.json +1 -1
- package/web/assets/{index-BfOACraN.js → index-D6bmQt7Y.js} +1549 -1549
- package/web/index.html +1 -1
package/dist/cli.js
CHANGED
|
@@ -16,165 +16,6 @@ var init_types = __esm({
|
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
// ../runner/src/reverse-standard.ts
|
|
20
|
-
var init_reverse_standard = __esm({
|
|
21
|
-
"../runner/src/reverse-standard.ts"() {
|
|
22
|
-
"use strict";
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// ../runner/src/verify-scope.ts
|
|
27
|
-
var CHANGED;
|
|
28
|
-
var init_verify_scope = __esm({
|
|
29
|
-
"../runner/src/verify-scope.ts"() {
|
|
30
|
-
"use strict";
|
|
31
|
-
CHANGED = [
|
|
32
|
-
"Scope verifikasi: HANYA yang berubah. Mesin ini menjalankan beberapa sesi sekaligus \u2014",
|
|
33
|
-
"memverifikasi seluruh project menghabiskan RAM & CPU yang sedang dipakai sesi lain.",
|
|
34
|
-
"",
|
|
35
|
-
"Berkas yang berubah di worktree ini:",
|
|
36
|
-
'`git diff --name-only "$HANOMAN_BASE_SHA"...HEAD` (yang sudah di-commit) dan',
|
|
37
|
-
"`git status --porcelain` (yang belum).",
|
|
38
|
-
"",
|
|
39
|
-
"- Test: jalankan HANYA test yang berkaitan dengan berkas itu. Repo vitest:",
|
|
40
|
-
' `pnpm vitest --run --changed "$HANOMAN_BASE_SHA"` (vitest sendiri menurunkan berkas yang',
|
|
41
|
-
" berubah dari git, termasuk yang belum di-commit), atau `pnpm vitest related --run <berkas\u2026>`,",
|
|
42
|
-
" atau sebut path berkas test-nya langsung. Stack lain: `pytest <path>`, `go test ./paket/...`.",
|
|
43
|
-
" JANGAN `pnpm test` atau `vitest run` polos \u2014 itu seluruh suite.",
|
|
44
|
-
" Jebakan: `--changed` menyalakan `passWithNoTests`, jadi nol test TERLIHAT hijau. Pastikan",
|
|
45
|
-
' test-nya memang berjalan, jangan menerima "no test files" sebagai bukti.',
|
|
46
|
-
"- Typecheck: hanya paket yang tersentuh (mis. `pnpm --filter ./server typecheck`).",
|
|
47
|
-
" JANGAN `pnpm -r typecheck` \u2014 itu menyalakan satu proses tsc per paket sekaligus.",
|
|
48
|
-
"- Lint: hanya berkas yang berubah, bukan seluruh repo.",
|
|
49
|
-
"- Build penuh: hanya bila yang kamu ubah memang soal build/bundling.",
|
|
50
|
-
"- Boot server + curl / smoke end-to-end: hanya bila task ini menyentuh endpoint atau perilaku",
|
|
51
|
-
" runtime-nya, sekali di akhir \u2014 bukan rutin tiap task.",
|
|
52
|
-
"- Membereskan proses nyangkut: JANGAN `pkill -f <pola>` maupun `killall`. Prompt setiap sesi",
|
|
53
|
-
" hidup di ARGV proses agennya, jadi pola seperti `vitest`/`tsc`/`node` ikut mencocoki agen sesi",
|
|
54
|
-
" LAIN di mesin ini dan mematikannya di tengah kerja \u2014 dan `pkill` mengecualikan leluhurnya",
|
|
55
|
-
" sendiri, jadi yang mati selalu sesi tetangga, bukan sesimu. Bunuh per-PID: `ps`/`lsof -ti:<port>`",
|
|
56
|
-
" \u2192 `kill <pid>`; atau sempitkan polanya sampai memuat path worktree-mu sendiri.",
|
|
57
|
-
"",
|
|
58
|
-
"Suite penuh, lint penuh, dan build penuh adalah tugas MANUSIA sebelum merge, bukan tugas sesi.",
|
|
59
|
-
"Pengecualian yang kamu putuskan sendiri: bila perubahanmu memang berdampak luas (mengubah",
|
|
60
|
-
"tipe/kontrak bersama, skema, atau berkas yang diimpor banyak modul), perluas scope seperlunya",
|
|
61
|
-
"dan katakan alasannya. Ini panduan biaya, bukan larangan."
|
|
62
|
-
].join("\n");
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// ../runner/src/code-style.ts
|
|
67
|
-
var CODE_STYLE_CLAUSE;
|
|
68
|
-
var init_code_style = __esm({
|
|
69
|
-
"../runner/src/code-style.ts"() {
|
|
70
|
-
"use strict";
|
|
71
|
-
CODE_STYLE_CLAUSE = [
|
|
72
|
-
"Gaya kode \u2014 berlaku setiap kali kamu menulis atau mengubah kode:",
|
|
73
|
-
"- Tulis kode yang rapi dan mengikuti idiom, penamaan, serta struktur kode di sekitarnya.",
|
|
74
|
-
" Kodemu harus terbaca seperti kode yang sudah ada di berkas itu, bukan seperti tempelan.",
|
|
75
|
-
"- Jangan menulis komentar yang cuma mengulang apa yang sudah dinyatakan kode.",
|
|
76
|
-
"- Komentar hanya untuk hal yang TIDAK terbaca dari kode: alasan/why sebuah keputusan,",
|
|
77
|
-
" trade-off yang diambil, workaround beserta rujukan SPEC/ADR-nya, atau invariant yang tak",
|
|
78
|
-
" kelihatan. Komentar semacam itu justru berharga \u2014 jangan ikut dibuang.",
|
|
79
|
-
"- Jangan menambahkan komentar pembatas seksi, header berhiasan, atau narasi langkah demi langkah.",
|
|
80
|
-
"- Jangan meninggalkan kode mati atau kode yang dikomentari. Hapus saja; riwayat git yang menyimpannya."
|
|
81
|
-
].join("\n");
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// ../runner/src/goal-spec.ts
|
|
86
|
-
var init_goal_spec = __esm({
|
|
87
|
-
"../runner/src/goal-spec.ts"() {
|
|
88
|
-
"use strict";
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
// ../runner/src/prompt.ts
|
|
93
|
-
var ESCALATION_CONTRACT, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
|
|
94
|
-
var init_prompt = __esm({
|
|
95
|
-
"../runner/src/prompt.ts"() {
|
|
96
|
-
"use strict";
|
|
97
|
-
init_reverse_standard();
|
|
98
|
-
init_verify_scope();
|
|
99
|
-
init_code_style();
|
|
100
|
-
init_goal_spec();
|
|
101
|
-
ESCALATION_CONTRACT = [
|
|
102
|
-
"REKOMENDASI ESKALASI (wajib, terbaca mesin). Di bagian akhir dokumen audit, tulis bagian",
|
|
103
|
-
"`## Rekomendasi eskalasi` berisi penjelasan singkat untuk manusia, LALU tepat SATU blok ```json",
|
|
104
|
-
"berbentuk persis seperti ini (satu-satunya blok json di dokumen itu):",
|
|
105
|
-
"",
|
|
106
|
-
"```json",
|
|
107
|
-
'{ "escalation": { "target": "none|qa|brief|prd", "reason": "<alasan singkat>",',
|
|
108
|
-
' "alternatives": ["<target lain yang masuk akal>"],',
|
|
109
|
-
' "prefill": { "title": "", "context": "", "outcome": "", "constraints": "", "severity": "", "steps": "" } } }',
|
|
110
|
-
"```",
|
|
111
|
-
"",
|
|
112
|
-
"Pilih `target` dari hasil auditmu, bukan default:",
|
|
113
|
-
'- "qa" \u2014 bug / regresi / perilaku salah yang perlu diperbaiki. Isi `prefill.severity`',
|
|
114
|
-
" (critical|major|minor) dan `prefill.steps` (langkah reproduksi).",
|
|
115
|
-
'- "brief" \u2014 kebutuhan/fitur yang bentuknya sudah jelas dan cakupannya satu backlog.',
|
|
116
|
-
" Isi `prefill.title`, `prefill.context`, `prefill.outcome`.",
|
|
117
|
-
'- "prd" \u2014 kebutuhan produk yang besar, ambigu, atau lintas modul sehingga perlu dokumen PRD',
|
|
118
|
-
" lebih dulu. Isi `prefill.title`, `prefill.context`, `prefill.outcome`.",
|
|
119
|
-
'- "none" \u2014 pertanyaannya sudah terjawab; tak perlu perbaikan maupun fitur baru.',
|
|
120
|
-
"",
|
|
121
|
-
"`alternatives` boleh array kosong. Jangan menulis blok json lain di dokumen itu."
|
|
122
|
-
].join("\n");
|
|
123
|
-
REVERSE_PHASE_GUIDE = [
|
|
124
|
-
"- Scan: baca source code \u2014 stack, arsitektur, data model, API surface, perilaku domain. Belum menulis docs.",
|
|
125
|
-
"- Docs teknis: tulis kategori yang bisa diturunkan dari kode (architecture, requirements + EARS dari perilaku nyata, adr ber-Status accepted (reverse-engineered), operations, security, design-system/frontend bila relevan). Isi lengkap dan spesifik, bukan kerangka.",
|
|
126
|
-
"- Wawancara: untuk product, business, brand, research, entrypoints \u2014 ajukan SATU pertanyaan per giliran ke manusia di terminal ini, tunggu jawabannya, isi docs dari jawaban. Jangan mengarang. Topik tanpa jawaban tandai: Status: draft \u2014 menunggu input.",
|
|
127
|
-
"- Konvensi & index: tulis internal/docs/README.md (index bernomor lengkap), CLAUDE.md, AGENTS.md, .claude/settings.json + .claude/hooks/ensure-docs-updated.py persis seperti STANDAR DOCS.",
|
|
128
|
-
"- Serah terima: pastikan setiap berkas docs terdaftar di index, lalu tulis ringkasan hasil + daftar pertanyaan yang belum terjawab ke terminal."
|
|
129
|
-
].join("\n");
|
|
130
|
-
SCAFFOLD_PHASE_GUIDE = [
|
|
131
|
-
"- Brainstorm: perdalam IDE project (di bawah) jadi masalah, pengguna, scope, dan metrik sukses. Ajukan SATU pertanyaan per giliran ke manusia di terminal ini, tunggu jawabannya. Jangan mengarang; topik yang belum dijawab tandai sebagai open question.",
|
|
132
|
-
"- Objective: kunci SATU MVP objective yang terukur dari hasil brainstorm, tulis ringkas di docs.",
|
|
133
|
-
"- Doc index: tulis SELURUH internal/docs/** dari ide+objective+jawaban, mengikuti STANDAR DOCS di bawah \u2014 entrypoints, product, business, requirements (+EARS dari perilaku yang diinginkan), research, architecture (stack/data-model/api-contract/nfr), adr awal (Status accepted), design-system/frontend bila ada UI, operations, security, plus README index bernomor + CLAUDE.md + AGENTS.md + Stop hook. Lengkap dan spesifik terhadap ide ini, BUKAN kerangka."
|
|
134
|
-
].join("\n");
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// ../runner/src/git.ts
|
|
139
|
-
var init_git = __esm({
|
|
140
|
-
"../runner/src/git.ts"() {
|
|
141
|
-
"use strict";
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// ../runner/src/settings.ts
|
|
146
|
-
var init_settings = __esm({
|
|
147
|
-
"../runner/src/settings.ts"() {
|
|
148
|
-
"use strict";
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// ../runner/src/goal.ts
|
|
153
|
-
var init_goal = __esm({
|
|
154
|
-
"../runner/src/goal.ts"() {
|
|
155
|
-
"use strict";
|
|
156
|
-
init_prompt();
|
|
157
|
-
init_goal_spec();
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// ../runner/src/codex-settings.ts
|
|
162
|
-
var init_codex_settings = __esm({
|
|
163
|
-
"../runner/src/codex-settings.ts"() {
|
|
164
|
-
"use strict";
|
|
165
|
-
init_prompt();
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// ../runner/src/agent-cli.ts
|
|
170
|
-
var init_agent_cli = __esm({
|
|
171
|
-
"../runner/src/agent-cli.ts"() {
|
|
172
|
-
"use strict";
|
|
173
|
-
init_settings();
|
|
174
|
-
init_codex_settings();
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
19
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
179
20
|
var util, objectUtil, ZodParsedType, getParsedType;
|
|
180
21
|
var init_util = __esm({
|
|
@@ -4319,6 +4160,120 @@ var init_spec_source = __esm({
|
|
|
4319
4160
|
}
|
|
4320
4161
|
});
|
|
4321
4162
|
|
|
4163
|
+
// ../shared/src/method-catalog.ts
|
|
4164
|
+
function resolveMethod(id) {
|
|
4165
|
+
return (id ? METHODS[id] : void 0) ?? METHODS[DEFAULT_METHOD];
|
|
4166
|
+
}
|
|
4167
|
+
var DEFAULT_METHOD, VERIFICATION_GATE, MATT_CLAUSE, METHODS, METHOD_IDS, uniq, PLAN_DIRS, SPEC_DIRS;
|
|
4168
|
+
var init_method_catalog = __esm({
|
|
4169
|
+
"../shared/src/method-catalog.ts"() {
|
|
4170
|
+
"use strict";
|
|
4171
|
+
DEFAULT_METHOD = "superpowers";
|
|
4172
|
+
VERIFICATION_GATE = "superpowers:verification-before-completion";
|
|
4173
|
+
MATT_CLAUSE = "Sesi ini TAK BERPENUNGGU \u2014 tak ada manusia yang menonton terminal untuk menjawab. Skill mattpocock yang kontraknya mewawancarai manusia (`/grill-me`, `/to-spec`, `/triage`) JANGAN dipakai: pakai primitif model-invoked-nya dan putuskan sendiri. `to-tickets` di fase Plan dipakai HANYA sebagai penghasil berkas plan berkotak `- [ ]` di `docs/matt/plans/`, BUKAN penerbit tiket \u2014 hanoman sendiri adalah issue tracker-nya, jadi jangan menulis ke tracker eksternal mana pun.";
|
|
4174
|
+
METHODS = {
|
|
4175
|
+
// Isi `PHASE_SKILLS` (SPEC-166) dipindah APA ADANYA. Objective & Spec adalah keluaran skill
|
|
4176
|
+
// brainstorming yang di-invoke di fase Brainstorm — sengaja tak punya entri sendiri. Fase reverse
|
|
4177
|
+
// dipandu standar docs di prompt-nya, bukan skill.
|
|
4178
|
+
superpowers: {
|
|
4179
|
+
id: "superpowers",
|
|
4180
|
+
label: "superpowers",
|
|
4181
|
+
planDir: "docs/superpowers/plans",
|
|
4182
|
+
specDir: "docs/superpowers/specs",
|
|
4183
|
+
phaseSkills: {
|
|
4184
|
+
Brainstorm: ["superpowers:brainstorming"],
|
|
4185
|
+
Audit: ["superpowers:systematic-debugging"],
|
|
4186
|
+
Plan: ["superpowers:writing-plans"],
|
|
4187
|
+
Execute: [
|
|
4188
|
+
"superpowers:executing-plans",
|
|
4189
|
+
"superpowers:test-driven-development",
|
|
4190
|
+
VERIFICATION_GATE
|
|
4191
|
+
],
|
|
4192
|
+
// SPEC-407 · fase `Goal` sengaja TANPA skill: seluruh inti flow itu membebaskan sesi dari
|
|
4193
|
+
// proses kaku. Yang tetap dijaga cuma pintu keluarnya.
|
|
4194
|
+
Verifikasi: [VERIFICATION_GATE]
|
|
4195
|
+
},
|
|
4196
|
+
exitSkills: [VERIFICATION_GATE],
|
|
4197
|
+
requires: ["superpowers"],
|
|
4198
|
+
install: {
|
|
4199
|
+
claude: [
|
|
4200
|
+
"claude plugin marketplace add obra/superpowers-marketplace",
|
|
4201
|
+
"claude plugin install superpowers@superpowers-marketplace"
|
|
4202
|
+
],
|
|
4203
|
+
codex: ["codex plugin add superpowers@openai-curated"]
|
|
4204
|
+
}
|
|
4205
|
+
},
|
|
4206
|
+
// Plugin `mattpocock-skills` (`/plugin install mattpocock-skills`); skill plugin di Claude Code
|
|
4207
|
+
// beralamat `plugin:skill`. `superpowers` tetap ikut di `requires` karena gerbang verifikasinya
|
|
4208
|
+
// dipinjam dari sana — mattpocock tak punya padanannya.
|
|
4209
|
+
matt: {
|
|
4210
|
+
id: "matt",
|
|
4211
|
+
label: "mattpocock",
|
|
4212
|
+
planDir: "docs/matt/plans",
|
|
4213
|
+
specDir: "docs/matt/specs",
|
|
4214
|
+
phaseSkills: {
|
|
4215
|
+
Brainstorm: ["mattpocock-skills:grilling"],
|
|
4216
|
+
Audit: ["mattpocock-skills:diagnosing-bugs"],
|
|
4217
|
+
Plan: ["mattpocock-skills:to-tickets"],
|
|
4218
|
+
Execute: [
|
|
4219
|
+
"mattpocock-skills:implement",
|
|
4220
|
+
"mattpocock-skills:tdd",
|
|
4221
|
+
"mattpocock-skills:code-review"
|
|
4222
|
+
],
|
|
4223
|
+
Verifikasi: [VERIFICATION_GATE]
|
|
4224
|
+
},
|
|
4225
|
+
exitSkills: [VERIFICATION_GATE],
|
|
4226
|
+
extraClause: MATT_CLAUSE,
|
|
4227
|
+
requires: ["mattpocock-skills", "superpowers"],
|
|
4228
|
+
// `mattpocock-skills` ada di marketplace resmi Claude Code → tanpa `marketplace add`.
|
|
4229
|
+
// superpowers ikut dipasang karena `requires` menyebutnya: gerbang verifikasinya dipinjam
|
|
4230
|
+
// dari sana (INVARIAN 2). codex belum punya plugin native mattpocock — jalur resminya
|
|
4231
|
+
// `npx skills`, dan ia INTERAKTIF; itu justru alasan pemasangan hidup di pane yang ditonton.
|
|
4232
|
+
install: {
|
|
4233
|
+
claude: [
|
|
4234
|
+
"claude plugin install mattpocock-skills",
|
|
4235
|
+
"claude plugin marketplace add obra/superpowers-marketplace",
|
|
4236
|
+
"claude plugin install superpowers@superpowers-marketplace"
|
|
4237
|
+
],
|
|
4238
|
+
codex: [
|
|
4239
|
+
"npx skills@latest add mattpocock/skills",
|
|
4240
|
+
"codex plugin add superpowers@openai-curated"
|
|
4241
|
+
]
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
};
|
|
4245
|
+
METHOD_IDS = Object.keys(METHODS);
|
|
4246
|
+
uniq = (xs) => [...new Set(xs)];
|
|
4247
|
+
PLAN_DIRS = uniq(METHOD_IDS.map((id) => METHODS[id].planDir));
|
|
4248
|
+
SPEC_DIRS = uniq(METHOD_IDS.map((id) => METHODS[id].specDir));
|
|
4249
|
+
}
|
|
4250
|
+
});
|
|
4251
|
+
|
|
4252
|
+
// ../shared/src/method-status.ts
|
|
4253
|
+
function methodSkills(m) {
|
|
4254
|
+
return [.../* @__PURE__ */ new Set([...Object.values(m.phaseSkills).flat(), ...m.exitSkills])];
|
|
4255
|
+
}
|
|
4256
|
+
function methodStatus(m, agent, installed) {
|
|
4257
|
+
const haveSkills = new Set(installed.skills);
|
|
4258
|
+
const havePackages = new Set(installed.packages);
|
|
4259
|
+
const missingPackages = m.requires.filter((p) => !havePackages.has(p));
|
|
4260
|
+
const missingSkills = methodSkills(m).filter((id) => !haveSkills.has(id));
|
|
4261
|
+
return {
|
|
4262
|
+
method: m.id,
|
|
4263
|
+
label: m.label,
|
|
4264
|
+
agent,
|
|
4265
|
+
ready: missingPackages.length === 0 && missingSkills.length === 0,
|
|
4266
|
+
missingPackages,
|
|
4267
|
+
missingSkills,
|
|
4268
|
+
install: [...m.install[agent]]
|
|
4269
|
+
};
|
|
4270
|
+
}
|
|
4271
|
+
var init_method_status = __esm({
|
|
4272
|
+
"../shared/src/method-status.ts"() {
|
|
4273
|
+
"use strict";
|
|
4274
|
+
}
|
|
4275
|
+
});
|
|
4276
|
+
|
|
4322
4277
|
// ../shared/src/agent-engine.ts
|
|
4323
4278
|
var zAgentEngine;
|
|
4324
4279
|
var init_agent_engine = __esm({
|
|
@@ -4465,6 +4420,7 @@ var init_entities = __esm({
|
|
|
4465
4420
|
init_telegram();
|
|
4466
4421
|
init_agent_engine();
|
|
4467
4422
|
init_auto_merge();
|
|
4423
|
+
init_method_catalog();
|
|
4468
4424
|
zProject = external_exports.object({
|
|
4469
4425
|
id: external_exports.string(),
|
|
4470
4426
|
name: external_exports.string(),
|
|
@@ -4664,6 +4620,12 @@ var init_entities = __esm({
|
|
|
4664
4620
|
// SPEC-338 · ADR-0074 · model/effort codex
|
|
4665
4621
|
verifyScope: zVerifyScope.default("changed"),
|
|
4666
4622
|
// SPEC-376 · ADR-0080 · scope verifikasi sesi
|
|
4623
|
+
// SPEC-734 · ADR-0113 · metode workflow default. LENIENT (`z.string()`, bukan `z.enum`):
|
|
4624
|
+
// instance yang di-sync dari hub bisa membawa id metode yang belum ada di build ini, dan itu
|
|
4625
|
+
// harus jadi fallback diam di titik pakai (`resolveMethod`) — bukan baris Setting yang gagal
|
|
4626
|
+
// parse lalu mengosongkan layar Settings. Alasan yang sama dengan model/effort di sini.
|
|
4627
|
+
method: external_exports.string().default(DEFAULT_METHOD),
|
|
4628
|
+
// SPEC-734 · ADR-0113 · metode workflow default
|
|
4667
4629
|
conflict: zConflict.default(CONFLICT_DEFAULTS),
|
|
4668
4630
|
// SPEC-383 · ADR-0081 · default sesi konflik rebase/merge
|
|
4669
4631
|
lead: zLead.default(LEAD_DEFAULTS),
|
|
@@ -5378,7 +5340,15 @@ var init_dto = __esm({
|
|
|
5378
5340
|
// SPEC-236 · terminal biasa NON-claude: shell mentah di repoDir project. Tanpa flow (bukan
|
|
5379
5341
|
// pipeline claude). DIDAHULUKAN: z.object non-strict membuang key asing, jadi bila varian
|
|
5380
5342
|
// longgar {project,flow?} lebih dulu, {project,shell:true} akan lolos sbg plain (shell dibuang).
|
|
5381
|
-
|
|
5343
|
+
// SPEC-739 · ADR-0114 · pemasangan skill metode: klien mengirim METODE + AGEN, bukan teks
|
|
5344
|
+
// perintah — perintahnya diturunkan server dari katalog `METHODS`. Dengan begitu "perintah
|
|
5345
|
+
// instalasi adalah data katalog" berlaku ujung ke ujung, dan endpoint ini tak pernah menjadi
|
|
5346
|
+
// "jalankan shell arbitrer". Tanpa field ini, shell mentah persis seperti SPEC-236.
|
|
5347
|
+
external_exports.object({
|
|
5348
|
+
project: external_exports.string(),
|
|
5349
|
+
shell: external_exports.literal(true),
|
|
5350
|
+
install: external_exports.object({ method: external_exports.string(), agent: zAgent }).optional()
|
|
5351
|
+
}),
|
|
5382
5352
|
// SPEC-166 · "reverse" = sesi project-level di worktree-nya sendiri, menyusun Source of Truth
|
|
5383
5353
|
// dari kode. TANPA override runtime: sesi project-level mengikuti Setting.agent (ADR-0074).
|
|
5384
5354
|
// Terminal biasa (tanpa flow) kini punya variannya SENDIRI di bawah — lihat SPEC-517.
|
|
@@ -5425,6 +5395,10 @@ var init_dto = __esm({
|
|
|
5425
5395
|
goalCondition: external_exports.string().max(4e3).optional(),
|
|
5426
5396
|
agent: zAgent.optional(),
|
|
5427
5397
|
verifyScope: zVerifyScope.optional(),
|
|
5398
|
+
// SPEC-734 · ADR-0113 — metode workflow per SESI: undefined → Spec.payload.method →
|
|
5399
|
+
// Setting.method → "superpowers". LENIENT (`z.string()`, bukan `z.enum`): id yang tak dikenal
|
|
5400
|
+
// jatuh ke default di `resolveMethod`, bukan ditolak 400 — alasan yang sama dengan zSetting.
|
|
5401
|
+
method: external_exports.string().optional(),
|
|
5428
5402
|
// SPEC-447 · ADR-0093 — lewati gerbang dependency. Hanya jalur manusia; UI hanya
|
|
5429
5403
|
// mengirimkannya sesudah operator melihat daftar pemblokirnya.
|
|
5430
5404
|
force: external_exports.boolean().optional()
|
|
@@ -5618,6 +5592,8 @@ var init_api = __esm({
|
|
|
5618
5592
|
limits: `${API}/limits`,
|
|
5619
5593
|
// SPEC-339 · versi codex CLI (peringatan lunak model GPT-5.6).
|
|
5620
5594
|
codexVersion: `${API}/codex/version`,
|
|
5595
|
+
// SPEC-739 · ADR-0114 · kesiapan skill metode per agen. LOCAL-only, diturunkan live dari disk.
|
|
5596
|
+
methodStatus: `${API}/methods/status`,
|
|
5621
5597
|
// SPEC-489 · panduan AI agent — markdown MENTAH & PUBLIC (tanpa auth). Satu definisi URL untuk
|
|
5622
5598
|
// klien web dan untuk tautan yang disalin operator ke agennya.
|
|
5623
5599
|
agentDoc: `${API}/agent-integration.md`,
|
|
@@ -7146,6 +7122,8 @@ var init_src = __esm({
|
|
|
7146
7122
|
"use strict";
|
|
7147
7123
|
init_enums();
|
|
7148
7124
|
init_spec_source();
|
|
7125
|
+
init_method_catalog();
|
|
7126
|
+
init_method_status();
|
|
7149
7127
|
init_agent_engine();
|
|
7150
7128
|
init_entities();
|
|
7151
7129
|
init_agent();
|
|
@@ -7172,6 +7150,169 @@ var init_src = __esm({
|
|
|
7172
7150
|
}
|
|
7173
7151
|
});
|
|
7174
7152
|
|
|
7153
|
+
// ../runner/src/reverse-standard.ts
|
|
7154
|
+
var init_reverse_standard = __esm({
|
|
7155
|
+
"../runner/src/reverse-standard.ts"() {
|
|
7156
|
+
"use strict";
|
|
7157
|
+
}
|
|
7158
|
+
});
|
|
7159
|
+
|
|
7160
|
+
// ../runner/src/verify-scope.ts
|
|
7161
|
+
var CHANGED;
|
|
7162
|
+
var init_verify_scope = __esm({
|
|
7163
|
+
"../runner/src/verify-scope.ts"() {
|
|
7164
|
+
"use strict";
|
|
7165
|
+
CHANGED = [
|
|
7166
|
+
"Scope verifikasi: HANYA yang berubah. Mesin ini menjalankan beberapa sesi sekaligus \u2014",
|
|
7167
|
+
"memverifikasi seluruh project menghabiskan RAM & CPU yang sedang dipakai sesi lain.",
|
|
7168
|
+
"",
|
|
7169
|
+
"Berkas yang berubah di worktree ini:",
|
|
7170
|
+
'`git diff --name-only "$HANOMAN_BASE_SHA"...HEAD` (yang sudah di-commit) dan',
|
|
7171
|
+
"`git status --porcelain` (yang belum).",
|
|
7172
|
+
"",
|
|
7173
|
+
"- Test: jalankan HANYA test yang berkaitan dengan berkas itu. Repo vitest:",
|
|
7174
|
+
' `pnpm vitest --run --changed "$HANOMAN_BASE_SHA"` (vitest sendiri menurunkan berkas yang',
|
|
7175
|
+
" berubah dari git, termasuk yang belum di-commit), atau `pnpm vitest related --run <berkas\u2026>`,",
|
|
7176
|
+
" atau sebut path berkas test-nya langsung. Stack lain: `pytest <path>`, `go test ./paket/...`.",
|
|
7177
|
+
" JANGAN `pnpm test` atau `vitest run` polos \u2014 itu seluruh suite.",
|
|
7178
|
+
" Jebakan: `--changed` menyalakan `passWithNoTests`, jadi nol test TERLIHAT hijau. Pastikan",
|
|
7179
|
+
' test-nya memang berjalan, jangan menerima "no test files" sebagai bukti.',
|
|
7180
|
+
"- Typecheck: hanya paket yang tersentuh (mis. `pnpm --filter ./server typecheck`).",
|
|
7181
|
+
" JANGAN `pnpm -r typecheck` \u2014 itu menyalakan satu proses tsc per paket sekaligus.",
|
|
7182
|
+
"- Lint: hanya berkas yang berubah, bukan seluruh repo.",
|
|
7183
|
+
"- Build penuh: hanya bila yang kamu ubah memang soal build/bundling.",
|
|
7184
|
+
"- Boot server + curl / smoke end-to-end: hanya bila task ini menyentuh endpoint atau perilaku",
|
|
7185
|
+
" runtime-nya, sekali di akhir \u2014 bukan rutin tiap task.",
|
|
7186
|
+
"- Membereskan proses nyangkut: JANGAN `pkill -f <pola>` maupun `killall`. Prompt setiap sesi",
|
|
7187
|
+
" hidup di ARGV proses agennya, jadi pola seperti `vitest`/`tsc`/`node` ikut mencocoki agen sesi",
|
|
7188
|
+
" LAIN di mesin ini dan mematikannya di tengah kerja \u2014 dan `pkill` mengecualikan leluhurnya",
|
|
7189
|
+
" sendiri, jadi yang mati selalu sesi tetangga, bukan sesimu. Bunuh per-PID: `ps`/`lsof -ti:<port>`",
|
|
7190
|
+
" \u2192 `kill <pid>`; atau sempitkan polanya sampai memuat path worktree-mu sendiri.",
|
|
7191
|
+
"",
|
|
7192
|
+
"Suite penuh, lint penuh, dan build penuh adalah tugas MANUSIA sebelum merge, bukan tugas sesi.",
|
|
7193
|
+
"Pengecualian yang kamu putuskan sendiri: bila perubahanmu memang berdampak luas (mengubah",
|
|
7194
|
+
"tipe/kontrak bersama, skema, atau berkas yang diimpor banyak modul), perluas scope seperlunya",
|
|
7195
|
+
"dan katakan alasannya. Ini panduan biaya, bukan larangan."
|
|
7196
|
+
].join("\n");
|
|
7197
|
+
}
|
|
7198
|
+
});
|
|
7199
|
+
|
|
7200
|
+
// ../runner/src/code-style.ts
|
|
7201
|
+
var CODE_STYLE_CLAUSE;
|
|
7202
|
+
var init_code_style = __esm({
|
|
7203
|
+
"../runner/src/code-style.ts"() {
|
|
7204
|
+
"use strict";
|
|
7205
|
+
CODE_STYLE_CLAUSE = [
|
|
7206
|
+
"Gaya kode \u2014 berlaku setiap kali kamu menulis atau mengubah kode:",
|
|
7207
|
+
"- Tulis kode yang rapi dan mengikuti idiom, penamaan, serta struktur kode di sekitarnya.",
|
|
7208
|
+
" Kodemu harus terbaca seperti kode yang sudah ada di berkas itu, bukan seperti tempelan.",
|
|
7209
|
+
"- Jangan menulis komentar yang cuma mengulang apa yang sudah dinyatakan kode.",
|
|
7210
|
+
"- Komentar hanya untuk hal yang TIDAK terbaca dari kode: alasan/why sebuah keputusan,",
|
|
7211
|
+
" trade-off yang diambil, workaround beserta rujukan SPEC/ADR-nya, atau invariant yang tak",
|
|
7212
|
+
" kelihatan. Komentar semacam itu justru berharga \u2014 jangan ikut dibuang.",
|
|
7213
|
+
"- Jangan menambahkan komentar pembatas seksi, header berhiasan, atau narasi langkah demi langkah.",
|
|
7214
|
+
"- Jangan meninggalkan kode mati atau kode yang dikomentari. Hapus saja; riwayat git yang menyimpannya."
|
|
7215
|
+
].join("\n");
|
|
7216
|
+
}
|
|
7217
|
+
});
|
|
7218
|
+
|
|
7219
|
+
// ../runner/src/goal-spec.ts
|
|
7220
|
+
var init_goal_spec = __esm({
|
|
7221
|
+
"../runner/src/goal-spec.ts"() {
|
|
7222
|
+
"use strict";
|
|
7223
|
+
}
|
|
7224
|
+
});
|
|
7225
|
+
|
|
7226
|
+
// ../runner/src/prompt.ts
|
|
7227
|
+
var ESCALATION_CONTRACT, PROJECT_METHOD, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
|
|
7228
|
+
var init_prompt = __esm({
|
|
7229
|
+
"../runner/src/prompt.ts"() {
|
|
7230
|
+
"use strict";
|
|
7231
|
+
init_src();
|
|
7232
|
+
init_reverse_standard();
|
|
7233
|
+
init_verify_scope();
|
|
7234
|
+
init_code_style();
|
|
7235
|
+
init_goal_spec();
|
|
7236
|
+
ESCALATION_CONTRACT = [
|
|
7237
|
+
"REKOMENDASI ESKALASI (wajib, terbaca mesin). Di bagian akhir dokumen audit, tulis bagian",
|
|
7238
|
+
"`## Rekomendasi eskalasi` berisi penjelasan singkat untuk manusia, LALU tepat SATU blok ```json",
|
|
7239
|
+
"berbentuk persis seperti ini (satu-satunya blok json di dokumen itu):",
|
|
7240
|
+
"",
|
|
7241
|
+
"```json",
|
|
7242
|
+
'{ "escalation": { "target": "none|qa|brief|prd", "reason": "<alasan singkat>",',
|
|
7243
|
+
' "alternatives": ["<target lain yang masuk akal>"],',
|
|
7244
|
+
' "prefill": { "title": "", "context": "", "outcome": "", "constraints": "", "severity": "", "steps": "" } } }',
|
|
7245
|
+
"```",
|
|
7246
|
+
"",
|
|
7247
|
+
"Pilih `target` dari hasil auditmu, bukan default:",
|
|
7248
|
+
'- "qa" \u2014 bug / regresi / perilaku salah yang perlu diperbaiki. Isi `prefill.severity`',
|
|
7249
|
+
" (critical|major|minor) dan `prefill.steps` (langkah reproduksi).",
|
|
7250
|
+
'- "brief" \u2014 kebutuhan/fitur yang bentuknya sudah jelas dan cakupannya satu backlog.',
|
|
7251
|
+
" Isi `prefill.title`, `prefill.context`, `prefill.outcome`.",
|
|
7252
|
+
'- "prd" \u2014 kebutuhan produk yang besar, ambigu, atau lintas modul sehingga perlu dokumen PRD',
|
|
7253
|
+
" lebih dulu. Isi `prefill.title`, `prefill.context`, `prefill.outcome`.",
|
|
7254
|
+
'- "none" \u2014 pertanyaannya sudah terjawab; tak perlu perbaikan maupun fitur baru.',
|
|
7255
|
+
"",
|
|
7256
|
+
"`alternatives` boleh array kosong. Jangan menulis blok json lain di dokumen itu."
|
|
7257
|
+
].join("\n");
|
|
7258
|
+
PROJECT_METHOD = resolveMethod();
|
|
7259
|
+
REVERSE_PHASE_GUIDE = [
|
|
7260
|
+
"- Scan: baca source code \u2014 stack, arsitektur, data model, API surface, perilaku domain. Belum menulis docs.",
|
|
7261
|
+
"- Docs teknis: tulis kategori yang bisa diturunkan dari kode (architecture, requirements + EARS dari perilaku nyata, adr ber-Status accepted (reverse-engineered), operations, security, design-system/frontend bila relevan). Isi lengkap dan spesifik, bukan kerangka.",
|
|
7262
|
+
"- Wawancara: untuk product, business, brand, research, entrypoints \u2014 ajukan SATU pertanyaan per giliran ke manusia di terminal ini, tunggu jawabannya, isi docs dari jawaban. Jangan mengarang. Topik tanpa jawaban tandai: Status: draft \u2014 menunggu input.",
|
|
7263
|
+
"- Konvensi & index: tulis internal/docs/README.md (index bernomor lengkap), CLAUDE.md, AGENTS.md, .claude/settings.json + .claude/hooks/ensure-docs-updated.py persis seperti STANDAR DOCS.",
|
|
7264
|
+
"- Serah terima: pastikan setiap berkas docs terdaftar di index, lalu tulis ringkasan hasil + daftar pertanyaan yang belum terjawab ke terminal."
|
|
7265
|
+
].join("\n");
|
|
7266
|
+
SCAFFOLD_PHASE_GUIDE = [
|
|
7267
|
+
"- Brainstorm: perdalam IDE project (di bawah) jadi masalah, pengguna, scope, dan metrik sukses. Ajukan SATU pertanyaan per giliran ke manusia di terminal ini, tunggu jawabannya. Jangan mengarang; topik yang belum dijawab tandai sebagai open question.",
|
|
7268
|
+
"- Objective: kunci SATU MVP objective yang terukur dari hasil brainstorm, tulis ringkas di docs.",
|
|
7269
|
+
"- Doc index: tulis SELURUH internal/docs/** dari ide+objective+jawaban, mengikuti STANDAR DOCS di bawah \u2014 entrypoints, product, business, requirements (+EARS dari perilaku yang diinginkan), research, architecture (stack/data-model/api-contract/nfr), adr awal (Status accepted), design-system/frontend bila ada UI, operations, security, plus README index bernomor + CLAUDE.md + AGENTS.md + Stop hook. Lengkap dan spesifik terhadap ide ini, BUKAN kerangka."
|
|
7270
|
+
].join("\n");
|
|
7271
|
+
}
|
|
7272
|
+
});
|
|
7273
|
+
|
|
7274
|
+
// ../runner/src/git.ts
|
|
7275
|
+
var init_git = __esm({
|
|
7276
|
+
"../runner/src/git.ts"() {
|
|
7277
|
+
"use strict";
|
|
7278
|
+
}
|
|
7279
|
+
});
|
|
7280
|
+
|
|
7281
|
+
// ../runner/src/settings.ts
|
|
7282
|
+
var init_settings = __esm({
|
|
7283
|
+
"../runner/src/settings.ts"() {
|
|
7284
|
+
"use strict";
|
|
7285
|
+
}
|
|
7286
|
+
});
|
|
7287
|
+
|
|
7288
|
+
// ../runner/src/goal.ts
|
|
7289
|
+
var init_goal = __esm({
|
|
7290
|
+
"../runner/src/goal.ts"() {
|
|
7291
|
+
"use strict";
|
|
7292
|
+
init_src();
|
|
7293
|
+
init_prompt();
|
|
7294
|
+
init_goal_spec();
|
|
7295
|
+
}
|
|
7296
|
+
});
|
|
7297
|
+
|
|
7298
|
+
// ../runner/src/codex-settings.ts
|
|
7299
|
+
var init_codex_settings = __esm({
|
|
7300
|
+
"../runner/src/codex-settings.ts"() {
|
|
7301
|
+
"use strict";
|
|
7302
|
+
init_src();
|
|
7303
|
+
init_prompt();
|
|
7304
|
+
}
|
|
7305
|
+
});
|
|
7306
|
+
|
|
7307
|
+
// ../runner/src/agent-cli.ts
|
|
7308
|
+
var init_agent_cli = __esm({
|
|
7309
|
+
"../runner/src/agent-cli.ts"() {
|
|
7310
|
+
"use strict";
|
|
7311
|
+
init_settings();
|
|
7312
|
+
init_codex_settings();
|
|
7313
|
+
}
|
|
7314
|
+
});
|
|
7315
|
+
|
|
7175
7316
|
// ../runner/src/custom-agents.ts
|
|
7176
7317
|
var init_custom_agents = __esm({
|
|
7177
7318
|
"../runner/src/custom-agents.ts"() {
|
|
@@ -7238,6 +7379,128 @@ var init_paths = __esm({
|
|
|
7238
7379
|
}
|
|
7239
7380
|
});
|
|
7240
7381
|
|
|
7382
|
+
// ../runner/src/skills.ts
|
|
7383
|
+
import { homedir as homedir2 } from "node:os";
|
|
7384
|
+
import { join as join2 } from "node:path";
|
|
7385
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
7386
|
+
function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
|
|
7387
|
+
const own = (agent === "codex" ? env.HANOMAN_CODEX_HOME : env.HANOMAN_CLAUDE_HOME)?.trim();
|
|
7388
|
+
if (own) return own;
|
|
7389
|
+
if (agent === "codex") {
|
|
7390
|
+
const cx = env.CODEX_HOME?.trim();
|
|
7391
|
+
if (cx) return cx;
|
|
7392
|
+
}
|
|
7393
|
+
return join2(osHome, agent === "codex" ? ".codex" : ".claude");
|
|
7394
|
+
}
|
|
7395
|
+
function dirsIn(dir) {
|
|
7396
|
+
try {
|
|
7397
|
+
return readdirSync(dir, { withFileTypes: true }).filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith(".")).map((e) => e.name);
|
|
7398
|
+
} catch {
|
|
7399
|
+
return [];
|
|
7400
|
+
}
|
|
7401
|
+
}
|
|
7402
|
+
function readJson(file) {
|
|
7403
|
+
try {
|
|
7404
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
7405
|
+
} catch {
|
|
7406
|
+
return null;
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7409
|
+
function skillsUnder(dir, pkg) {
|
|
7410
|
+
return dirsIn(dir).filter((name) => existsSync(join2(dir, name, "SKILL.md"))).map((name) => ({ id: pkg ? `${pkg}:${name}` : name, name, pkg, dir: join2(dir, name) }));
|
|
7411
|
+
}
|
|
7412
|
+
function splitPluginKey(key) {
|
|
7413
|
+
const at = key.lastIndexOf("@");
|
|
7414
|
+
return at > 0 ? { pkg: key.slice(0, at), marketplace: key.slice(at + 1) } : { pkg: key, marketplace: "" };
|
|
7415
|
+
}
|
|
7416
|
+
function manifestRoots(home) {
|
|
7417
|
+
const j = readJson(join2(home, "plugins", "installed_plugins.json"));
|
|
7418
|
+
const plugins = j?.plugins;
|
|
7419
|
+
if (!plugins || typeof plugins !== "object") return [];
|
|
7420
|
+
const out = [];
|
|
7421
|
+
for (const [key, entries] of Object.entries(plugins)) {
|
|
7422
|
+
const { pkg, marketplace } = splitPluginKey(key);
|
|
7423
|
+
for (const e of Array.isArray(entries) ? entries : []) {
|
|
7424
|
+
const p = e?.installPath;
|
|
7425
|
+
if (typeof p === "string" && p) out.push({ pkg, marketplace, dir: p });
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7428
|
+
return out;
|
|
7429
|
+
}
|
|
7430
|
+
function cacheRoots(home) {
|
|
7431
|
+
const cache = join2(home, "plugins", "cache");
|
|
7432
|
+
const out = [];
|
|
7433
|
+
for (const marketplace of dirsIn(cache))
|
|
7434
|
+
for (const pkg of dirsIn(join2(cache, marketplace)))
|
|
7435
|
+
for (const version3 of dirsIn(join2(cache, marketplace, pkg)))
|
|
7436
|
+
out.push({ pkg, marketplace, dir: join2(cache, marketplace, pkg, version3) });
|
|
7437
|
+
return out;
|
|
7438
|
+
}
|
|
7439
|
+
function disabledPlugins(agent, home) {
|
|
7440
|
+
const out = /* @__PURE__ */ new Set();
|
|
7441
|
+
if (agent === "claude") {
|
|
7442
|
+
const en = readJson(join2(home, "settings.json"))?.enabledPlugins;
|
|
7443
|
+
if (en && typeof en === "object") {
|
|
7444
|
+
for (const [k, v] of Object.entries(en)) if (v === false) out.add(k);
|
|
7445
|
+
}
|
|
7446
|
+
return out;
|
|
7447
|
+
}
|
|
7448
|
+
let toml;
|
|
7449
|
+
try {
|
|
7450
|
+
toml = readFileSync(join2(home, "config.toml"), "utf8");
|
|
7451
|
+
} catch {
|
|
7452
|
+
return out;
|
|
7453
|
+
}
|
|
7454
|
+
let current = null;
|
|
7455
|
+
for (const raw of toml.split("\n")) {
|
|
7456
|
+
const line = raw.trim();
|
|
7457
|
+
const head = /^\[([^\]]*)\]$/.exec(line);
|
|
7458
|
+
if (head) {
|
|
7459
|
+
const m = /^plugins\."(.+)"$/.exec(head[1] ?? "");
|
|
7460
|
+
current = m ? m[1] : null;
|
|
7461
|
+
continue;
|
|
7462
|
+
}
|
|
7463
|
+
if (current && /^enabled\s*=\s*false\b/.test(line)) out.add(current);
|
|
7464
|
+
}
|
|
7465
|
+
return out;
|
|
7466
|
+
}
|
|
7467
|
+
function scanAgentSkills(agent, env = process.env, osHome = homedir2()) {
|
|
7468
|
+
const home = agentSkillHome(agent, env, osHome);
|
|
7469
|
+
const disabled = disabledPlugins(agent, home);
|
|
7470
|
+
const roots = [];
|
|
7471
|
+
const skills = [];
|
|
7472
|
+
const packages = /* @__PURE__ */ new Set();
|
|
7473
|
+
const seenSkill = /* @__PURE__ */ new Set();
|
|
7474
|
+
const seenRoot = /* @__PURE__ */ new Set();
|
|
7475
|
+
const add = (dir, found) => {
|
|
7476
|
+
if (!found.length) return;
|
|
7477
|
+
if (!seenRoot.has(dir)) {
|
|
7478
|
+
seenRoot.add(dir);
|
|
7479
|
+
roots.push(dir);
|
|
7480
|
+
}
|
|
7481
|
+
for (const s2 of found) if (!seenSkill.has(s2.id)) {
|
|
7482
|
+
seenSkill.add(s2.id);
|
|
7483
|
+
skills.push(s2);
|
|
7484
|
+
}
|
|
7485
|
+
};
|
|
7486
|
+
const userDir = join2(home, "skills");
|
|
7487
|
+
add(userDir, skillsUnder(userDir, null));
|
|
7488
|
+
for (const r of [...manifestRoots(home), ...cacheRoots(home)]) {
|
|
7489
|
+
if (disabled.has(`${r.pkg}@${r.marketplace}`)) continue;
|
|
7490
|
+
const dir = join2(r.dir, "skills");
|
|
7491
|
+
const found = skillsUnder(dir, r.pkg);
|
|
7492
|
+
if (!found.length) continue;
|
|
7493
|
+
packages.add(r.pkg);
|
|
7494
|
+
add(dir, found);
|
|
7495
|
+
}
|
|
7496
|
+
return { agent, home, roots, skills, packages: [...packages] };
|
|
7497
|
+
}
|
|
7498
|
+
var init_skills = __esm({
|
|
7499
|
+
"../runner/src/skills.ts"() {
|
|
7500
|
+
"use strict";
|
|
7501
|
+
}
|
|
7502
|
+
});
|
|
7503
|
+
|
|
7241
7504
|
// ../runner/src/telegram-operator.ts
|
|
7242
7505
|
var init_telegram_operator = __esm({
|
|
7243
7506
|
"../runner/src/telegram-operator.ts"() {
|
|
@@ -7262,29 +7525,30 @@ var init_src2 = __esm({
|
|
|
7262
7525
|
init_verify_scope();
|
|
7263
7526
|
init_code_style();
|
|
7264
7527
|
init_paths();
|
|
7528
|
+
init_skills();
|
|
7265
7529
|
init_telegram_operator();
|
|
7266
7530
|
}
|
|
7267
7531
|
});
|
|
7268
7532
|
|
|
7269
7533
|
// src/layout.ts
|
|
7270
|
-
import { join as
|
|
7534
|
+
import { join as join3, resolve as resolve2 } from "node:path";
|
|
7271
7535
|
function resolveLayout(distDir2, exists) {
|
|
7272
7536
|
const pkg = resolve2(distDir2, "..");
|
|
7273
|
-
if (exists(
|
|
7537
|
+
if (exists(join3(pkg, "prisma", "schema.prisma"))) {
|
|
7274
7538
|
return {
|
|
7275
7539
|
root: pkg,
|
|
7276
|
-
schema:
|
|
7277
|
-
server:
|
|
7278
|
-
web: exists(
|
|
7540
|
+
schema: join3(pkg, "prisma", "schema.prisma"),
|
|
7541
|
+
server: join3(pkg, "dist", "server.js"),
|
|
7542
|
+
web: exists(join3(pkg, "web")) ? join3(pkg, "web") : null
|
|
7279
7543
|
};
|
|
7280
7544
|
}
|
|
7281
7545
|
const repo = resolve2(distDir2, "../..");
|
|
7282
|
-
if (exists(
|
|
7546
|
+
if (exists(join3(repo, "server", "prisma", "schema.prisma"))) {
|
|
7283
7547
|
return {
|
|
7284
7548
|
root: repo,
|
|
7285
|
-
schema:
|
|
7286
|
-
server:
|
|
7287
|
-
web: exists(
|
|
7549
|
+
schema: join3(repo, "server", "prisma", "schema.prisma"),
|
|
7550
|
+
server: join3(repo, "server", "dist", "server.js"),
|
|
7551
|
+
web: exists(join3(repo, "src", "dist")) ? join3(repo, "src", "dist") : null
|
|
7288
7552
|
};
|
|
7289
7553
|
}
|
|
7290
7554
|
throw new Error(`hanoman: prisma/schema.prisma tak ditemukan dari ${distDir2} \u2014 instalasi rusak?`);
|
|
@@ -7382,8 +7646,8 @@ __export(start_exports, {
|
|
|
7382
7646
|
});
|
|
7383
7647
|
import { spawn, execFileSync as execFileSync2 } from "node:child_process";
|
|
7384
7648
|
import { createRequire } from "node:module";
|
|
7385
|
-
import { existsSync, mkdirSync, readdirSync, statSync, chmodSync } from "node:fs";
|
|
7386
|
-
import { dirname as dirname2, join as
|
|
7649
|
+
import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, statSync, chmodSync } from "node:fs";
|
|
7650
|
+
import { dirname as dirname2, join as join4, resolve as resolvePath } from "node:path";
|
|
7387
7651
|
import { fileURLToPath } from "node:url";
|
|
7388
7652
|
function parseStartArgs(argv) {
|
|
7389
7653
|
const out = { port: null, host: null, db: null, migrate: true };
|
|
@@ -7476,9 +7740,9 @@ async function ensurePrismaClient(schema, dbUrl, ctx) {
|
|
|
7476
7740
|
}
|
|
7477
7741
|
}
|
|
7478
7742
|
function spawnHelperPaths(ptyDir, listDir, exists) {
|
|
7479
|
-
const dirs = [
|
|
7480
|
-
for (const name of listDir(
|
|
7481
|
-
return dirs.map((d) =>
|
|
7743
|
+
const dirs = [join4(ptyDir, "build", "Release")];
|
|
7744
|
+
for (const name of listDir(join4(ptyDir, "prebuilds"))) dirs.push(join4(ptyDir, "prebuilds", name));
|
|
7745
|
+
return dirs.map((d) => join4(d, "spawn-helper")).filter(exists);
|
|
7482
7746
|
}
|
|
7483
7747
|
function ensureSpawnHelpersExecutable(paths2, ops) {
|
|
7484
7748
|
const fixed = [];
|
|
@@ -7502,11 +7766,11 @@ function repairSpawnHelper(ctx) {
|
|
|
7502
7766
|
}
|
|
7503
7767
|
const paths2 = spawnHelperPaths(ptyDir, (d) => {
|
|
7504
7768
|
try {
|
|
7505
|
-
return
|
|
7769
|
+
return readdirSync2(d);
|
|
7506
7770
|
} catch {
|
|
7507
7771
|
return [];
|
|
7508
7772
|
}
|
|
7509
|
-
},
|
|
7773
|
+
}, existsSync2);
|
|
7510
7774
|
const fixed = ensureSpawnHelpersExecutable(paths2, {
|
|
7511
7775
|
mode: (p) => statSync(p).mode,
|
|
7512
7776
|
chmod: (p, m) => chmodSync(p, m)
|
|
@@ -7558,7 +7822,7 @@ async function start(argv, ctx) {
|
|
|
7558
7822
|
let layout;
|
|
7559
7823
|
let dbUrl;
|
|
7560
7824
|
try {
|
|
7561
|
-
layout = resolveLayout(distDir(),
|
|
7825
|
+
layout = resolveLayout(distDir(), existsSync2);
|
|
7562
7826
|
dbUrl = opts.db ? `file:${resolvePath(opts.db)}` : resolveDbUrl(ctx.env, dirname2(layout.schema));
|
|
7563
7827
|
} catch (e) {
|
|
7564
7828
|
ctx.stderr(`${e.message}
|
|
@@ -7571,7 +7835,7 @@ async function start(argv, ctx) {
|
|
|
7571
7835
|
const home = resolveHome(ctx.env);
|
|
7572
7836
|
mkdirSync(home, { recursive: true });
|
|
7573
7837
|
mkdirSync(dirname2(dbFilePath(dbUrl)), { recursive: true });
|
|
7574
|
-
if (!
|
|
7838
|
+
if (!existsSync2(layout.server)) {
|
|
7575
7839
|
ctx.stderr(`hanoman: bundle server tak ada di ${layout.server} \u2014 jalankan \`pnpm build\` dulu
|
|
7576
7840
|
`);
|
|
7577
7841
|
return 1;
|
|
@@ -7655,7 +7919,7 @@ __export(doctor_exports, {
|
|
|
7655
7919
|
doctorReport: () => doctorReport
|
|
7656
7920
|
});
|
|
7657
7921
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
7658
|
-
import { accessSync, constants, existsSync as
|
|
7922
|
+
import { accessSync, constants, existsSync as existsSync3 } from "node:fs";
|
|
7659
7923
|
import { dirname as dirname3 } from "node:path";
|
|
7660
7924
|
function doctorReport(p) {
|
|
7661
7925
|
const major = Number(/^v?(\d+)/.exec(p.node)?.[1] ?? 0);
|
|
@@ -7675,6 +7939,15 @@ function doctorReport(p) {
|
|
|
7675
7939
|
{ mark: p.web ? "\u2713" : "!", text: p.web ? "aset dashboard ada" : "aset dashboard tak ada \u2014 API jalan, dashboard tidak", fatal: false },
|
|
7676
7940
|
{ mark: "\xB7", text: `db ${p.db}`, fatal: false }
|
|
7677
7941
|
];
|
|
7942
|
+
for (const m of p.methods) {
|
|
7943
|
+
const agent = m.agent === "codex" ? "Codex CLI" : "Claude Code";
|
|
7944
|
+
rows.push({
|
|
7945
|
+
mark: m.ready ? "\u2713" : "!",
|
|
7946
|
+
text: m.ready ? `metode ${m.method} \xB7 ${agent} \u2014 siap` : `metode ${m.method} \xB7 ${agent} \u2014 belum siap: ` + [...m.missingPackages, ...m.missingSkills].join(", ") + m.install.map((c) => `
|
|
7947
|
+
${c}`).join(""),
|
|
7948
|
+
fatal: false
|
|
7949
|
+
});
|
|
7950
|
+
}
|
|
7678
7951
|
if (!p.claude && !p.codex) {
|
|
7679
7952
|
rows.push({ mark: "\u2717", text: "tak ada CLI agen (claude ATAU codex wajib ada)", fatal: true });
|
|
7680
7953
|
}
|
|
@@ -7691,7 +7964,7 @@ async function doctor(_argv, ctx) {
|
|
|
7691
7964
|
let layout;
|
|
7692
7965
|
let db;
|
|
7693
7966
|
try {
|
|
7694
|
-
layout = resolveLayout(distDir(),
|
|
7967
|
+
layout = resolveLayout(distDir(), existsSync3);
|
|
7695
7968
|
db = dbFilePath(resolveDbUrl(ctx.env, dirname3(layout.schema)));
|
|
7696
7969
|
} catch (e) {
|
|
7697
7970
|
ctx.stderr(`${e.message}
|
|
@@ -7701,20 +7974,28 @@ async function doctor(_argv, ctx) {
|
|
|
7701
7974
|
const home = resolveHome(ctx.env);
|
|
7702
7975
|
let homeWritable = false;
|
|
7703
7976
|
try {
|
|
7704
|
-
accessSync(
|
|
7977
|
+
accessSync(existsSync3(home) ? home : dirname3(home), constants.W_OK);
|
|
7705
7978
|
homeWritable = true;
|
|
7706
7979
|
} catch {
|
|
7707
7980
|
}
|
|
7981
|
+
const claude = version(ctx.env.HANOMAN_CLAUDE_BIN ?? "claude", ["--version"]);
|
|
7982
|
+
const codex = version(ctx.env.HANOMAN_CODEX_BIN ?? "codex", ["--version"]);
|
|
7983
|
+
const method = METHODS[DEFAULT_METHOD];
|
|
7984
|
+
const methods = zAgent.options.filter((a) => (a === "codex" ? codex : claude) !== null).map((a) => {
|
|
7985
|
+
const s2 = scanAgentSkills(a, ctx.env);
|
|
7986
|
+
return methodStatus(method, a, { skills: s2.skills.map((k) => k.id), packages: s2.packages });
|
|
7987
|
+
});
|
|
7708
7988
|
const r = doctorReport({
|
|
7709
7989
|
node: process.version,
|
|
7710
7990
|
git: version("git", ["--version"]),
|
|
7711
7991
|
tmux: version("tmux", ["-V"]),
|
|
7712
|
-
claude
|
|
7713
|
-
codex
|
|
7992
|
+
claude,
|
|
7993
|
+
codex,
|
|
7714
7994
|
gh: version(ctx.env.HANOMAN_GH_BIN ?? "gh", ["--version"]),
|
|
7715
7995
|
homeWritable,
|
|
7716
7996
|
web: layout.web !== null,
|
|
7717
|
-
db
|
|
7997
|
+
db,
|
|
7998
|
+
methods
|
|
7718
7999
|
});
|
|
7719
8000
|
ctx.stdout(`hanoman doctor
|
|
7720
8001
|
${r.lines.join("\n")}
|
|
@@ -7730,6 +8011,7 @@ var init_doctor = __esm({
|
|
|
7730
8011
|
"src/commands/doctor.ts"() {
|
|
7731
8012
|
"use strict";
|
|
7732
8013
|
init_src2();
|
|
8014
|
+
init_src();
|
|
7733
8015
|
init_layout();
|
|
7734
8016
|
init_start();
|
|
7735
8017
|
}
|
|
@@ -28519,9 +28801,9 @@ var mcp_exports = {};
|
|
|
28519
28801
|
__export(mcp_exports, {
|
|
28520
28802
|
default: () => mcp
|
|
28521
28803
|
});
|
|
28522
|
-
import { readFileSync } from "node:fs";
|
|
28523
|
-
import { homedir as
|
|
28524
|
-
import { join as
|
|
28804
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
28805
|
+
import { homedir as homedir3 } from "node:os";
|
|
28806
|
+
import { join as join5 } from "node:path";
|
|
28525
28807
|
async function mcp(argv, ctx) {
|
|
28526
28808
|
const cfg = resolveMcpConfig(argv, ctx.env, () => tokenFile(ctx.env));
|
|
28527
28809
|
const say = (s2) => ctx.stderr(redactToken(s2, cfg.token) + "\n");
|
|
@@ -28552,9 +28834,9 @@ var init_mcp2 = __esm({
|
|
|
28552
28834
|
init_server();
|
|
28553
28835
|
init_redact();
|
|
28554
28836
|
tokenFile = (env) => {
|
|
28555
|
-
const home = env.HANOMAN_HOME ??
|
|
28837
|
+
const home = env.HANOMAN_HOME ?? join5(homedir3(), ".hanoman");
|
|
28556
28838
|
try {
|
|
28557
|
-
return
|
|
28839
|
+
return readFileSync2(join5(home, "agent-token"), "utf8");
|
|
28558
28840
|
} catch {
|
|
28559
28841
|
return null;
|
|
28560
28842
|
}
|
|
@@ -28574,7 +28856,7 @@ __export(migrate_pg_exports, {
|
|
|
28574
28856
|
migrationSteps: () => migrationSteps,
|
|
28575
28857
|
parseMigrateArgs: () => parseMigrateArgs
|
|
28576
28858
|
});
|
|
28577
|
-
import { existsSync as
|
|
28859
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
28578
28860
|
import { dirname as dirname4, resolve as resolvePath2 } from "node:path";
|
|
28579
28861
|
function coerceInt8(rows, fields, model) {
|
|
28580
28862
|
const cols = fields.filter((f) => f.dataTypeID === INT8_OID).map((f) => f.name);
|
|
@@ -28642,7 +28924,7 @@ async function migratePg(argv, ctx) {
|
|
|
28642
28924
|
let layout;
|
|
28643
28925
|
let dbUrl;
|
|
28644
28926
|
try {
|
|
28645
|
-
layout = resolveLayout(distDir(),
|
|
28927
|
+
layout = resolveLayout(distDir(), existsSync4);
|
|
28646
28928
|
dbUrl = opts.to ? `file:${resolvePath2(opts.to)}` : resolveDbUrl(ctx.env, dirname4(layout.schema));
|
|
28647
28929
|
} catch (e) {
|
|
28648
28930
|
ctx.stderr(`${e.message}
|
|
@@ -28781,11 +29063,11 @@ var init_migrate_pg = __esm({
|
|
|
28781
29063
|
});
|
|
28782
29064
|
|
|
28783
29065
|
// src/config.ts
|
|
28784
|
-
import { readFileSync as
|
|
28785
|
-
import { join as
|
|
29066
|
+
import { readFileSync as readFileSync3, existsSync as existsSync5 } from "node:fs";
|
|
29067
|
+
import { join as join6 } from "node:path";
|
|
28786
29068
|
function loadConfig(repoRoot) {
|
|
28787
|
-
const p =
|
|
28788
|
-
const raw =
|
|
29069
|
+
const p = join6(repoRoot, "hanoman.config.json");
|
|
29070
|
+
const raw = existsSync5(p) ? JSON.parse(readFileSync3(p, "utf8")) : {};
|
|
28789
29071
|
return zHanomanConfig.parse(raw);
|
|
28790
29072
|
}
|
|
28791
29073
|
var init_config3 = __esm({
|
|
@@ -28797,12 +29079,12 @@ var init_config3 = __esm({
|
|
|
28797
29079
|
|
|
28798
29080
|
// src/repo.ts
|
|
28799
29081
|
import { spawnSync } from "node:child_process";
|
|
28800
|
-
import { join as
|
|
29082
|
+
import { join as join7 } from "node:path";
|
|
28801
29083
|
function resolveRepo(cwd) {
|
|
28802
29084
|
const r = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8" });
|
|
28803
29085
|
const root = r.status === 0 ? r.stdout.trim() : cwd;
|
|
28804
29086
|
const { docsDir } = loadConfig(root);
|
|
28805
|
-
return { root, docsDir, indexPath:
|
|
29087
|
+
return { root, docsDir, indexPath: join7(root, docsDir, "README.md") };
|
|
28806
29088
|
}
|
|
28807
29089
|
var init_repo = __esm({
|
|
28808
29090
|
"src/repo.ts"() {
|
|
@@ -28812,10 +29094,10 @@ var init_repo = __esm({
|
|
|
28812
29094
|
});
|
|
28813
29095
|
|
|
28814
29096
|
// src/docs-model.ts
|
|
28815
|
-
import { readFileSync as
|
|
28816
|
-
import { join as
|
|
29097
|
+
import { readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
29098
|
+
import { join as join8, relative } from "node:path";
|
|
28817
29099
|
function parseIndex(indexPath) {
|
|
28818
|
-
const md =
|
|
29100
|
+
const md = readFileSync4(indexPath, "utf8");
|
|
28819
29101
|
const out = /* @__PURE__ */ new Set();
|
|
28820
29102
|
for (const m of md.matchAll(LINK_RE2)) {
|
|
28821
29103
|
let t = m[1].trim();
|
|
@@ -28828,9 +29110,9 @@ function parseIndex(indexPath) {
|
|
|
28828
29110
|
function walkDocs(docsRoot) {
|
|
28829
29111
|
const out = [];
|
|
28830
29112
|
const walk = (dir) => {
|
|
28831
|
-
for (const name of
|
|
29113
|
+
for (const name of readdirSync3(dir)) {
|
|
28832
29114
|
if (name.startsWith(".")) continue;
|
|
28833
|
-
const abs =
|
|
29115
|
+
const abs = join8(dir, name);
|
|
28834
29116
|
if (statSync2(abs).isDirectory()) walk(abs);
|
|
28835
29117
|
else out.push(relative(docsRoot, abs).split("\\").join("/"));
|
|
28836
29118
|
}
|
|
@@ -28862,17 +29144,17 @@ var init_docs_model = __esm({
|
|
|
28862
29144
|
});
|
|
28863
29145
|
|
|
28864
29146
|
// src/verify.ts
|
|
28865
|
-
import { join as
|
|
28866
|
-
import { existsSync as
|
|
29147
|
+
import { join as join9 } from "node:path";
|
|
29148
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
28867
29149
|
function scanCoverage(cwd) {
|
|
28868
29150
|
const { root, docsDir, indexPath } = resolveRepo(cwd);
|
|
28869
|
-
const docsRoot =
|
|
28870
|
-
if (!
|
|
28871
|
-
if (!
|
|
29151
|
+
const docsRoot = join9(root, docsDir);
|
|
29152
|
+
if (!existsSync6(docsRoot)) return { coverage: 100, cats: [] };
|
|
29153
|
+
if (!existsSync6(indexPath)) throw new Error(`index Source of Truth tidak ada: ${indexPath}`);
|
|
28872
29154
|
const corpus = walkDocs(docsRoot);
|
|
28873
29155
|
const read = (rel) => {
|
|
28874
29156
|
try {
|
|
28875
|
-
return
|
|
29157
|
+
return readFileSync5(join9(docsRoot, rel), "utf8");
|
|
28876
29158
|
} catch {
|
|
28877
29159
|
return null;
|
|
28878
29160
|
}
|
|
@@ -28915,9 +29197,9 @@ var init_docs_scan = __esm({
|
|
|
28915
29197
|
});
|
|
28916
29198
|
|
|
28917
29199
|
// src/index-edit.ts
|
|
28918
|
-
import { readFileSync as
|
|
29200
|
+
import { readFileSync as readFileSync6, writeFileSync } from "node:fs";
|
|
28919
29201
|
function addLink(indexPath, relPath, category) {
|
|
28920
|
-
let md =
|
|
29202
|
+
let md = readFileSync6(indexPath, "utf8");
|
|
28921
29203
|
if (md.includes(`(${relPath})`)) return;
|
|
28922
29204
|
const base = relPath.split("/").pop().replace(/\.md$/, "");
|
|
28923
29205
|
const line = `- [${base}](${relPath})`;
|
|
@@ -28946,23 +29228,23 @@ __export(docs_index_exports, {
|
|
|
28946
29228
|
default: () => docs_index_default
|
|
28947
29229
|
});
|
|
28948
29230
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
28949
|
-
import { join as
|
|
28950
|
-
import { existsSync as
|
|
29231
|
+
import { join as join10 } from "node:path";
|
|
29232
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
28951
29233
|
async function docs_index_default(args, ctx) {
|
|
28952
29234
|
const { values } = parseArgs2({ args, options: { check: { type: "boolean" }, fix: { type: "boolean" } }, allowPositionals: true });
|
|
28953
29235
|
const { root, docsDir, indexPath } = resolveRepo(ctx.cwd);
|
|
28954
|
-
const docsRoot =
|
|
29236
|
+
const docsRoot = join10(root, docsDir);
|
|
28955
29237
|
const corpus = walkDocs(docsRoot);
|
|
28956
29238
|
const read = (rel) => {
|
|
28957
29239
|
try {
|
|
28958
|
-
return
|
|
29240
|
+
return readFileSync7(join10(docsRoot, rel), "utf8");
|
|
28959
29241
|
} catch {
|
|
28960
29242
|
return null;
|
|
28961
29243
|
}
|
|
28962
29244
|
};
|
|
28963
29245
|
const linked = linkedSetFrom(INDEX_NAME, corpus, read);
|
|
28964
29246
|
const unlinked = corpus.filter((f) => f !== INDEX_NAME && !linked.has(f));
|
|
28965
|
-
const dangling = [...parseIndex(indexPath)].filter((p) => !
|
|
29247
|
+
const dangling = [...parseIndex(indexPath)].filter((p) => !existsSync7(join10(docsRoot, p)));
|
|
28966
29248
|
if (values.fix) {
|
|
28967
29249
|
for (const f of unlinked) addLink(indexPath, f, f.split("/")[0]);
|
|
28968
29250
|
ctx.stdout(`linked ${unlinked.length} doc(s)
|
|
@@ -29015,7 +29297,7 @@ var init_docs_link = __esm({
|
|
|
29015
29297
|
});
|
|
29016
29298
|
|
|
29017
29299
|
// src/release/pack.ts
|
|
29018
|
-
import { join as
|
|
29300
|
+
import { join as join11 } from "node:path";
|
|
29019
29301
|
function packageJsonFor(version3, deps) {
|
|
29020
29302
|
return {
|
|
29021
29303
|
name: PKG_NAME,
|
|
@@ -29053,17 +29335,17 @@ function verifyPackedDeps(pkg) {
|
|
|
29053
29335
|
}
|
|
29054
29336
|
function copyPlan(repo) {
|
|
29055
29337
|
return [
|
|
29056
|
-
{ from:
|
|
29057
|
-
{ from:
|
|
29058
|
-
{ from:
|
|
29059
|
-
{ from:
|
|
29060
|
-
{ from:
|
|
29061
|
-
{ from:
|
|
29062
|
-
{ from:
|
|
29338
|
+
{ from: join11(repo, "server/dist/server.js"), to: "dist/server.js" },
|
|
29339
|
+
{ from: join11(repo, "server/dist/build-info.json"), to: "dist/build-info.json" },
|
|
29340
|
+
{ from: join11(repo, "cli/dist/hanoman.js"), to: "dist/cli.js" },
|
|
29341
|
+
{ from: join11(repo, "src/dist"), to: "web", dir: true },
|
|
29342
|
+
{ from: join11(repo, "server/prisma/schema.prisma"), to: "prisma/schema.prisma" },
|
|
29343
|
+
{ from: join11(repo, "server/prisma/migrations"), to: "prisma/migrations", dir: true },
|
|
29344
|
+
{ from: join11(repo, "internal/docs/operations/npm-readme.md"), to: "README.md" },
|
|
29063
29345
|
// SPEC-489 · dibaca runtime oleh pickGuideFile (kandidat `<pkg>/docs/…`). Bukan README:
|
|
29064
29346
|
// README paket adalah npm-readme.md (berhadapan-MANUSIA), ini naskah berhadapan-AGEN.
|
|
29065
|
-
{ from:
|
|
29066
|
-
{ from:
|
|
29347
|
+
{ from: join11(repo, "docs/agent-integration.md"), to: "docs/agent-integration.md" },
|
|
29348
|
+
{ from: join11(repo, "LICENSE"), to: "LICENSE" }
|
|
29067
29349
|
];
|
|
29068
29350
|
}
|
|
29069
29351
|
var PKG_NAME, REPO_URL, RUNTIME_DEPS, REQUIRED_ARTIFACTS, BIN_SHIM;
|
|
@@ -29109,10 +29391,10 @@ var pack_exports = {};
|
|
|
29109
29391
|
__export(pack_exports, {
|
|
29110
29392
|
default: () => pack
|
|
29111
29393
|
});
|
|
29112
|
-
import { cpSync, existsSync as
|
|
29113
|
-
import { dirname as dirname5, join as
|
|
29394
|
+
import { cpSync, existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync8, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
29395
|
+
import { dirname as dirname5, join as join12 } from "node:path";
|
|
29114
29396
|
function depVersions(repo) {
|
|
29115
|
-
const read = (p) => JSON.parse(
|
|
29397
|
+
const read = (p) => JSON.parse(readFileSync8(join12(repo, p), "utf8"));
|
|
29116
29398
|
const server = read("server/package.json"), cli = read("cli/package.json");
|
|
29117
29399
|
const pools = [server.dependencies, server.devDependencies, cli.dependencies, cli.devDependencies];
|
|
29118
29400
|
const out = {};
|
|
@@ -29126,19 +29408,19 @@ function depVersions(repo) {
|
|
|
29126
29408
|
async function pack(argv, ctx) {
|
|
29127
29409
|
let repo;
|
|
29128
29410
|
try {
|
|
29129
|
-
repo = resolveLayout(distDir(),
|
|
29411
|
+
repo = resolveLayout(distDir(), existsSync8).root;
|
|
29130
29412
|
} catch (e) {
|
|
29131
29413
|
ctx.stderr(`${e.message}
|
|
29132
29414
|
`);
|
|
29133
29415
|
return 1;
|
|
29134
29416
|
}
|
|
29135
|
-
if (!
|
|
29417
|
+
if (!existsSync8(join12(repo, "server/prisma/schema.prisma"))) {
|
|
29136
29418
|
ctx.stderr("pack: hanya bisa dijalankan dari checkout repo hanoman\n");
|
|
29137
29419
|
return 1;
|
|
29138
29420
|
}
|
|
29139
29421
|
const outIdx = argv.indexOf("--out");
|
|
29140
|
-
const out = outIdx === -1 ?
|
|
29141
|
-
const version3 = JSON.parse(
|
|
29422
|
+
const out = outIdx === -1 ? join12(repo, "dist-npm") : join12(repo, argv[outIdx + 1] ?? "dist-npm");
|
|
29423
|
+
const version3 = JSON.parse(readFileSync8(join12(repo, "package.json"), "utf8")).version;
|
|
29142
29424
|
if (!version3) {
|
|
29143
29425
|
ctx.stderr("pack: root package.json tanpa field version\n");
|
|
29144
29426
|
return 1;
|
|
@@ -29152,20 +29434,20 @@ async function pack(argv, ctx) {
|
|
|
29152
29434
|
return 1;
|
|
29153
29435
|
}
|
|
29154
29436
|
rmSync(out, { recursive: true, force: true });
|
|
29155
|
-
mkdirSync2(
|
|
29437
|
+
mkdirSync2(join12(out, "bin"), { recursive: true });
|
|
29156
29438
|
for (const item of copyPlan(repo)) {
|
|
29157
|
-
if (!
|
|
29439
|
+
if (!existsSync8(item.from)) {
|
|
29158
29440
|
ctx.stderr(`pack: artefak hilang \u2014 ${item.from} (sudah \`pnpm build\`?)
|
|
29159
29441
|
`);
|
|
29160
29442
|
return 1;
|
|
29161
29443
|
}
|
|
29162
|
-
const dest =
|
|
29444
|
+
const dest = join12(out, item.to);
|
|
29163
29445
|
mkdirSync2(dirname5(dest), { recursive: true });
|
|
29164
29446
|
cpSync(item.from, dest, item.dir ? { recursive: true } : {});
|
|
29165
29447
|
}
|
|
29166
|
-
writeFileSync2(
|
|
29167
|
-
writeFileSync2(
|
|
29168
|
-
const missing = REQUIRED_ARTIFACTS.filter((a) => !
|
|
29448
|
+
writeFileSync2(join12(out, "bin/hanoman.mjs"), BIN_SHIM);
|
|
29449
|
+
writeFileSync2(join12(out, "package.json"), JSON.stringify(packageJsonFor(version3, deps), null, 2) + "\n");
|
|
29450
|
+
const missing = REQUIRED_ARTIFACTS.filter((a) => !existsSync8(join12(out, a)));
|
|
29169
29451
|
if (missing.length) {
|
|
29170
29452
|
ctx.stderr(`pack: artefak wajib hilang: ${missing.join(", ")}
|
|
29171
29453
|
`);
|
|
@@ -29190,13 +29472,13 @@ var verify_packed_exports = {};
|
|
|
29190
29472
|
__export(verify_packed_exports, {
|
|
29191
29473
|
default: () => verifyPacked
|
|
29192
29474
|
});
|
|
29193
|
-
import { readFileSync as
|
|
29194
|
-
import { join as
|
|
29475
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
29476
|
+
import { join as join13 } from "node:path";
|
|
29195
29477
|
function verifyPacked(_argv, ctx) {
|
|
29196
|
-
const path =
|
|
29478
|
+
const path = join13(process.cwd(), "package.json");
|
|
29197
29479
|
let pkg;
|
|
29198
29480
|
try {
|
|
29199
|
-
pkg = JSON.parse(
|
|
29481
|
+
pkg = JSON.parse(readFileSync9(path, "utf8"));
|
|
29200
29482
|
} catch {
|
|
29201
29483
|
ctx.stderr(`verify: tak bisa membaca ${path}
|
|
29202
29484
|
`);
|