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.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +13 -6
- package/dist/server.js +57 -36
- package/docs/agent-integration.md +5 -4
- package/package.json +1 -1
- package/web/assets/{index-CzdyLXKP.js → index-Bwx_Vz8-.js} +1547 -1547
- package/web/index.html +1 -1
package/dist/build-info.json
CHANGED
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
|
|
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}.
|
|
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: {
|
|
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
|
|
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
|
-
},
|
|
4208
|
+
}, []);
|
|
4208
4209
|
return done({
|
|
4209
4210
|
severity: severityFromPriority(prio()),
|
|
4210
4211
|
steps: "",
|
|
4211
4212
|
expected: str3("goal"),
|
|
4212
4213
|
actual: "",
|
|
4213
|
-
env: ""
|
|
4214
|
-
|
|
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}.
|
|
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: {
|
|
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
|
|
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(
|
|
8134
|
-
codeStyleClause(
|
|
8143
|
+
scopeClause(flow, opts.verifyScope),
|
|
8144
|
+
codeStyleClause(flow),
|
|
8135
8145
|
methodClause(m),
|
|
8136
|
-
skillInstruction(PIPELINES
|
|
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].
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
{
|