hanoman 0.1.19 → 0.1.20

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.19",
3
- "sha": "070dac2",
4
- "builtAt": "2026-08-03T19:06:22.703Z"
2
+ "version": "0.1.20",
3
+ "sha": "76f8304",
4
+ "builtAt": "2026-08-06T02:10:06.880Z"
5
5
  }
package/dist/cli.js CHANGED
@@ -63,6 +63,25 @@ var init_verify_scope = __esm({
63
63
  }
64
64
  });
65
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
+
66
85
  // ../runner/src/goal-spec.ts
67
86
  var init_goal_spec = __esm({
68
87
  "../runner/src/goal-spec.ts"() {
@@ -77,6 +96,7 @@ var init_prompt = __esm({
77
96
  "use strict";
78
97
  init_reverse_standard();
79
98
  init_verify_scope();
99
+ init_code_style();
80
100
  init_goal_spec();
81
101
  ESCALATION_CONTRACT = [
82
102
  "REKOMENDASI ESKALASI (wajib, terbaca mesin). Di bagian akhir dokumen audit, tulis bagian",
@@ -6974,6 +6994,7 @@ var init_custom_agents = __esm({
6974
6994
  "../runner/src/custom-agents.ts"() {
6975
6995
  "use strict";
6976
6996
  init_src();
6997
+ init_code_style();
6977
6998
  }
6978
6999
  });
6979
7000
 
@@ -7056,6 +7077,7 @@ var init_src2 = __esm({
7056
7077
  init_agent_cli();
7057
7078
  init_custom_agents();
7058
7079
  init_verify_scope();
7080
+ init_code_style();
7059
7081
  init_paths();
7060
7082
  init_telegram_operator();
7061
7083
  }
package/dist/server.js CHANGED
@@ -7466,6 +7466,25 @@ var init_verify_scope = __esm({
7466
7466
  }
7467
7467
  });
7468
7468
 
7469
+ // ../runner/src/code-style.ts
7470
+ var CODE_STYLE_CLAUSE;
7471
+ var init_code_style = __esm({
7472
+ "../runner/src/code-style.ts"() {
7473
+ "use strict";
7474
+ CODE_STYLE_CLAUSE = [
7475
+ "Gaya kode \u2014 berlaku setiap kali kamu menulis atau mengubah kode:",
7476
+ "- Tulis kode yang rapi dan mengikuti idiom, penamaan, serta struktur kode di sekitarnya.",
7477
+ " Kodemu harus terbaca seperti kode yang sudah ada di berkas itu, bukan seperti tempelan.",
7478
+ "- Jangan menulis komentar yang cuma mengulang apa yang sudah dinyatakan kode.",
7479
+ "- Komentar hanya untuk hal yang TIDAK terbaca dari kode: alasan/why sebuah keputusan,",
7480
+ " trade-off yang diambil, workaround beserta rujukan SPEC/ADR-nya, atau invariant yang tak",
7481
+ " kelihatan. Komentar semacam itu justru berharga \u2014 jangan ikut dibuang.",
7482
+ "- Jangan menambahkan komentar pembatas seksi, header berhiasan, atau narasi langkah demi langkah.",
7483
+ "- Jangan meninggalkan kode mati atau kode yang dikomentari. Hapus saja; riwayat git yang menyimpannya."
7484
+ ].join("\n");
7485
+ }
7486
+ });
7487
+
7469
7488
  // ../runner/src/goal-spec.ts
7470
7489
  function readGoalPayload(payload) {
7471
7490
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) return null;
@@ -7494,6 +7513,7 @@ Detail: ${JSON.stringify(spec.payload)}` : "";
7494
7513
  auditOnlyInstruction(flow),
7495
7514
  autonomyClause(autonomy),
7496
7515
  scopeClause(flow, verifyScope),
7516
+ codeStyleClause(flow),
7497
7517
  skillInstruction(PIPELINES[flow]),
7498
7518
  `Setelah fase terakhir: commit, lalu \`git push origin HEAD:refs/heads/${branchTo}\`. Worktree ini detached HEAD \u2014 itu memang disengaja.`,
7499
7519
  `Backlog item ${spec.id} \xB7 sumber ${spec.source} \xB7 prioritas ${spec.priority}
@@ -7509,6 +7529,7 @@ Detail: ${JSON.stringify(spec.payload)}` : "";
7509
7529
  `JANGAN mengulang fase awal \u2014 spec & plan sudah ada. Lanjut di fase Execute: baca plan di docs/superpowers/plans/** untuk backlog item ini, periksa task yang sudah \`[x]\` dan selesaikan yang masih \`[ ]\`. Verifikasi nyata sebelum klaim selesai.`,
7510
7530
  autonomyClause(autonomy),
7511
7531
  scopeClause(flow, verifyScope),
7532
+ codeStyleClause(flow),
7512
7533
  skillInstruction(["Execute"]),
7513
7534
  `Setelah selesai: commit, lalu \`git push origin HEAD:refs/heads/${branchTo}\`. Worktree ini detached HEAD \u2014 itu memang disengaja.`,
7514
7535
  `Backlog item ${spec.id} \xB7 sumber ${spec.source} \xB7 prioritas ${spec.priority}
@@ -7527,6 +7548,7 @@ Detail: ${JSON.stringify(spec.payload)}` : "";
7527
7548
  auditDecided ? "" : auditDecisionInstruction(flow),
7528
7549
  autonomyClause(autonomy),
7529
7550
  scopeClause(flow, verifyScope),
7551
+ codeStyleClause(flow),
7530
7552
  skillInstruction(PIPELINES[flow]),
7531
7553
  `Setelah fase terakhir: commit, lalu \`git push origin HEAD:refs/heads/${branchTo}\`. Worktree ini detached HEAD \u2014 itu memang disengaja.`,
7532
7554
  `Backlog item ${spec.id} \xB7 sumber ${spec.source} \xB7 prioritas ${spec.priority}
@@ -7549,6 +7571,7 @@ function startGoalPrompt(spec, branchTo, opts = {}) {
7549
7571
  "Fase Verifikasi bukan formalitas: jalankan perintah yang membuktikan goal-nya tercapai (test/typecheck/benchmark/perintah yang relevan) dan baca outputnya. Klaim tanpa output bukan bukti.",
7550
7572
  autonomyClause(opts.autonomy),
7551
7573
  scopeClause("goal", opts.verifyScope),
7574
+ codeStyleClause("goal"),
7552
7575
  skillInstruction(PIPELINES.goal),
7553
7576
  `Setelah fase terakhir: commit, lalu \`git push origin HEAD:refs/heads/${branchTo}\`. Worktree ini detached HEAD \u2014 itu memang disengaja.`,
7554
7577
  `Backlog item ${spec.id} \xB7 sumber ${spec.source} \xB7 prioritas ${spec.priority}
@@ -7621,12 +7644,13 @@ Stack: ${project.stack || "\u2014"}`,
7621
7644
  ${REVERSE_STANDARD}`
7622
7645
  ].filter(Boolean).join("\n\n");
7623
7646
  }
7624
- var PIPELINES, AUTONOMY_CLAUSE, AUTONOMY_CLAUSE_FULL, autonomyClause, phaseInstruction, PHASE_SKILLS, skillInstruction, auditDecisionInstruction, ESCALATION_CONTRACT, auditOnlyInstruction, auditContinuationInstruction, writesCode, scopeClause, resumeClause, RESUMED_WORKTREE_NOTE, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
7647
+ var PIPELINES, AUTONOMY_CLAUSE, AUTONOMY_CLAUSE_FULL, autonomyClause, phaseInstruction, PHASE_SKILLS, skillInstruction, auditDecisionInstruction, ESCALATION_CONTRACT, auditOnlyInstruction, auditContinuationInstruction, writesCode, scopeClause, codeStyleClause, resumeClause, RESUMED_WORKTREE_NOTE, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
7625
7648
  var init_prompt = __esm({
7626
7649
  "../runner/src/prompt.ts"() {
7627
7650
  "use strict";
7628
7651
  init_reverse_standard();
7629
7652
  init_verify_scope();
7653
+ init_code_style();
7630
7654
  init_goal_spec();
7631
7655
  PIPELINES = {
7632
7656
  feature: ["Brainstorm", "Objective", "Spec", "Plan", "Execute"],
@@ -7706,6 +7730,7 @@ ${lines2.join("\n")}` : "";
7706
7730
  };
7707
7731
  writesCode = (flow) => PIPELINES[flow].includes("Execute") || PIPELINES[flow].includes("Goal");
7708
7732
  scopeClause = (flow, scope) => scope && writesCode(flow) ? verifyScopeClause(scope) : "";
7733
+ codeStyleClause = (flow) => writesCode(flow) ? CODE_STYLE_CLAUSE : "";
7709
7734
  resumeClause = (r, branchTo, hasPlan = true) => {
7710
7735
  const fase = r.recorded.length ? `Fase yang SUDAH tercatat di $HANOMAN_PHASE_FILE: ${r.recorded.join(" \xB7 ")}. JANGAN mengulang fase itu dan JANGAN menulis ulang barisnya.` : "Belum ada fase yang tercatat di $HANOMAN_PHASE_FILE \u2014 worktree ini sendiri yang jadi alasan melanjutkan.";
7711
7736
  const lanjut = r.next ? `Lanjutkan dari fase: ${r.next}.` : hasPlan ? "Semua fase sudah tercatat. Periksa apakah plan di `docs/superpowers/plans/**` masih menyisakan task `- [ ]` dan selesaikan sisanya; bila sudah bersih, tinggal commit & push." : "Semua fase sudah tercatat. Buktikan sekali lagi goal-nya benar-benar tercapai, lalu commit & push.";
@@ -8034,10 +8059,14 @@ var init_agent_cli = __esm({
8034
8059
  function agentPromptOf(def2, roster) {
8035
8060
  const can = liveMentions(def2, roster);
8036
8061
  if (can.length === 0) {
8037
- return `${def2.instructions}
8038
-
8039
- ---
8040
- Kamu TIDAK boleh mendelegasikan ke agen lain. Selesaikan sendiri lalu laporkan hasilnya.`;
8062
+ return [
8063
+ def2.instructions,
8064
+ "",
8065
+ "---",
8066
+ "Kamu TIDAK boleh mendelegasikan ke agen lain. Selesaikan sendiri lalu laporkan hasilnya.",
8067
+ "",
8068
+ CODE_STYLE_CLAUSE
8069
+ ].join("\n");
8041
8070
  }
8042
8071
  const list2 = can.map((m) => `@${m}`).join(", ");
8043
8072
  return [
@@ -8046,7 +8075,9 @@ Kamu TIDAK boleh mendelegasikan ke agen lain. Selesaikan sendiri lalu laporkan h
8046
8075
  "---",
8047
8076
  `Kamu boleh mendelegasikan HANYA ke: ${list2}. Panggil lewat ${MENTION_TOOL} dengan nama agennya.`,
8048
8077
  `Anggaran rantai delegasi seluruh sesi ini ${MENTION_MAX_HOPS} hop. Bila kamu sudah berada di hop ke-${MENTION_MAX_HOPS}, JANGAN mendelegasikan lagi \u2014 selesaikan sendiri lalu laporkan.`,
8049
- "Sebutkan hop keberapa kamu berada saat mendelegasikan, dan jangan pernah memanggil agen yang sudah ada di rantai yang membawamu ke sini."
8078
+ "Sebutkan hop keberapa kamu berada saat mendelegasikan, dan jangan pernah memanggil agen yang sudah ada di rantai yang membawamu ke sini.",
8079
+ "",
8080
+ CODE_STYLE_CLAUSE
8050
8081
  ].join("\n");
8051
8082
  }
8052
8083
  function renderAgentsJson(defs) {
@@ -8091,6 +8122,7 @@ var init_custom_agents = __esm({
8091
8122
  "../runner/src/custom-agents.ts"() {
8092
8123
  "use strict";
8093
8124
  init_src();
8125
+ init_code_style();
8094
8126
  liveMentions = (def2, roster) => {
8095
8127
  const names = new Set(roster.map((r) => r.name));
8096
8128
  return def2.mentions.filter((m) => names.has(m) && m !== def2.name);
@@ -8231,6 +8263,7 @@ var init_src2 = __esm({
8231
8263
  init_agent_cli();
8232
8264
  init_custom_agents();
8233
8265
  init_verify_scope();
8266
+ init_code_style();
8234
8267
  init_paths();
8235
8268
  init_telegram_operator();
8236
8269
  }
@@ -18925,6 +18958,7 @@ async function projects_default(app2) {
18925
18958
 
18926
18959
  // src/routes/specs.ts
18927
18960
  init_src();
18961
+ init_src2();
18928
18962
  import { existsSync as existsSync4 } from "node:fs";
18929
18963
 
18930
18964
  // src/services/integrate.ts
@@ -22295,6 +22329,9 @@ ${item.context}` : item.context;
22295
22329
  `hanoman \xB7 selesaikan konflik ${r.op} branch \`${sourceBranch(spec.id)}\` ${r.op === "merge" ? "ke" : "di atas"} \`${r.target}\`.`,
22296
22330
  `Kamu berada di worktree yang tertinggal di tengah operasi ${r.op} dengan konflik. Resolve konflik pada file bertanda, jaga kedua sisi perubahan sesuai maksudnya.`,
22297
22331
  r.finalize,
22332
+ // SPEC-543 · ADR-0108 · menyelesaikan konflik selalu berarti menyunting kode, dan prompt ini
22333
+ // dirakit inline di route — gerbang `writesCode` di runner/src/prompt.ts tak menjangkaunya.
22334
+ CODE_STYLE_CLAUSE,
22298
22335
  `Backlog item ${spec.id} \u2014 ${spec.title}.`
22299
22336
  ].join("\n\n");
22300
22337
  const s2 = createSession(spec.projectId, r.worktree, {
@@ -22543,6 +22580,7 @@ async function docs_default(app2) {
22543
22580
  }
22544
22581
 
22545
22582
  // src/routes/ide.ts
22583
+ init_src2();
22546
22584
  import { basename } from "node:path";
22547
22585
  import { spawn as spawn2 } from "node:child_process";
22548
22586
 
@@ -23501,6 +23539,8 @@ async function finishGraphOp(reply, id, repoDir, r, verb) {
23501
23539
  `hanoman \xB7 selesaikan konflik ${verb} \`${r.source}\` \u2192 \`${r.target}\`.`,
23502
23540
  `Kamu berada di worktree yang tertinggal di tengah ${verb} dengan konflik. Resolve konflik pada file bertanda, jaga kedua sisi perubahan sesuai maksudnya.`,
23503
23541
  r.finalize,
23542
+ // SPEC-543 · ADR-0108 · cermin pintu konflik backlog di routes/specs.ts.
23543
+ CODE_STYLE_CLAUSE,
23504
23544
  `${verb} via git graph project ${id}.`
23505
23545
  ].join("\n\n");
23506
23546
  const s2 = createSession(id, r.worktree, { id: basename(r.worktree), model, effort, agent, prompt });
@@ -23963,6 +24003,8 @@ async function terminal_default(app2) {
23963
24003
  `hanoman \xB7 selesaikan konflik ${r.op} branch \`${s2.branch}\` ${r.op === "merge" ? "ke" : "di atas"} \`${r.target}\`.`,
23964
24004
  `Kamu berada di worktree yang tertinggal di tengah operasi ${r.op} dengan konflik. Resolve konflik pada file bertanda, jaga kedua sisi perubahan sesuai maksudnya.`,
23965
24005
  r.finalize,
24006
+ // SPEC-543 · ADR-0108 · cermin pintu konflik backlog di routes/specs.ts.
24007
+ CODE_STYLE_CLAUSE,
23966
24008
  `Sesi PRD ${s2.id}.`
23967
24009
  ].join("\n\n");
23968
24010
  const cs = createSession(s2.projectId, r.worktree, {
@@ -26342,6 +26384,7 @@ init_pty();
26342
26384
 
26343
26385
  // src/services/lead/prompt.ts
26344
26386
  init_src();
26387
+ init_src2();
26345
26388
  var bullet2 = (s2) => `- ${s2}`;
26346
26389
  function leadPrompt(q, c) {
26347
26390
  const lines2 = [];
@@ -26405,6 +26448,8 @@ function leadPrompt(q, c) {
26405
26448
  lines2.push(` ${LEAD_ACTIONS.join(" \xB7 ")}`);
26406
26449
  lines2.push(" Deploy, perintah/konsol VPS, data produksi, dan penghapusan apa pun (project, backlog, branch, worktree, notifikasi, jejak) TERKUNCI dan tidak akan pernah dijalankan.");
26407
26450
  lines2.push("");
26451
+ lines2.push(CODE_STYLE_CLAUSE);
26452
+ lines2.push("");
26408
26453
  lines2.push("## Sepanjang apa (WAJIB)");
26409
26454
  lines2.push(`Peminta jawabanmu adalah MESIN yang sedang menunggu, bukan pembaca laporan. \`decision\` paling banyak ${LEAD_DECISION_MAX} karakter (satu kalimat) dan \`reason\` paling banyak ${LEAD_REASON_MAX} karakter (dua-tiga kalimat). Yang lebih panjang dipangkas server sebelum sampai ke peminta.`);
26410
26455
  lines2.push("JANGAN menuliskan: ringkasan ulang konteks yang sudah kamu terima di atas, latar belakang atau sejarah masalahnya, daftar alternatif yang tak diminta, maupun rencana kerja bertahap. Langsung putusannya dan alasannya.");
@@ -28206,6 +28251,7 @@ async function changelogAgentDefaults() {
28206
28251
  }
28207
28252
 
28208
28253
  // src/services/changelog/render.ts
28254
+ init_src2();
28209
28255
  var MODE_LABEL = {
28210
28256
  backlog: "backlog yang selesai dalam rentang tanggal",
28211
28257
  commit: "riwayat perubahan repo dalam rentang yang dipilih",
@@ -28255,6 +28301,10 @@ function changelogPrompt(input, budgetMs) {
28255
28301
  "- Gabungkan bahan yang bicara hal yang sama jadi satu butir. 3\u201310 butir; kurangi bila memang sedikit.",
28256
28302
  "- Jangan mengarang perubahan yang tak ada di bahan.",
28257
28303
  "",
28304
+ // SPEC-543 · ADR-0108 · dipasang di SEMUA prompt agen, bukan hanya yang menulis kode; gerbang
28305
+ // di baris pertama klausa yang membuatnya diam untuk narator ini.
28306
+ CODE_STYLE_CLAUSE,
28307
+ "",
28258
28308
  "Bentuk keluaran \u2014 HANYA markdown ini, tanpa kalimat pembuka atau penutup di luarnya,",
28259
28309
  "tanpa blok kode:",
28260
28310
  "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {