hanoman 0.1.44 → 0.1.45

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.44",
3
- "sha": "0b74c39",
4
- "builtAt": "2026-08-17T09:48:14.366Z"
2
+ "version": "0.1.45",
3
+ "sha": "8badf76",
4
+ "builtAt": "2026-08-18T01:35:38.039Z"
5
5
  }
package/dist/cli.js CHANGED
@@ -4129,7 +4129,7 @@ var init_enums = __esm({
4129
4129
  "use strict";
4130
4130
  init_zod();
4131
4131
  zStage = external_exports.enum(["brainstorming", "objective", "spec-ready", "planned", "executing", "done"]);
4132
- zSpecSource = external_exports.enum(["brief", "qa", "audit", "help", "goal"]);
4132
+ zSpecSource = external_exports.enum(["brief", "qa", "audit", "help", "goal", "no_effort"]);
4133
4133
  zDocStatus = external_exports.enum(["ok", "drift", "broken"]);
4134
4134
  zPriority = external_exports.enum(["tinggi", "sedang", "rendah"]);
4135
4135
  zProjectKind = external_exports.enum(["from-scratch", "existing"]);
@@ -4144,7 +4144,7 @@ var init_enums = __esm({
4144
4144
 
4145
4145
  // ../shared/src/spec-source.ts
4146
4146
  function payloadShapeFor(source) {
4147
- return source === "qa" ? "qa" : source === "goal" ? "goal" : "brief";
4147
+ return source === "qa" ? "qa" : GOAL_SHAPED_SOURCES.has(source) ? "goal" : "brief";
4148
4148
  }
4149
4149
  function shapeOfPayload(payload) {
4150
4150
  const p = payload ?? {};
@@ -4153,10 +4153,12 @@ function shapeOfPayload(payload) {
4153
4153
  function payloadMatchesSource(source, payload) {
4154
4154
  return shapeOfPayload(payload) === payloadShapeFor(source);
4155
4155
  }
4156
+ var GOAL_SHAPED_SOURCES;
4156
4157
  var init_spec_source = __esm({
4157
4158
  "../shared/src/spec-source.ts"() {
4158
4159
  "use strict";
4159
4160
  init_enums();
4161
+ GOAL_SHAPED_SOURCES = /* @__PURE__ */ new Set(["goal", "no_effort"]);
4160
4162
  }
4161
4163
  });
4162
4164
 
@@ -4450,6 +4452,10 @@ var init_entities = __esm({
4450
4452
  expected: external_exports.string(),
4451
4453
  actual: external_exports.string(),
4452
4454
  env: external_exports.string(),
4455
+ // SPEC-826 · bentuk ketiga yang ikut punya batasan pengerjaan. `.default("")` bukan gaya:
4456
+ // payload qa yang SUDAH tersimpan tak punya field ini, dan `z.string()` polos membuat setiap
4457
+ // baris lama gagal validasi begitu ia lewat zSpec/zCreateSpec/zPatchSpec/zChangeSpecSource.
4458
+ constraints: external_exports.string().default(""),
4453
4459
  fromAudit: external_exports.string().optional()
4454
4460
  });
4455
4461
  zGoalPayload = external_exports.object({
@@ -5288,7 +5294,7 @@ var init_dto = __esm({
5288
5294
  capacity: external_exports.number()
5289
5295
  }).default({ inFlight: 0, queued: 0, capacity: 1 })
5290
5296
  });
5291
- zFlow = external_exports.enum(["feature", "qa", "scaffold", "reverse", "prd", "audit", "breakdown", "goal"]);
5297
+ zFlow = external_exports.enum(["feature", "qa", "scaffold", "reverse", "prd", "audit", "breakdown", "goal", "no_effort"]);
5292
5298
  zPrdBrief = external_exports.object({
5293
5299
  title: external_exports.string().min(1),
5294
5300
  context: external_exports.string(),
@@ -6548,12 +6554,13 @@ var init_mcp_schema = __esm({
6548
6554
  expected: str("Yang seharusnya terjadi."),
6549
6555
  actual: str("Yang sebenarnya terjadi. Dari sinilah `objective` backlog diturunkan server."),
6550
6556
  env: str("Lingkungan tempat temuan muncul: versi, browser, OS, instance."),
6557
+ constraints: str("Batasan yang mengikat pengerjaan: yang tak boleh berubah, yang wajib dipertahankan. Boleh string kosong \u2014 SENGAJA tak wajib (SPEC-826)."),
6551
6558
  fromAudit: str("Opsional. Id backlog audit asal (mis. `SPEC-371`).")
6552
6559
  },
6553
6560
  required: ["severity", "steps", "expected", "actual", "env"]
6554
6561
  });
6555
6562
  GOAL_PAYLOAD = obj({
6556
- description: "Bentuk payload untuk source `goal`. Sesi goal mengejar satu tujuan tanpa fase perencanaan (ADR-0089).",
6563
+ description: "Bentuk payload untuk source `goal` dan `no_effort`. Sesi goal mengejar satu tujuan tanpa fase perencanaan (ADR-0089); sesi no_effort mengerjakan satu task remeh dalam SATU fase lalu berhenti (ADR-0123).",
6557
6564
  properties: {
6558
6565
  goal: str("Satu tujuan yang dikejar sesi. Dari sinilah `objective` backlog diturunkan server."),
6559
6566
  done: str("Bukti berhenti yang dituntut. Kosong berarti goal itu sendiri buktinya."),
@@ -6563,12 +6570,12 @@ var init_mcp_schema = __esm({
6563
6570
  required: ["goal", "done", "constraints", "priority"]
6564
6571
  });
6565
6572
  SPEC_PAYLOAD_ONEOF = {
6566
- description: "Isi backlog. BENTUKNYA DITENTUKAN `source`: `qa` \u2192 {severity, steps, expected, actual, env}; `goal` \u2192 {goal, done, constraints, priority}; `brief`/`audit`/`help` \u2192 {context, outcome, constraints, priority}. Bentuk yang tak cocok ditolak sebelum dikirim.",
6573
+ description: "Isi backlog. BENTUKNYA DITENTUKAN `source`: `qa` \u2192 {severity, steps, expected, actual, env, constraints}; `goal`/`no_effort` \u2192 {goal, done, constraints, priority}; `brief`/`audit`/`help` \u2192 {context, outcome, constraints, priority}. `constraints` qa opsional (default string kosong); bentuk yang tak cocok ditolak sebelum dikirim.",
6567
6574
  oneOf: [BRIEF_PAYLOAD, QA_PAYLOAD, GOAL_PAYLOAD]
6568
6575
  };
6569
6576
  SOURCE_PAYLOAD_ALLOF = [
6570
6577
  { if: { properties: { source: { const: "qa" } }, required: ["source"] }, then: { properties: { payload: QA_PAYLOAD } } },
6571
- { if: { properties: { source: { const: "goal" } }, required: ["source"] }, then: { properties: { payload: GOAL_PAYLOAD } } },
6578
+ { if: { properties: { source: { enum: ["goal", "no_effort"] } }, required: ["source"] }, then: { properties: { payload: GOAL_PAYLOAD } } },
6572
6579
  { if: { properties: { source: { enum: ["brief", "audit", "help"] } }, required: ["source"] }, then: { properties: { payload: BRIEF_PAYLOAD } } }
6573
6580
  ];
6574
6581
  PAGE_PARAMS = {
package/dist/server.js CHANGED
@@ -4151,7 +4151,7 @@ var init_enums = __esm({
4151
4151
  "use strict";
4152
4152
  init_zod();
4153
4153
  zStage = external_exports.enum(["brainstorming", "objective", "spec-ready", "planned", "executing", "done"]);
4154
- zSpecSource = external_exports.enum(["brief", "qa", "audit", "help", "goal"]);
4154
+ zSpecSource = external_exports.enum(["brief", "qa", "audit", "help", "goal", "no_effort"]);
4155
4155
  zDocStatus = external_exports.enum(["ok", "drift", "broken"]);
4156
4156
  zPriority = external_exports.enum(["tinggi", "sedang", "rendah"]);
4157
4157
  zProjectKind = external_exports.enum(["from-scratch", "existing"]);
@@ -4166,7 +4166,7 @@ var init_enums = __esm({
4166
4166
 
4167
4167
  // ../shared/src/spec-source.ts
4168
4168
  function payloadShapeFor(source) {
4169
- return source === "qa" ? "qa" : source === "goal" ? "goal" : "brief";
4169
+ return source === "qa" ? "qa" : GOAL_SHAPED_SOURCES.has(source) ? "goal" : "brief";
4170
4170
  }
4171
4171
  function shapeOfPayload(payload) {
4172
4172
  const p = payload ?? {};
@@ -4203,15 +4203,17 @@ function convertPayload(to, payload) {
4203
4203
  expected: str3("outcome"),
4204
4204
  actual: str3("context"),
4205
4205
  env: "",
4206
+ constraints: str3("constraints"),
4206
4207
  ...fromAudit ? { fromAudit } : {}
4207
- }, nonEmpty(["constraints"]));
4208
+ }, []);
4208
4209
  return done({
4209
4210
  severity: severityFromPriority(prio()),
4210
4211
  steps: "",
4211
4212
  expected: str3("goal"),
4212
4213
  actual: "",
4213
- env: ""
4214
- }, nonEmpty(["done", "constraints"]));
4214
+ env: "",
4215
+ constraints: str3("constraints")
4216
+ }, nonEmpty(["done"]));
4215
4217
  }
4216
4218
  if (toShape === "goal") {
4217
4219
  if (fromShape === "brief") {
@@ -4224,7 +4226,7 @@ function convertPayload(to, payload) {
4224
4226
  return done({
4225
4227
  goal: str3("expected"),
4226
4228
  done: "",
4227
- constraints: "",
4229
+ constraints: str3("constraints"),
4228
4230
  priority: priorityFromSeverity(p.severity)
4229
4231
  }, nonEmpty(["steps", "actual", "env", "fromAudit"]));
4230
4232
  }
@@ -4232,7 +4234,7 @@ function convertPayload(to, payload) {
4232
4234
  return done({
4233
4235
  context: str3("actual"),
4234
4236
  outcome: str3("expected"),
4235
- constraints: "",
4237
+ constraints: str3("constraints"),
4236
4238
  priority: priorityFromSeverity(p.severity),
4237
4239
  ...fromAudit ? { fromAudit } : {}
4238
4240
  }, nonEmpty(["steps", "env"]));
@@ -4243,11 +4245,12 @@ function convertPayload(to, payload) {
4243
4245
  priority: prio()
4244
4246
  }, nonEmpty(["done"]));
4245
4247
  }
4246
- var SHAPE_REQUIRED;
4248
+ var GOAL_SHAPED_SOURCES, SHAPE_REQUIRED;
4247
4249
  var init_spec_source = __esm({
4248
4250
  "../shared/src/spec-source.ts"() {
4249
4251
  "use strict";
4250
4252
  init_enums();
4253
+ GOAL_SHAPED_SOURCES = /* @__PURE__ */ new Set(["goal", "no_effort"]);
4251
4254
  SHAPE_REQUIRED = {
4252
4255
  brief: ["context", "outcome"],
4253
4256
  qa: ["steps", "expected", "actual", "env"],
@@ -4596,6 +4599,10 @@ var init_entities = __esm({
4596
4599
  expected: external_exports.string(),
4597
4600
  actual: external_exports.string(),
4598
4601
  env: external_exports.string(),
4602
+ // SPEC-826 · bentuk ketiga yang ikut punya batasan pengerjaan. `.default("")` bukan gaya:
4603
+ // payload qa yang SUDAH tersimpan tak punya field ini, dan `z.string()` polos membuat setiap
4604
+ // baris lama gagal validasi begitu ia lewat zSpec/zCreateSpec/zPatchSpec/zChangeSpecSource.
4605
+ constraints: external_exports.string().default(""),
4599
4606
  fromAudit: external_exports.string().optional()
4600
4607
  });
4601
4608
  zGoalPayload = external_exports.object({
@@ -5456,9 +5463,9 @@ var init_cron_expr = __esm({
5456
5463
 
5457
5464
  // ../shared/src/dto.ts
5458
5465
  function flowForSource(source) {
5459
- return source === "qa" ? "qa" : source === "audit" ? "audit" : source === "goal" ? "goal" : "feature";
5466
+ return source === "qa" ? "qa" : source === "audit" ? "audit" : source === "goal" ? "goal" : source === "no_effort" ? "no_effort" : "feature";
5460
5467
  }
5461
- var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zSetup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
5468
+ var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, isGoalShapedFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zSetup, zChangePassword, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, UPDATE_RESTART_EXIT, zUpdateApplyBody, zTicketView, zTicketAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
5462
5469
  var init_dto = __esm({
5463
5470
  "../shared/src/dto.ts"() {
5464
5471
  "use strict";
@@ -5730,7 +5737,8 @@ var init_dto = __esm({
5730
5737
  capacity: external_exports.number()
5731
5738
  }).default({ inFlight: 0, queued: 0, capacity: 1 })
5732
5739
  });
5733
- zFlow = external_exports.enum(["feature", "qa", "scaffold", "reverse", "prd", "audit", "breakdown", "goal"]);
5740
+ zFlow = external_exports.enum(["feature", "qa", "scaffold", "reverse", "prd", "audit", "breakdown", "goal", "no_effort"]);
5741
+ isGoalShapedFlow = (flow) => flow === "goal" || flow === "no_effort";
5734
5742
  zPrdBrief = external_exports.object({
5735
5743
  title: external_exports.string().min(1),
5736
5744
  context: external_exports.string(),
@@ -7147,12 +7155,13 @@ var init_mcp_schema = __esm({
7147
7155
  expected: str("Yang seharusnya terjadi."),
7148
7156
  actual: str("Yang sebenarnya terjadi. Dari sinilah `objective` backlog diturunkan server."),
7149
7157
  env: str("Lingkungan tempat temuan muncul: versi, browser, OS, instance."),
7158
+ constraints: str("Batasan yang mengikat pengerjaan: yang tak boleh berubah, yang wajib dipertahankan. Boleh string kosong \u2014 SENGAJA tak wajib (SPEC-826)."),
7150
7159
  fromAudit: str("Opsional. Id backlog audit asal (mis. `SPEC-371`).")
7151
7160
  },
7152
7161
  required: ["severity", "steps", "expected", "actual", "env"]
7153
7162
  });
7154
7163
  GOAL_PAYLOAD = obj({
7155
- description: "Bentuk payload untuk source `goal`. Sesi goal mengejar satu tujuan tanpa fase perencanaan (ADR-0089).",
7164
+ description: "Bentuk payload untuk source `goal` dan `no_effort`. Sesi goal mengejar satu tujuan tanpa fase perencanaan (ADR-0089); sesi no_effort mengerjakan satu task remeh dalam SATU fase lalu berhenti (ADR-0123).",
7156
7165
  properties: {
7157
7166
  goal: str("Satu tujuan yang dikejar sesi. Dari sinilah `objective` backlog diturunkan server."),
7158
7167
  done: str("Bukti berhenti yang dituntut. Kosong berarti goal itu sendiri buktinya."),
@@ -7162,12 +7171,12 @@ var init_mcp_schema = __esm({
7162
7171
  required: ["goal", "done", "constraints", "priority"]
7163
7172
  });
7164
7173
  SPEC_PAYLOAD_ONEOF = {
7165
- description: "Isi backlog. BENTUKNYA DITENTUKAN `source`: `qa` \u2192 {severity, steps, expected, actual, env}; `goal` \u2192 {goal, done, constraints, priority}; `brief`/`audit`/`help` \u2192 {context, outcome, constraints, priority}. Bentuk yang tak cocok ditolak sebelum dikirim.",
7174
+ description: "Isi backlog. BENTUKNYA DITENTUKAN `source`: `qa` \u2192 {severity, steps, expected, actual, env, constraints}; `goal`/`no_effort` \u2192 {goal, done, constraints, priority}; `brief`/`audit`/`help` \u2192 {context, outcome, constraints, priority}. `constraints` qa opsional (default string kosong); bentuk yang tak cocok ditolak sebelum dikirim.",
7166
7175
  oneOf: [BRIEF_PAYLOAD, QA_PAYLOAD, GOAL_PAYLOAD]
7167
7176
  };
7168
7177
  SOURCE_PAYLOAD_ALLOF = [
7169
7178
  { if: { properties: { source: { const: "qa" } }, required: ["source"] }, then: { properties: { payload: QA_PAYLOAD } } },
7170
- { if: { properties: { source: { const: "goal" } }, required: ["source"] }, then: { properties: { payload: GOAL_PAYLOAD } } },
7179
+ { if: { properties: { source: { enum: ["goal", "no_effort"] } }, required: ["source"] }, then: { properties: { payload: GOAL_PAYLOAD } } },
7171
7180
  { if: { properties: { source: { enum: ["brief", "audit", "help"] } }, required: ["source"] }, then: { properties: { payload: BRIEF_PAYLOAD } } }
7172
7181
  ];
7173
7182
  PAGE_PARAMS = {
@@ -8115,25 +8124,26 @@ Judul: ${spec.title}
8115
8124
  Objective: ${spec.objective}${detail}`
8116
8125
  ].filter(Boolean).join("\n\n");
8117
8126
  }
8118
- function startGoalPrompt(spec, branchTo, opts = {}) {
8127
+ function startGoalPrompt(flow, spec, branchTo, opts = {}) {
8119
8128
  const m = resolveMethod(opts.method);
8120
8129
  const g = readGoalPayload(spec.payload);
8130
+ const noEffort = flow === "no_effort";
8121
8131
  const detail = [
8122
8132
  `Goal: ${g?.goal ?? spec.objective}`,
8123
8133
  g?.done ? `Selesai bila: ${g.done}` : "",
8124
8134
  g?.constraints ? `Batasan: ${g.constraints}` : ""
8125
8135
  ].filter(Boolean).join("\n");
8126
8136
  return [
8127
- "hanoman goal \u2014 sesi ini mengejar SATU goal sampai tercapai. TIDAK ada fase Brainstorm, Objective, Spec, maupun Plan: jangan menulis design doc, jangan menulis plan berkotak, jangan memecah pekerjaan ini jadi backlog baru. Langsung kerjakan goal-nya. Tetap ikuti internal/docs sebagai Source of Truth; perbarui docs yang tersentuh dan link-nya di index, dalam commit yang sama.",
8137
+ noEffort ? "hanoman no-effort \u2014 sesi ini mengerjakan SATU pekerjaan remeh lalu berhenti. TIDAK ada fase Brainstorm, Objective, Spec, Plan, maupun fase pembuktian terpisah: jangan menulis design doc, jangan menulis plan berkotak, jangan memecah pekerjaan ini jadi backlog baru, dan jangan menambah fase sendiri. Langsung kerjakan, buktikan seperlunya di fase yang sama, lalu berhenti. Tetap ikuti internal/docs sebagai Source of Truth; perbarui docs yang tersentuh dan link-nya di index, dalam commit yang sama." : "hanoman goal \u2014 sesi ini mengejar SATU goal sampai tercapai. TIDAK ada fase Brainstorm, Objective, Spec, maupun Plan: jangan menulis design doc, jangan menulis plan berkotak, jangan memecah pekerjaan ini jadi backlog baru. Langsung kerjakan goal-nya. Tetap ikuti internal/docs sebagai Source of Truth; perbarui docs yang tersentuh dan link-nya di index, dalam commit yang sama.",
8128
8138
  opts.resume ? resumeClause(opts.resume, branchTo, m.planDir, false) : "",
8129
8139
  detail,
8130
- phaseInstruction(PIPELINES.goal, m),
8131
- "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.",
8140
+ phaseInstruction(PIPELINES[flow], m),
8141
+ noEffort ? "" : "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.",
8132
8142
  autonomyClause(opts.autonomy),
8133
- scopeClause("goal", opts.verifyScope),
8134
- codeStyleClause("goal"),
8143
+ scopeClause(flow, opts.verifyScope),
8144
+ codeStyleClause(flow),
8135
8145
  methodClause(m),
8136
- skillInstruction(PIPELINES.goal, m, writesCode("goal")),
8146
+ skillInstruction(PIPELINES[flow], m, writesCode(flow)),
8137
8147
  `Setelah fase terakhir: commit, lalu \`git push origin HEAD:refs/heads/${branchTo}\`. Worktree ini detached HEAD \u2014 itu memang disengaja.`,
8138
8148
  `Backlog item ${spec.id} \xB7 sumber ${spec.source} \xB7 prioritas ${spec.priority}
8139
8149
  Judul: ${spec.title}`
@@ -8219,7 +8229,7 @@ Stack: ${project.stack || "\u2014"}`,
8219
8229
  ${cron.prompt}`
8220
8230
  ].join("\n\n");
8221
8231
  }
8222
- var PIPELINES, AUTONOMY_CLAUSE, AUTONOMY_CLAUSE_FULL, autonomyClause, phaseInstruction, skillInstruction, auditDecisionInstruction, ESCALATION_CONTRACT, auditOnlyInstruction, auditContinuationInstruction, writesCode, scopeClause, codeStyleClause, methodClause, PROJECT_METHOD, resumeClause, RESUMED_WORKTREE_NOTE, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
8232
+ var PIPELINES, WORK_PHASES, AUTONOMY_CLAUSE, AUTONOMY_CLAUSE_FULL, autonomyClause, phaseInstruction, skillInstruction, auditDecisionInstruction, ESCALATION_CONTRACT, auditOnlyInstruction, auditContinuationInstruction, writesCode, scopeClause, codeStyleClause, methodClause, PROJECT_METHOD, resumeClause, RESUMED_WORKTREE_NOTE, REVERSE_PHASE_GUIDE, SCAFFOLD_PHASE_GUIDE;
8223
8233
  var init_prompt = __esm({
8224
8234
  "../runner/src/prompt.ts"() {
8225
8235
  "use strict";
@@ -8241,8 +8251,14 @@ var init_prompt = __esm({
8241
8251
  // SPEC-407 · ADR-0089 · backlog goal: tak ada fase perencanaan sama sekali. `Goal` = kerjakan,
8242
8252
  // `Verifikasi` = buktikan. Kedua nama unik lintas PIPELINES — syarat peta REACHED di server,
8243
8253
  // yang berkunci nama fase saja.
8244
- goal: ["Goal", "Verifikasi"]
8245
- };
8254
+ goal: ["Goal", "Verifikasi"],
8255
+ // SPEC-825 · ADR-0123 · task remeh: SATU fase. Fase `Verifikasi` milik flow goal menghabiskan
8256
+ // satu giliran agen untuk membuktikan sesuatu yang diff-nya sendiri sudah membuktikan; untuk
8257
+ // ganti copy / bump konstanta / typo docs itu murni biaya. Nama `Kerjakan` unik lintas
8258
+ // PIPELINES — syarat peta REACHED server, yang berkunci nama fase saja.
8259
+ no_effort: ["Kerjakan"]
8260
+ };
8261
+ WORK_PHASES = ["Execute", "Goal", "Kerjakan"];
8246
8262
  AUTONOMY_CLAUSE = 'Jalankan seluruh pipeline sampai tuntas tanpa berhenti di batas antar-fase. Checkpoint "review"/"approval"/"need review" milik skill superpowers BUKAN titik berhenti di sini \u2014 lanjut saja ke fase berikutnya. Berhenti HANYA saat butuh keputusan manusia sejati (percabangan yang mengubah bentuk kerja: data model, kontrak API, scope); saat itu tanyakan di terminal ini dan tunggu jawabannya. Selain itu, terus lanjut.';
8247
8263
  AUTONOMY_CLAUSE_FULL = "Kamu berjalan TANPA pengawas \u2014 tak ada manusia yang menonton terminal ini untuk menjawab. Putuskan sendiri di SETIAP percabangan (termasuk yang mengubah bentuk kerja: data model, kontrak API, scope) berdasarkan Source of Truth dan penilaian terbaikmu; JANGAN berhenti bertanya. Tembus seluruh pipeline sampai stage `done`, lalu commit & push. Jangan menunggu review/persetujuan siapa pun \u2014 catat asumsi & keputusan penting di pesan commit agar bisa di-review pasca-fakta. Merge ke branch utama tetap dilakukan manusia, bukan kamu.";
8248
8264
  autonomyClause = (mode) => mode === "full-control" ? AUTONOMY_CLAUSE_FULL : AUTONOMY_CLAUSE;
@@ -8296,7 +8312,7 @@ ${lines2.join("\n")}` : "";
8296
8312
  return `Backlog brief ini LANJUTAN dari audit ${fromAudit}. Worktree ini lahir dari branch audit itu, jadi dokumen audit sudah ada di ${doc}. BACA dokumen itu lebih dulu dan pakai sebagai bahan fase Brainstorm & Objective \u2014 temuannya sudah terbukti, jangan menginvestigasi ulang dari nol. Semua fase tetap dijalankan: dokumen audit memuat TEMUAN, bukan bentuk solusi, jadi perancangan fitur tetap pekerjaanmu.`;
8297
8313
  return `Backlog qa ini LANJUTAN dari audit ${fromAudit}. Worktree ini lahir dari branch audit itu, jadi dokumen audit sudah ada di ${doc}. JANGAN mengulang investigasi fase Audit dari nol \u2014 baca dokumen audit itu sebagai temuan, tandai fase Audit dilewati (\`echo "Audit skipped" >> "$HANOMAN_PHASE_FILE"\`), lalu ambil keputusan pasca-Audit: perbaikan jelas & kecil \u2192 langsung Execute (tandai \`Spec skipped\` dan \`Plan skipped\` bila sesuai); selain itu Spec \u2192 Plan \u2192 Execute penuh.`;
8298
8314
  };
8299
- writesCode = (flow) => PIPELINES[flow].includes("Execute") || PIPELINES[flow].includes("Goal");
8315
+ writesCode = (flow) => PIPELINES[flow].some((p) => WORK_PHASES.includes(p));
8300
8316
  scopeClause = (flow, scope) => scope && writesCode(flow) ? verifyScopeClause(scope) : "";
8301
8317
  codeStyleClause = (flow) => writesCode(flow) ? CODE_STYLE_CLAUSE : "";
8302
8318
  methodClause = (method) => method.extraClause ?? "";
@@ -8487,7 +8503,7 @@ var init_settings = __esm({
8487
8503
  });
8488
8504
 
8489
8505
  // ../runner/src/goal.ts
8490
- function goalFlowCondition(specId, branchTo, spec) {
8506
+ function goalFlowCondition(flow, specId, branchTo, spec) {
8491
8507
  const g = readGoalPayload(spec?.payload);
8492
8508
  const goal = g?.goal || (spec?.objective ?? "").trim() || "(goal tak tercatat di backlog item)";
8493
8509
  const bukti = g?.done || goal;
@@ -8495,13 +8511,13 @@ function goalFlowCondition(specId, branchTo, spec) {
8495
8511
  `Sesi goal hanoman ${specId}. GOAL: ${goal}`,
8496
8512
  "Sesi ini hanya boleh berhenti bila transkrip TERBARU memuat bukti langsung semua hal berikut:",
8497
8513
  `1. goal tercapai \u2014 ${bukti};`,
8498
- `2. output \`cat "$HANOMAN_PHASE_FILE"\` yang memuat satu baris untuk SETIAP fase ${PIPELINES.goal.join(" \u2192 ")}, masing-masing berakhiran \`done\` atau \`skipped\`;`,
8514
+ `2. output \`cat "$HANOMAN_PHASE_FILE"\` yang memuat satu baris untuk SETIAP fase ${PIPELINES[flow].join(" \u2192 ")}, masing-masing berakhiran \`done\` atau \`skipped\`;`,
8499
8515
  `3. output \`git push origin HEAD:refs/heads/${branchTo}\` yang SUKSES sesudah commit terakhir.`,
8500
8516
  "Bila salah satu bukti tak ada di transkrip terbaru, kondisi BELUM terpenuhi: jalankan perintah verifikasinya, tuntaskan yang masih kurang, lalu lanjutkan \u2014 jangan berhenti."
8501
8517
  ].join("\n");
8502
8518
  }
8503
8519
  function defaultGoalCondition({ flow, specId, branchTo, spec }) {
8504
- if (flow === "goal") return goalFlowCondition(specId, branchTo, spec);
8520
+ if (isGoalShapedFlow(flow)) return goalFlowCondition(flow, specId, branchTo, spec);
8505
8521
  const phases = PIPELINES[flow];
8506
8522
  const planGate = phases.includes("Plan") && phases.includes("Execute");
8507
8523
  const clauses = [
@@ -9296,7 +9312,7 @@ function readPhases(file, flow) {
9296
9312
  function stageFor(phases) {
9297
9313
  let best = -1;
9298
9314
  for (const p of phases) {
9299
- if ((p.name === "Execute" || p.name === "Goal") && p.state === "active")
9315
+ if (WORK_PHASES.includes(p.name) && p.state === "active")
9300
9316
  best = Math.max(best, STAGES.indexOf("executing"));
9301
9317
  if (p.state !== "done" && p.state !== "skipped") continue;
9302
9318
  const s2 = REACHED[p.name];
@@ -9353,7 +9369,10 @@ var init_session_phases = __esm({
9353
9369
  // SPEC-407 · ADR-0089 · flow goal (Goal → Verifikasi): fase kerja mencapai `executing`, fase
9354
9370
  // verifikasi yang mencapai `done`. Kedua nama unik lintas PIPELINES — peta ini berkunci nama.
9355
9371
  Goal: "executing",
9356
- Verifikasi: "done"
9372
+ Verifikasi: "done",
9373
+ // SPEC-825 · ADR-0123 · flow no_effort (Kerjakan): satu fase, jadi fase kerjanya sendiri yang
9374
+ // mencapai `done` — tak ada fase verifikasi untuk menutupnya.
9375
+ Kerjakan: "done"
9357
9376
  };
9358
9377
  phasesComplete = (phases) => phases.length > 0 && phases.every((p) => p.state === "done" || p.state === "skipped");
9359
9378
  }
@@ -25863,7 +25882,7 @@ async function nextSpecId(repoDir) {
25863
25882
  // src/services/spec-fields.ts
25864
25883
  init_src();
25865
25884
  function deriveSpecFields(source, payload, manualPriority) {
25866
- if (source === "goal") {
25885
+ if (payloadShapeFor(source) === "goal") {
25867
25886
  const pick2 = (v) => typeof v === "string" ? v.trim() : "";
25868
25887
  return {
25869
25888
  priority: manualPriority,
@@ -28735,7 +28754,7 @@ async function specs_default(app2) {
28735
28754
  source: b.source,
28736
28755
  stage: "brainstorming",
28737
28756
  priority,
28738
- author: isQa ? `QA \xB7 ${author}` : b.source === "audit" ? `Audit \xB7 ${author}` : b.source === "goal" ? `Goal \xB7 ${author}` : author,
28757
+ author: isQa ? `QA \xB7 ${author}` : b.source === "audit" ? `Audit \xB7 ${author}` : b.source === "goal" ? `Goal \xB7 ${author}` : b.source === "no_effort" ? `No effort \xB7 ${author}` : author,
28739
28758
  objective,
28740
28759
  payload: b.payload,
28741
28760
  branchFrom: b.branchFrom ?? null,
@@ -30445,7 +30464,7 @@ async function startSpecSession(spec, opts) {
30445
30464
  const worktree = `${repoDir}/.worktrees/${id}`;
30446
30465
  const branchTo = `hanoman/${id}`;
30447
30466
  const resume = !isContinue && spec.baseSha ? resumeState(repoDir, worktree, branchTo, spec.headSha) : null;
30448
- const isGoalFlow = opts.flow === "goal";
30467
+ const isGoalFlow = isGoalShapedFlow(opts.flow);
30449
30468
  const goalArgs = {
30450
30469
  flow: opts.flow,
30451
30470
  specId: spec.id,
@@ -30487,7 +30506,7 @@ async function startSpecSession(spec, opts) {
30487
30506
  const resumeCtx = resume ? buildResumeCtx(repoDir, id, opts.flow, resume.worktreeKept) : void 0;
30488
30507
  let prompt;
30489
30508
  if (isGoalFlow) {
30490
- prompt = startGoalPrompt(brief, branchTo, {
30509
+ prompt = startGoalPrompt(opts.flow, brief, branchTo, {
30491
30510
  autonomy: opts.autonomy,
30492
30511
  verifyScope,
30493
30512
  resume: resumeCtx,
@@ -40891,7 +40910,8 @@ async function acceptTicket(t, opts) {
40891
40910
  steps: "Reproduksi dari keluhan pelapor & lampiran.",
40892
40911
  expected: "Perilaku yang diharapkan pelapor.",
40893
40912
  actual: detail,
40894
- env: ""
40913
+ env: "",
40914
+ constraints: ""
40895
40915
  } : { context: detail, outcome: "", constraints: "" };
40896
40916
  const repoDir = await resolveRepoDir(t.projectId);
40897
40917
  let spec = null;
@@ -44155,7 +44175,8 @@ ${backlink}`;
44155
44175
  steps: "Reproduksi dari deskripsi issue.",
44156
44176
  expected: "Perilaku yang diharapkan pelapor issue.",
44157
44177
  actual: detail,
44158
- env: ""
44178
+ env: "",
44179
+ constraints: ""
44159
44180
  } : { context: detail, outcome: "", constraints: "", priority };
44160
44181
  const repoDir = await resolveRepoDir(issue2.projectId).catch(() => null);
44161
44182
  let spec = null;
@@ -231,16 +231,17 @@ server menegakkannya di boundary.
231
231
  | `brief` | brief | `context`, `outcome`, `constraints`, `priority` |
232
232
  | `audit` | brief | idem — audit-only: hasilnya dokumen temuan, tanpa Execute |
233
233
  | `help` | brief | idem — item yang lahir dari tiket Help Center |
234
- | `qa` | qa | `severity` (`critical`\|`major`\|`minor`), `steps`, `expected`, `actual`, `env` |
235
- | `goal` | goal | `goal` (wajib), `done`, `constraints`, `priority` |
234
+ | `qa` | qa | `severity` (`critical`\|`major`\|`minor`), `steps`, `expected`, `actual`, `env`, `constraints` (opsional, default `""`) |
235
+ | `goal` | goal | `goal` (wajib), `done`, `constraints`, `priority` — sesi dua fase (Goal → Verifikasi) |
236
+ | `no_effort` | goal | idem — task remeh, sesi SATU fase (`Kerjakan`): langsung dikerjakan lalu berhenti |
236
237
 
237
238
  Body lengkap: `project` (slug project), `source`, `title`, `priority`
238
239
  (`tinggi`\|`sedang`\|`rendah`), `payload`; opsional `branchFrom` (branch basis — harus benar-benar
239
240
  ada di repo project) dan `dependsOn` (array id backlog yang harus selesai & ter-merge lebih dulu).
240
241
 
241
242
  Yang **tak** kamu kirim karena diturunkan server: `objective` (dari `outcome`/`context` untuk brief,
242
- `actual`/`steps` untuk qa, `goal` untuk goal) dan — khusus `qa` — `priority`, yang diturunkan dari
243
- `severity`.
243
+ `actual`/`steps` untuk qa, `goal` untuk goal & no_effort) dan — khusus `qa` — `priority`, yang
244
+ diturunkan dari `severity`.
244
245
 
245
246
  ```json
246
247
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.1.44",
3
+ "version": "0.1.45",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {