@mestreyoda/fabrica 0.1.4 → 0.1.6

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,43 +1,35 @@
1
1
  {
2
- "version": "1.0",
3
- "max_rounds": 2,
2
+ "version": "1.1",
3
+ "max_rounds": 1,
4
4
  "types": {
5
5
  "feature": {
6
6
  "round1": [
7
- { "id": "f1", "question": "Qual problema específico essa feature resolve para o usuário?", "required": true, "follow_up_if_vague": "Pode dar um exemplo concreto de quando o usuário sentiria falta dessa funcionalidade?" },
8
- { "id": "f2", "question": "Quem vai usar isso? Descreva o perfil do usuário principal.", "required": true, "follow_up_if_vague": um usuário final, admin, desenvolvedor, ou outro perfil?" },
9
- { "id": "f3", "question": "Qual é o fluxo principal? O que o usuário faz passo a passo?", "required": true, "follow_up_if_vague": "Tente descrever: 'O usuário clica em X, preenche Y, vê Z'." },
10
- { "id": "f4", "question": "Existe alguma restrição de tecnologia, prazo ou compatibilidade?", "required": false, "follow_up_if_vague": null },
11
- { "id": "f5", "question": "Esse fluxo exige login? Se sim, quais perfis existem e quais permissões cada perfil deve ter?", "required": false, "follow_up_if_vague": "Descreva pelo menos um exemplo de ação permitida e uma ação bloqueada por perfil." }
7
+ { "id": "f1", "question": "Qual o fluxo principal? O que o usuario faz e o que recebe de volta?", "required": true, "follow_up_if_vague": "Descreva o uso mais basico: entrada saida." },
8
+ { "id": "f2", "question": "Alguma restricao de tecnologia ou compatibilidade?", "required": false, "follow_up_if_vague": null }
12
9
  ]
13
10
  },
14
11
  "bugfix": {
15
12
  "round1": [
16
- { "id": "b1", "question": "O que está acontecendo de errado? Descreva o comportamento atual.", "required": true, "follow_up_if_vague": "Você alguma mensagem de erro? O que aparece na tela?" },
17
- { "id": "b2", "question": "O que deveria acontecer? Qual o comportamento esperado?", "required": true, "follow_up_if_vague": "Antes funcionava corretamente? Quando parou?" },
18
- { "id": "b3", "question": "Como reproduzir o bug? Passos exatos.", "required": true, "follow_up_if_vague": "Em qual página/tela? Com qual tipo de dado?" },
19
- { "id": "b4", "question": "Com que frequência acontece? Sempre, às vezes, em condições específicas?", "required": false, "follow_up_if_vague": null }
13
+ { "id": "b1", "question": "O que esta acontecendo vs. o que deveria acontecer?", "required": true, "follow_up_if_vague": "Voce ve alguma mensagem de erro?" },
14
+ { "id": "b2", "question": "Como reproduzir?", "required": true, "follow_up_if_vague": null }
20
15
  ]
21
16
  },
22
17
  "refactor": {
23
18
  "round1": [
24
- { "id": "r1", "question": "Qual parte do código precisa ser refatorada? Qual módulo/arquivo?", "required": true, "follow_up_if_vague": "Qual funcionalidade está nesse código?" },
25
- { "id": "r2", "question": "Qual o problema atual? (duplicação, complexidade, acoplamento, performance)", "required": true, "follow_up_if_vague": "O que dificulta trabalhar nesse código hoje?" },
26
- { "id": "r3", "question": "Qual o resultado esperado da refatoração?", "required": true, "follow_up_if_vague": "Quer que fique mais legível, mais rápido, ou mais testável?" }
19
+ { "id": "r1", "question": "Qual parte do codigo e qual o problema atual?", "required": true, "follow_up_if_vague": null },
20
+ { "id": "r2", "question": "Qual o resultado esperado da refatoracao?", "required": true, "follow_up_if_vague": null }
27
21
  ]
28
22
  },
29
23
  "research": {
30
24
  "round1": [
31
- { "id": "s1", "question": "O que precisa ser investigado ou avaliado?", "required": true, "follow_up_if_vague": uma tecnologia, abordagem, ou viabilidade de algo?" },
32
- { "id": "s2", "question": "Qual decisão essa pesquisa vai informar?", "required": true, "follow_up_if_vague": "O que muda se a conclusão for positiva vs negativa?" },
33
- { "id": "s3", "question": "Quais critérios definem sucesso da pesquisa?", "required": true, "follow_up_if_vague": "Qual entregável esperado? Documento, PoC, comparativo?" }
25
+ { "id": "s1", "question": "O que precisa ser investigado e qual decisao isso informa?", "required": true, "follow_up_if_vague": null },
26
+ { "id": "s2", "question": "Qual o entregavel? Documento, PoC, comparativo?", "required": true, "follow_up_if_vague": null }
34
27
  ]
35
28
  },
36
29
  "infra": {
37
30
  "round1": [
38
- { "id": "i1", "question": "O que precisa ser configurado/implantado/migrado?", "required": true, "follow_up_if_vague": CI/CD, deploy, banco de dados, monitoramento?" },
39
- { "id": "i2", "question": "Qual o ambiente alvo? (produção, staging, dev, local)", "required": true, "follow_up_if_vague": null },
40
- { "id": "i3", "question": "Há requisitos de downtime, rollback ou compatibilidade?", "required": false, "follow_up_if_vague": null }
31
+ { "id": "i1", "question": "O que precisa ser configurado e em qual ambiente?", "required": true, "follow_up_if_vague": null },
32
+ { "id": "i2", "question": "Ha requisitos de downtime ou rollback?", "required": false, "follow_up_if_vague": null }
41
33
  ]
42
34
  }
43
35
  }
package/dist/index.js CHANGED
@@ -111329,8 +111329,8 @@ import fsSync from "node:fs";
111329
111329
  import path5 from "node:path";
111330
111330
  import { fileURLToPath as fileURLToPath3 } from "node:url";
111331
111331
  function getCurrentVersion() {
111332
- if ("0.1.4") {
111333
- return "0.1.4";
111332
+ if ("0.1.6") {
111333
+ return "0.1.6";
111334
111334
  }
111335
111335
  try {
111336
111336
  const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
@@ -116084,30 +116084,34 @@ var init_conduct_interview = __esm({
116084
116084
  try {
116085
116085
  const questionsText = (payload.interview?.questions ?? []).map((q, i2) => `${i2 + 1}. ${q.question}`).join("\n");
116086
116086
  const answersText = Object.entries(payload.answers ?? {}).map(([key, value]) => `- ${key}: ${value}`).join("\n");
116087
- const prompt = `You are a software specification expert. Based on this project idea, answer the interview questions to produce a structured specification.
116087
+ const prompt = `You are a pragmatic senior engineer scoping a small project from a brief user request. Your job is to derive a tight, actionable specification \u2014 NOT to ask more questions.
116088
116088
 
116089
- Idea: ${payload.raw_idea}
116090
- Classification: ${type}
116089
+ User request: "${payload.raw_idea}"
116090
+ Type: ${type}
116091
116091
 
116092
- Questions:
116093
- ${questionsText}
116092
+ Context from earlier steps:
116093
+ ${answersText || "(none)"}
116094
116094
 
116095
- Existing answers:
116096
- ${answersText || "(none provided yet)"}
116095
+ Produce a concise JSON spec. The title should be a SHORT name (3-5 words, suitable as a repo name). Keep scope minimal \u2014 only what the user explicitly asked for.
116097
116096
 
116098
116097
  Return ONLY valid JSON (no markdown fences):
116099
116098
  {
116100
- "title": "<concise project title, max 120 chars>",
116101
- "objective": "<clear objective statement>",
116102
- "scope_v1": ["<scope item 1>", "<scope item 2>"],
116099
+ "project_slug": "<kebab-case repo name, 2-4 words, e.g. email-validator-cli>",
116100
+ "title": "<short project name, 3-5 words, max 60 chars>",
116101
+ "objective": "<1-2 sentence objective>",
116102
+ "scope_v1": ["<concrete deliverable 1>", "<concrete deliverable 2>"],
116103
116103
  "out_of_scope": ["<item>"],
116104
- "acceptance_criteria": ["<specific, domain-aware AC 1>", "<AC 2>"],
116104
+ "acceptance_criteria": ["<specific, testable AC 1>", "<AC 2>"],
116105
116105
  "definition_of_done": ["Code reviewed and merged", "Tests pass", "QA contract passes"],
116106
116106
  "constraints": "<constraints or 'None specified'>",
116107
116107
  "risks": ["<risk 1>"]
116108
116108
  }
116109
116109
 
116110
- IMPORTANT: Acceptance criteria must be domain-specific, not generic.`;
116110
+ Rules:
116111
+ - Title must be a short name like "email-validator-cli" or "task-tracker-api", NOT a full sentence.
116112
+ - Acceptance criteria must be domain-specific and testable.
116113
+ - Do NOT invent features the user didn't ask for.
116114
+ - Keep it lean \u2014 a CLI that validates emails doesn't need auth, profiles, or config files.`;
116111
116115
  const result = await withLlmRetry(() => ctx.runCommand(resolveOpenClawCli({
116112
116116
  homeDir: ctx.homeDir,
116113
116117
  workspaceDir: ctx.workspaceDir
@@ -117982,7 +117986,7 @@ function normalizeIntakeText(value) {
117982
117986
  return trimmed || null;
117983
117987
  }
117984
117988
  function sanitizeRepoName(raw) {
117985
- return raw.normalize("NFKD").replace(/[^\x00-\x7F]/g, "").toLowerCase().replace(/[\s_]+/g, "-").replace(/[^a-z0-9._-]+/g, "-").replace(/[._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80).replace(/-+$/g, "");
117989
+ return raw.normalize("NFKD").replace(/[^\x00-\x7F]/g, "").toLowerCase().replace(/[\s_]+/g, "-").replace(/[^a-z0-9._-]+/g, "-").replace(/[._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/g, "");
117986
117990
  }
117987
117991
  function isValidRepoName(name) {
117988
117992
  return name.length >= 3 && !REPO_NAME_BLOCKLIST.has(name);
@@ -118014,6 +118018,7 @@ function deriveRepoName(payload, explicitRepoName) {
118014
118018
  return deriveRepoNameFromCandidates([
118015
118019
  { value: explicitRepoName, source: "metadata.repo_url" },
118016
118020
  { value: payload.metadata.project_name, source: "metadata.project_name" },
118021
+ { value: payload.spec_data?.project_slug, source: "spec_data.project_slug" },
118017
118022
  { value: payload.project_map?.project_slug, source: "project_map.project_slug" },
118018
118023
  { value: payload.project_map?.project, source: "project_map.project" },
118019
118024
  { value: payload.spec?.title, source: "spec.title" },
@@ -142071,7 +142076,7 @@ init_migrate_layout();
142071
142076
  import { createHash as createHash6 } from "node:crypto";
142072
142077
  import fs38 from "node:fs/promises";
142073
142078
  import path39 from "node:path";
142074
- var SESSION_TTL_MS = 2 * 6e4;
142079
+ var SESSION_TTL_MS = 10 * 6e4;
142075
142080
  function sessionsDir(workspaceDir) {
142076
142081
  return path39.join(workspaceDir, DATA_DIR, "bootstrap-sessions");
142077
142082
  }
@@ -142261,9 +142266,12 @@ function parseClarificationResponse(text, session) {
142261
142266
  }
142262
142267
  function buildClarificationMessage(parsed, pendingClarification) {
142263
142268
  if (pendingClarification === "stack_and_name" || !parsed.stackHint && !parsed.projectName) {
142264
- return `Que ideia bacana! Para criar o projeto, qual stack voc\xEA quer usar? Por exemplo: Python, Node.js, Go, Java...`;
142269
+ return `Beleza! S\xF3 preciso de duas coisas pra criar:
142270
+
142271
+ 1. Qual stack? (Python, Node.js, Go, Java...)
142272
+ 2. Quer dar um nome pro projeto? Se n\xE3o, eu invento um.`;
142265
142273
  }
142266
- return `Qual stack voc\xEA quer usar para esse projeto? Por exemplo: Python, Node.js, Go, Java...`;
142274
+ return `Qual stack voc\xEA quer usar? (Python, Node.js, Go, Java...)`;
142267
142275
  }
142268
142276
  function buildFollowUpClarification(session) {
142269
142277
  if (!session.stackHint) {