@orchestrator-claude/definitions 3.37.1 → 3.37.3

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.
@@ -554,22 +554,23 @@ function buildMemoryLine(memoryIndexPath: string): string {
554
554
  }
555
555
 
556
556
  /**
557
- * Build [CAPABILITY-MATRIX] + [MEMORY-CONTEXT] lines for injection.
558
- * Fail-open: each half degrades INDEPENDENTLY (TD-249) — a throw building
559
- * the matrix must not discard a working memory line, and a throw building
560
- * the memory line must not discard a working matrix line. Previously both
561
- * lived in one try block, so either failure returned '' and threw away
562
- * whatever the other half had already produced.
563
- * Exported for unit-testability (TD-249).
557
+ * RFC-040 C5: unregistered cwd — no vault/agents/memory-index to read, skip.
558
+ * (Single guard is correct here, NOT a repeat of the TD-249 bug: all five
559
+ * paths derive from the same PROJECT_ROOT, so they are null/non-null
560
+ * together — this is one precondition, not two independently-failing
561
+ * steps. CAPABILITY_CACHE_PATH joined them in S445; it is PROJECT_ROOT-
562
+ * derived too, unless ORCHESTRATOR_STATE_DIR overrides the state dir, in
563
+ * which case it is non-null whenever PROJECT_ROOT is.)
564
564
  */
565
- export function buildCapabilityMatrixContext(): string {
566
- // RFC-040 C5: unregistered cwd — no vault/agents/memory-index to read, skip.
567
- // (Single guard is correct here, NOT a repeat of the TD-249 bug: all five
568
- // paths derive from the same PROJECT_ROOT, so they are null/non-null
569
- // together — this is one precondition, not two independently-failing
570
- // steps. CAPABILITY_CACHE_PATH joined them in S445; it is PROJECT_ROOT-
571
- // derived too, unless ORCHESTRATOR_STATE_DIR overrides the state dir, in
572
- // which case it is non-null whenever PROJECT_ROOT is.)
565
+ interface VaultPaths {
566
+ vaultConfigPath: string;
567
+ agentsDir: string;
568
+ profilesPath: string;
569
+ memoryIndexPath: string;
570
+ capabilityCachePath: string;
571
+ }
572
+
573
+ function resolveVaultPaths(caller: string): VaultPaths | null {
573
574
  if (
574
575
  VAULT_CONFIG_PATH === null ||
575
576
  AGENTS_DIR === null ||
@@ -577,33 +578,84 @@ export function buildCapabilityMatrixContext(): string {
577
578
  MEMORY_INDEX_PATH === null ||
578
579
  CAPABILITY_CACHE_PATH === null
579
580
  ) {
580
- log(
581
- HOOK,
582
- 'buildCapabilityMatrixContext: PROJECT_ROOT unresolved (unregistered cwd) — skipping'
583
- );
584
- return '';
581
+ log(HOOK, `${caller}: PROJECT_ROOT unresolved (unregistered cwd) — skipping`);
582
+ return null;
585
583
  }
584
+ return {
585
+ vaultConfigPath: VAULT_CONFIG_PATH,
586
+ agentsDir: AGENTS_DIR,
587
+ profilesPath: PROFILES_PATH,
588
+ memoryIndexPath: MEMORY_INDEX_PATH,
589
+ capabilityCachePath: CAPABILITY_CACHE_PATH,
590
+ };
591
+ }
586
592
 
587
- let matrixLine = '';
593
+ /**
594
+ * Build the [CAPABILITY-MATRIX] line for injection. Fail-open (TD-249):
595
+ * a throw here returns '' and never touches the memory line, which is
596
+ * built by buildMemoryContext() on its own try block.
597
+ * Exported for unit-testability (TD-315).
598
+ */
599
+ export function buildMatrixContext(): string {
600
+ const paths = resolveVaultPaths('buildMatrixContext');
601
+ if (!paths) return '';
588
602
  try {
589
- matrixLine = buildMatrixLine(
590
- VAULT_CONFIG_PATH,
591
- AGENTS_DIR,
592
- PROFILES_PATH,
593
- CAPABILITY_CACHE_PATH
603
+ return buildMatrixLine(
604
+ paths.vaultConfigPath,
605
+ paths.agentsDir,
606
+ paths.profilesPath,
607
+ paths.capabilityCachePath
594
608
  );
595
609
  } catch (err) {
596
610
  log(HOOK, `Capability matrix failed: ${err}`);
611
+ return '';
597
612
  }
613
+ }
598
614
 
599
- let memoryLine = '';
615
+ /**
616
+ * Build the [MEMORY-CONTEXT] line for injection. Fail-open (TD-249):
617
+ * a throw here returns '' and never touches the matrix line.
618
+ *
619
+ * TD-315: emitted SEPARATELY from the matrix — and BEFORE [LAST-SESSION] —
620
+ * so the memory is not the first block to die when the harness truncates
621
+ * additionalContext. Measured S513/S514: total 17190/17013 chars; with the
622
+ * old order ([ORCHESTRATOR-DATA] · [LAST-SESSION] · [PENDENTE] · greeting ·
623
+ * [CAPABILITY-MATRIX] · [MEMORY-CONTEXT]) the memory started at offset
624
+ * 10974/10551 and a 10000-char cut took ALL 20 memories while the
625
+ * narrative survived whole. Placed right after the state line (offset
626
+ * 4101 in S514, ending 10563), the same cut keeps 91% of it, and any cut
627
+ * >= 10563 keeps it whole — with nothing lost when nothing is cut. Capping
628
+ * [LAST-SESSION] instead would NOT save the memory (it would still end past
629
+ * 13000) and would mutilate the PM's narrative every session, cut or not.
630
+ * Exported for unit-testability (TD-315).
631
+ */
632
+ export function buildMemoryContext(): string {
633
+ const paths = resolveVaultPaths('buildMemoryContext');
634
+ if (!paths) return '';
600
635
  try {
601
- memoryLine = buildMemoryLine(MEMORY_INDEX_PATH);
636
+ return buildMemoryLine(paths.memoryIndexPath);
602
637
  } catch (err) {
603
638
  log(HOOK, `Memory context failed: ${err}`);
639
+ return '';
604
640
  }
641
+ }
605
642
 
606
- return [matrixLine, memoryLine].filter(Boolean).join('\n');
643
+ /**
644
+ * Build [CAPABILITY-MATRIX] + [MEMORY-CONTEXT] lines, matrix first.
645
+ * Fail-open: each half degrades INDEPENDENTLY (TD-249) — a throw building
646
+ * the matrix must not discard a working memory line, and a throw building
647
+ * the memory line must not discard a working matrix line. Previously both
648
+ * lived in one try block, so either failure returned '' and threw away
649
+ * whatever the other half had already produced.
650
+ *
651
+ * TD-315: no longer what main() injects — main() now places the two halves
652
+ * at different offsets (memory before the narrative, matrix after the
653
+ * greeting). Kept as the composed form for the TD-249 partial-failure
654
+ * contract and any external caller.
655
+ * Exported for unit-testability (TD-249).
656
+ */
657
+ export function buildCapabilityMatrixContext(): string {
658
+ return [buildMatrixContext(), buildMemoryContext()].filter(Boolean).join('\n');
607
659
  }
608
660
 
609
661
  /**
@@ -681,7 +733,10 @@ async function main(): Promise<void> {
681
733
  const backlog = getBacklogSummary();
682
734
  const tierInfo = await checkTier();
683
735
  const tierSegment = formatTierSegment(tierInfo);
684
- const capabilityContext = buildCapabilityMatrixContext();
736
+ // TD-315: two separate blocks at two different offsets — see
737
+ // buildMemoryContext's doc comment for the measured reason.
738
+ const memoryContext = buildMemoryContext();
739
+ const matrixContext = buildMatrixContext();
685
740
 
686
741
  // Sprint inbox check (RFC-027 S4 — only for sprint panes)
687
742
  const sprintInboxContext = checkSprintInbox();
@@ -773,11 +828,18 @@ async function main(): Promise<void> {
773
828
  // compaction destroys, so they ride both paths unchanged.
774
829
  // [LAST-SESSION]/[PENDENTE] stay boot-only: they orient someone arriving,
775
830
  // and mid-task they are noise that reads like a session opening.
831
+ //
832
+ // TD-315 ORDER CONTRACT: the state line stays at offset 0 (the greeting
833
+ // keys off the leading token); [MEMORY-CONTEXT] comes IMMEDIATELY after
834
+ // it, before [LAST-SESSION] and everything else, so that a truncation of
835
+ // additionalContext takes narrative and routing hints before it takes
836
+ // memory. Pinned by tests/hooks/session-start-memory-before-narrative.test.ts.
776
837
  const stateLine = `version=${backlog.version}${sessionSegment} | workflow=none${tierSegment}${sessionNumberSegment}${projectBindingSegment} | next=${backlog.next}`;
777
838
  outputContext(
778
839
  'SessionStart',
779
840
  [
780
841
  `${isRecovery ? '[ORCHESTRATOR-RECOVERY]' : '[ORCHESTRATOR-DATA]'} ${stateLine}`,
842
+ memoryContext,
781
843
  ...(isRecovery
782
844
  ? RECOVERY_DIRECTIVE
783
845
  : [
@@ -787,7 +849,7 @@ async function main(): Promise<void> {
787
849
  'Do NOT invoke /orchestrator skill for the greeting — use AskUserQuestion directly.',
788
850
  'Invoke /orchestrator skill only when the user chooses to start a workflow.',
789
851
  ]),
790
- capabilityContext,
852
+ matrixContext,
791
853
  sprintInboxContext,
792
854
  projectSelectionPrompt,
793
855
  ]
@@ -809,10 +871,13 @@ async function main(): Promise<void> {
809
871
  `Injecting workflow ${isRecovery ? 'recovery' : 'context'} (wf=${workflow.id} phase=${workflow.currentPhase})`
810
872
  );
811
873
  const stateLine = `version=${backlog.version}${sessionSegment} | workflow=${workflow.id} | type=${workflow.type} | phase=${workflow.currentPhase} | status=${workflow.status}${actionHint}${tierSegment}${sessionNumberSegment}${projectBindingSegment}`;
874
+ // TD-315: same order contract as the no-workflow path — memory right after
875
+ // the state line, matrix after the instruction block.
812
876
  outputContext(
813
877
  'SessionStart',
814
878
  [
815
879
  `${isRecovery ? '[ORCHESTRATOR-RECOVERY]' : '[ORCHESTRATOR-DATA]'} ${stateLine}`,
880
+ memoryContext,
816
881
  ...(isRecovery
817
882
  ? RECOVERY_DIRECTIVE
818
883
  : [
@@ -820,7 +885,7 @@ async function main(): Promise<void> {
820
885
  'Do NOT invoke /orchestrator skill for the greeting — use AskUserQuestion directly.',
821
886
  'Invoke /orchestrator skill when the user chooses to continue the workflow.',
822
887
  ]),
823
- capabilityContext,
888
+ matrixContext,
824
889
  projectSelectionPrompt,
825
890
  ]
826
891
  .filter(Boolean)
@@ -7664,6 +7664,10 @@ var MEMORY_TYPES = ["feedback", "project", "reference", "user"];
7664
7664
  function truncateSummary(summary, cap) {
7665
7665
  return summary.length > cap ? `${summary.slice(0, cap)}\u2026` : summary;
7666
7666
  }
7667
+ function hasRenderableSummary(entry) {
7668
+ return typeof entry.summary === "string";
7669
+ }
7670
+ var MEMORY_SKIPPED_WARNING_PREFIX = "- [AVISO] ";
7667
7671
  function countByType(list) {
7668
7672
  const counts = {};
7669
7673
  for (const e of list) {
@@ -7672,31 +7676,35 @@ function countByType(list) {
7672
7676
  return counts;
7673
7677
  }
7674
7678
  function formatMemoryContext(selected, allEntries) {
7675
- if (selected.length === 0) return "";
7676
- const selectedCounts = countByType(selected);
7679
+ const renderable = selected.filter(hasRenderableSummary);
7680
+ const skipped = selected.filter((e) => !hasRenderableSummary(e));
7681
+ const warning = skipped.length > 0 ? `${MEMORY_SKIPPED_WARNING_PREFIX}${String(skipped.length)} entrada(s) sem 'summary:' pulada(s) \u2014 conserte o \xEDndice: ${skipped.map((e) => e.file).join(", ")}` : "";
7682
+ if (renderable.length === 0) return warning ? `[MEMORY-CONTEXT] 0 mem\xF3rias
7683
+ ${warning}` : "";
7684
+ const selectedCounts = countByType(renderable);
7677
7685
  const totalCounts = countByType(allEntries);
7678
7686
  const perTypeSummary = MEMORY_TYPES.map(
7679
7687
  (t) => `${t}: ${selectedCounts[t] ?? 0}/${totalCounts[t] ?? 0}`
7680
7688
  ).join(", ");
7681
- const headerBase = `[MEMORY-CONTEXT] ${selected.length} de ${allEntries.length} mem\xF3rias (${perTypeSummary}); crit\xE9rio: cota m\xEDnima de 2 por tipo n\xE3o-feedback + prioridade feedback\u2192rec\xEAncia no restante`;
7682
- const availableForLines = AGGREGATE_CHAR_BUDGET - headerBase.length - SUFFIX_RESERVE;
7689
+ const headerBase = `[MEMORY-CONTEXT] ${renderable.length} de ${allEntries.length} mem\xF3rias (${perTypeSummary}); crit\xE9rio: cota m\xEDnima de 2 por tipo n\xE3o-feedback + prioridade feedback\u2192rec\xEAncia no restante`;
7690
+ const availableForLines = AGGREGATE_CHAR_BUDGET - headerBase.length - SUFFIX_RESERVE - (warning ? warning.length + 1 : 0);
7683
7691
  const lines = [];
7684
7692
  let used = 0;
7685
7693
  let droppedByBudget = 0;
7686
- for (let i = 0; i < selected.length; i++) {
7687
- const entry = selected[i];
7694
+ for (let i = 0; i < renderable.length; i++) {
7695
+ const entry = renderable[i];
7688
7696
  const name = entry.file.replace(/\.md$/, "");
7689
7697
  const truncated = truncateSummary(entry.summary, PER_ENTRY_SUMMARY_CHAR_CAP);
7690
7698
  const line = `- [${entry.type}] ${name}: ${truncated}`;
7691
7699
  if (used + line.length + 1 > availableForLines) {
7692
- droppedByBudget = selected.length - i;
7700
+ droppedByBudget = renderable.length - i;
7693
7701
  break;
7694
7702
  }
7695
7703
  lines.push(line);
7696
7704
  used += line.length + 1;
7697
7705
  }
7698
7706
  const header = droppedByBudget > 0 ? `${headerBase}; +${droppedByBudget} truncadas por or\xE7amento de caracteres` : headerBase;
7699
- return [header, ...lines].join("\n");
7707
+ return [header, ...lines, warning].filter(Boolean).join("\n");
7700
7708
  }
7701
7709
  function isWellFormedMemoryEntry(value) {
7702
7710
  return typeof value === "object" && value !== null && typeof value.file === "string";
package/manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": "orchestrator-definitions/v1",
3
3
  "namespace": "orchestrator",
4
- "version": "3.37.1",
5
- "generatedAt": "2026-09-03T21:04:09.839Z",
4
+ "version": "3.37.3",
5
+ "generatedAt": "2026-09-21T16:00:20.708Z",
6
6
  "definitions": {
7
7
  "agents": [
8
8
  {
@@ -49,7 +49,7 @@
49
49
  "slug": "ciclo-engineer",
50
50
  "file": "agents/ciclo-engineer.md",
51
51
  "version": "1.0.0",
52
- "checksum": "sha256:697b9ef0cb99ea1639a8712ed354dca084402a220c40d4425057c6c304f8358b",
52
+ "checksum": "sha256:b2f83b97ddbf6e4afe18c42122ffe5c40db31fa98df156c93e74c31344188a31",
53
53
  "supersedes": null,
54
54
  "metadata": {}
55
55
  },
@@ -161,7 +161,7 @@
161
161
  "slug": "presentation-engineer",
162
162
  "file": "agents/presentation-engineer.md",
163
163
  "version": "1.0.0",
164
- "checksum": "sha256:f7cfeee4d00baf2f4efe2ab32bef21830c3d9bbc1d8c3100fe92230792f01408",
164
+ "checksum": "sha256:315304c540811affd7af0e03ac3175be0ed3b0496e2d1262558f2156d01f90fd",
165
165
  "supersedes": null,
166
166
  "metadata": {}
167
167
  },
@@ -299,7 +299,7 @@
299
299
  "slug": "ciclo-lane-dispatch",
300
300
  "file": "skills/ciclo-lane-dispatch/SKILL.md",
301
301
  "version": "1.0.0",
302
- "checksum": "sha256:302ae98bd77fcad12e96f70ab3609f0662c403687c11a5aee0eb602a3b34349e",
302
+ "checksum": "sha256:36bcca4483a1170ea30e2478337f819bc755f6fbe60a954ef12f50e95c0becfc",
303
303
  "supersedes": null,
304
304
  "metadata": {}
305
305
  },
@@ -331,7 +331,7 @@
331
331
  "slug": "fase-1b-projecao",
332
332
  "file": "skills/fase-1b-projecao/SKILL.md",
333
333
  "version": "1.0.0",
334
- "checksum": "sha256:22bd537c35f354a39fe51ad5ea436fbf462099aa683dd19e27fe115d45e148a6",
334
+ "checksum": "sha256:efac5331273dc543d33c6ce1779ec860b7d3f80ba80bd17a431c09f4ce694f8d",
335
335
  "supersedes": null,
336
336
  "metadata": {}
337
337
  },
@@ -367,6 +367,14 @@
367
367
  "supersedes": null,
368
368
  "metadata": {}
369
369
  },
370
+ {
371
+ "slug": "lane-1-entrevista",
372
+ "file": "skills/lane-1-entrevista/SKILL.md",
373
+ "version": "1.0.0",
374
+ "checksum": "sha256:19f10164a2f69b4675f2ac251a327a9187eaa1c8c4151904a54eb030849494c7",
375
+ "supersedes": null,
376
+ "metadata": {}
377
+ },
370
378
  {
371
379
  "slug": "orchestrator",
372
380
  "file": "skills/orchestrator/SKILL.md",
@@ -553,11 +561,19 @@
553
561
  "supersedes": null,
554
562
  "metadata": {}
555
563
  },
564
+ {
565
+ "slug": "security-gate-honest",
566
+ "file": "hooks/security-gate-honest.mjs",
567
+ "version": "1.0.0",
568
+ "checksum": "sha256:ddb7690d673fd98640e4ae18bd91ce425a3e135ab1ed5c89c683a17ad48f5e24",
569
+ "supersedes": null,
570
+ "metadata": {}
571
+ },
556
572
  {
557
573
  "slug": "session-start",
558
574
  "file": "hooks/session-start.mjs",
559
575
  "version": "1.0.0",
560
- "checksum": "sha256:0342dd3e07d0dae5ad11d74ba843e4b3096035bc8ef9c393a58c68a99e3978bb",
576
+ "checksum": "sha256:f397e654327305c08e4a88853c45991924071f88195124f1e25cca7fd4c5f911",
561
577
  "supersedes": null,
562
578
  "metadata": {}
563
579
  },
@@ -573,7 +589,7 @@
573
589
  "slug": "subagent-start",
574
590
  "file": "hooks/subagent-start.mjs",
575
591
  "version": "1.0.0",
576
- "checksum": "sha256:0404e7edd4da46a5893048f74f1e01bb76479c18e5649636232a7a256a100230",
592
+ "checksum": "sha256:abfc51ee72c7d016ff31c57616e84a15fa5ab11a209827d87d29f5d1d8edc7e8",
577
593
  "supersedes": null,
578
594
  "metadata": {}
579
595
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-claude/definitions",
3
- "version": "3.37.1",
3
+ "version": "3.37.3",
4
4
  "description": "Built-in definitions (agents, skills, hooks, workflows, KB seeds) for the Orchestrator ecosystem",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: ciclo-lane-dispatch
3
- description: Use BEFORE delegating a lane 2A run to ciclo-engineer (PRD do cliente → Ciclo modelado + protótipo navegável). Triggers on "delegar lane 2A", "rodar o ciclo-engineer", "PRD para protótipo", "run de medição do charter", "modelar o ciclo do cliente". Carries the orchestrator side of the lane: pré-voo, prompt de despacho, e — o essencial — como julgar o relatório que volta re-medindo em vez de acreditar. Do NOT use to BUILD the artifact (that is the agent's charter, which it carries itself) nor for lane 2B (ciclo sem tela — captura não fechada).
3
+ description: Use BEFORE delegating a lane 2A run to ciclo-engineer (PRD do cliente → Ciclo modelado + protótipo navegável). Triggers on "delegar lane 2A", "rodar o ciclo-engineer", "PRD para protótipo", "run de medição do charter", "modelar o ciclo do cliente". Carries the orchestrator side of the lane: pré-voo, prompt de despacho, e — o essencial — como julgar o relatório que volta re-medindo em vez de acreditar. Do NOT use to BUILD the artifact (that is the agent's charter, which it carries itself). Covers both lane 2A and lane 2B (ciclo sem tela) — in 2B the pre-flight carries eight inputs instead of five (§1.3-B) and judgment uses the modeling auditor (§3.6) instead of Playwright.
4
4
  ---
5
5
 
6
- # Ciclo Lane Dispatch — o lado do orquestrador da lane 2A
6
+ # Ciclo Lane Dispatch — o lado do orquestrador da lane 2 (2A e 2B)
7
7
 
8
8
  O `ciclo-engineer` carrega o **executável** (fases 0–6, dez armadilhas, disciplina de token). Esta
9
9
  skill carrega o que **não** cabe nele: o que fazer antes de despachar, e o que fazer com o que
@@ -15,12 +15,11 @@ usuário · `[L]` lacuna aberta.
15
15
 
16
16
  ## Quando usar
17
17
 
18
- USE quando for delegar uma corrida da lane 2A: um PRD de cliente vira **Ciclo modelado** (sempre) e
19
- **protótipo navegável** (quando o PRD tem superfície).
18
+ USE quando for delegar uma corrida da lane 2A **ou 2B**: um PRD de cliente vira **Ciclo modelado** (sempre) e
19
+ **protótipo navegável** (quando o PRD tem superfície). Em 2B o pré-voo tem **nove** insumos (§1.3-B) e o julgamento usa o auditor de modelagem (§3.6).
20
20
 
21
21
  NÃO use para:
22
22
  - **construir** o artefato — é a fase do agente, e ele traz o procedimento próprio;
23
- - **lane 2B** (ciclo sem tela) — não tem doc de procedimento; o agente recusa por construção;
24
23
  - deck Slidev (`presentation-engineer`) ou React app code (`frontend-engineer`).
25
24
 
26
25
  ---
@@ -36,7 +35,7 @@ de processo não chega ao delegado. Se a sessão anterior "corrigiu o charter",
36
35
  `agents/ciclo-engineer.md` pelos termos da correção antes de rodar um teste que depende dela —
37
36
  senão o run mede o charter velho e tu credita o resultado ao novo.
38
37
 
39
- **1.3 Meça os cinco insumos do contrato, não os presuma.** São: caminho do PRD · caminho do design
38
+ **1.3 (2A) Meça os cinco insumos do contrato, não os presuma.** São: caminho do PRD · caminho do design
40
39
  system · repo-alvo · escopo (quais US) · ator-alvo. O **ator sai do PRD com linha citada**, nunca de
41
40
  memória. `[M]` Na S420 cinco das seis correções ao orquestrador foram da mesma família: afirmação
42
41
  sobre artefato externo sem probe — o Invariante 6 escrito e não aplicado.
@@ -46,6 +45,9 @@ insumo *quais US* não é servido pelo PRD: é servido pela **projeção** (a fa
46
45
  projeção só vale se for re-derivável, e o contrato da lane 1 exige três itens juntos no registro
47
46
  dela — commit, `sha256` da fonte e o pedido literal (`J4`, §5 do contrato). Antes de despachar:
48
47
 
48
+ `[S]` **Em modo 2B, um quarto campo.** O escopo não é "a projeção" — é o **corte humano congelado**,
49
+ com o seu próprio `sha256`. Leve os três de sempre **e** o caminho do arquivo do corte com o `sha`.
50
+
49
51
  ```bash
50
52
  # 1. o sha256 que a projecao DECLARA ter derivado (Anexo A.1 dela)
51
53
  grep -A1 'sha256.*fonte' <projecao>
@@ -62,16 +64,34 @@ preenche** (cláusula *Marca `client` proibida sem registro*, no §2 abaixo, e S
62
64
  > Referência por conteúdo e não por número de linha, de propósito: esta própria inserção deslocou
63
65
  > em +21 as linhas que a versão anterior citava como `:57-59`.
64
66
 
67
+ **1.3-B (2B) Os insumos da 2B não são os cinco da 2A — são nove, com papel diferente em três.**
68
+ `[M]` Os cinco da 2A contra o teste do contrato §2.4 (*"campo que só faz sentido para um tipo de
69
+ escopo captura substrato"*), re-medidos:
70
+
71
+ | insumo 2A | na 2B | marca | referente |
72
+ |---|---|---|---|
73
+ | caminho do PRD | **exigido**, igual | `[M]` | Fase 0 é agnóstica |
74
+ | escopo (quais US) | **exigido — como corte humano congelado com `sha`**, nunca "a projeção" | `[U]` **B6, PM** | `ORCAMENTO…:175`; ruído medido 33·66·55·78·74·80·75·75 |
75
+ | ator-alvo | **exigido, com linha citada** do PRD | `[M]` | §1.3 (*o ator sai do PRD com linha citada*); a projeção current tem 12 rótulos, o PRD nove posições (§1.2) — o despacho diz **qual** |
76
+ | caminho do design system | **exigido com outro papel**: contrato de renderização do trilho | `[S]` D6 | Ciclo 01 e os nove Ciclos da partição D-022 inlinam verbatim (os seis da geração 1, hoje em `deliverables/lane-2a/superados/`, também inlinavam); `design-system/od-format/system/` existe |
77
+ | repo-alvo | **dissolvido** → *onde o artefato mora* (`deliverables/lane-2b/`) | `[M]` TD-293 | `ORCAMENTO…` C.3 |
78
+ | **novo:** `modo = 2B` | **exigido, declarado** | `[S]` D2 | contrato §2.4 `:197`: inferir é ambíguo |
79
+ | *(sem equivalente 2A — é 2B-only, como `modo`)* | **novo:** `reflexivo = sim/não`, declarado no despacho quando o PRD descreve o harness que executa a lane | `[S]` D4 | `PROPOSTA-EQUIPAMENTO-LANE2B-S515.md` §5.3 :266-267 (Detecção); `ciclo-engineer.md:137` (F10 — a sonda obrigatória que o campo dispara) |
80
+ | **novo:** registro da conversa do cliente (se houver) | opcional; **sem ele a marca `client` não existe** | `[M]` | `ciclo-engineer.md:107`; §2, cláusula *Marca `client` proibida sem registro* |
81
+ | **novo:** caminho do auditor de modelagem | **exigido** — pré-condição de o agente aceitar 2B | `[S]` F4 | `ciclo-engineer.md`, *Fora de escopo* (recusa 2B sem o auditor em disco) |
82
+
83
+ Rótulos B·/D·/F· e "contrato" referem-se à `PROPOSTA-EQUIPAMENTO-LANE2B-S515.md` e ao `LANE1-CONTRATO-SAIDA-S473.md`.
84
+
65
85
  **1.4 Se for run de medição, retire a referência E prove que ela não cobre o alvo.** `[M]` (S420)
66
86
  Antes de escrever o prompt, `grep -c` no artefato de referência pelo escopo pretendido. Se ele já
67
87
  cobre o alvo, o run mede cópia, não transferência. Quando a referência cobre todo o espaço de
68
- alvos, a restrição vira ativo: retire-a do agente e **use-a depois como ground truth**.
88
+ alvos, a restrição vira ativo: retire-a do agente e **use-a depois como ground truth**. `[S]` Em 2B a referência a vedar são os **nove Ciclos da partição D-022** (mesmo PRD-001: `ciclo-agente-fase-dispatch-s516.html`, `ciclo-continuidade-handoff-s516.html`, `ciclo-define-gate-s515.html`, `ciclo-emenda-constituicao-s516.html`, `ciclo-instrumento-varredura-s515.html`, `ciclo-opera-sessao-s515.html`, `ciclo-orquestrador-workflow-s516.html`, `ciclo-ratifica-s515-run2.html`, `ciclo-time-cliente-curva-s516.html`) e o **Ciclo 01** (`CICLO-01-TOKEN-EXTRACTION-S417.md`), **e também os três protótipos** `prototipo-app-canvas.html`, `prototipo-app-canvas-v2.html`, `prototipo-app-canvas-v3.html` (`deliverables/lane-2a/`) — telas 2A sobre o mesmo PRD-001; a 2B existe para não ver tela; o próximo protótipo, por superfície, nasce depois do run 2B como unidade separada. Os seis Ciclos da geração 1 (pré-partição, movidos para `deliverables/lane-2a/superados/` na S517) não contam — não são a referência ativa.
69
89
 
70
90
  ---
71
91
 
72
92
  ## 2 · O prompt de despacho
73
93
 
74
- Entregue os cinco insumos e mais estas cláusulas:
94
+ Entregue os cinco insumos (nove em 2B, §1.3-B) e mais estas cláusulas:
75
95
 
76
96
  - **Vedação de referência** (em run de medição): *não leia o conteúdo de artefatos anteriores desta
77
97
  lane; listar o diretório para escolher nome livre é permitido.*
@@ -85,6 +105,9 @@ Entregue os cinco insumos e mais estas cláusulas:
85
105
  commita depois de ler o relatório.
86
106
  - **Cláusula de escape.** `[M]` (S420) *"Se o protocolo te obrigar a abrir o arquivo vedado, não
87
107
  abra — registre o conflito."* Produziu duas declarações honestas e espontâneas.
108
+ - **Em modo 2B, quatro campos a mais.** `[S]` *"modo = 2B; auditor em `scripts/audit-ciclo-modelagem.py`;
109
+ reflexivo = sim/não; corte = <arquivo> sha <x>."* A **neutralidade** abaixo continua valendo: não
110
+ diga ao agente que se mede c6/c7 (§5.4 da proposta).
88
111
 
89
112
  **Neutralidade do dispatch — regra dura.** `[S]` Se o run existe para medir alguma dimensão
90
113
  (interatividade, densidade, fidelidade), **não conte isso ao agente**. Dizer "estou medindo teus
@@ -122,6 +145,13 @@ mesma US nos quatro runs):
122
145
  `[M]` O baseline opus **não é comparável no eixo de telas**: ele usa vocabulário próprio
123
146
  (`ws-step`, `spine-step`). Compare runs entre si, que compartilham o charter.
124
147
 
148
+ `[M]` (S513) A coluna de telas sai **particionada por vocabulário**, `Ns/Mv` — `s` é token de classe
149
+ `screen`/`*-screen`, `v` é container com token `view` (a forma dos artefatos do app, `<main
150
+ class="view" data-view=…>`). Antes disso o contador deu **0 na v1 e na v2** do protótipo do app,
151
+ que têm 6 telas cada (S512 contou por grep) — segundo falso zero da família do §3.3, noventa e duas sessões e
152
+ um vocabulário depois. Um zero de um lado nunca mais se disfarça de zero de superfície: `0s/6v` é
153
+ leitura, `0s/0v` é o achado grave. `[S]` Em 2B este instrumento (`audit-prototype-interactivity.sh`) imprime `0s/0v` **por definição** — não é veredito de nada; o veredito de 2B é o do auditor de modelagem (§3.6).
154
+
125
155
  ### 3.2 Fidelidade do contrato de tokens — a checagem que o auditor NÃO faz
126
156
 
127
157
  `[M]` (S420) O auditor valida o **grafo de referências** (`var(--x)` aponta para algo declarado).
@@ -155,6 +185,61 @@ Duas regras saem disso:
155
185
  **corrobora** que os gates são estruturais e não decorativos; não substitui percorrer o fluxo no
156
186
  browser e ver o botão travar e liberar. Se tu não abriu o browser, diga que não abriu.
157
187
 
188
+ ### 3.5 O que nenhum dos três lê: a CSSOM — regra escrita e não aplicada
189
+
190
+ `[M]` (S512) `ciclo-registro-estrutural.html`, **mergeado em main**, tinha em `:335` um `/*` que
191
+ documentava o conserto do overflow da S511 e não tinha `*/`. O próximo `*/` estava em `:365`, dentro
192
+ de outro comentário; como comentário CSS não aninha, ele fechou o de 335 — e **vinte regras entre
193
+ 345-364 viraram texto** (`.chip` inclusive o `white-space:normal` que a memória S507 prescreve,
194
+ `.edge-head`, `.edge-title`, `.edge-open`). Segundo caso em `:391→:402`. Confirmado no render com
195
+ controle positivo: 24 `.chip` com borda 0, padding 0, Montserrat em vez de mono; `.edge-card
196
+ {min-width:0}`, que está **antes** do comentário, vivo.
197
+
198
+ **Por que passou pelos três instrumentos:** o auditor de tokens valida o *grafo de referências* no
199
+ texto — `var(--x)` dentro de comentário é texto e aponta para token declarado. O diff de pares
200
+ (§3.2) olha declarações `--x: v;`, que não estavam no span. O auditor de interatividade (§3.1)
201
+ conta listeners e JS. **Nenhum lê a CSSOM.** E o 375×375 da S511 passou plausivelmente *por causa*
202
+ do defeito: chip sem padding é mais estreito. É a lição da S511 em outra roupa — documentar o
203
+ **conserto** matou vinte regras vizinhas.
204
+
205
+ Dois passos, o segundo é o veredito:
206
+
207
+ ```bash
208
+ # 1. detector barato — por bloco <style>, máquina de estados; imprime cada span de
209
+ # comentário com `/*` aninhado E linhas com forma de regra CSS dentro dele.
210
+ scripts/audit-css-dead-by-comment.py <artefato.html> [outros.html ...]
211
+ ```
212
+
213
+ `[M]` Calibrado na S513 com **um defeituoso e sete controles**: o registro-estrutural dá 2 `SUSPEITO`
214
+ (`:335→:365` com 17 linhas com forma de regra; `:391→:402` com 1), exit 1; os sete irmãos dão 1
215
+ `AVISO` cada e exit 0 — é o `/*` do glob `fonts/*.woff2` em prosa dentro do comentário das fontes,
216
+ que um balanço cru `/*` contra `*/` acusaria como defeito. **Balanço por arquivo dá falso positivo;
217
+ máquina de estados simples dá falso negativo** (o `/*` de 335 *é* fechado, pelo `*/` errado). O
218
+ sinal é a conjunção: aninhamento **e** regra engolida.
219
+
220
+ ```js
221
+ // 2. o juiz — Playwright browser_evaluate. Um seletor de DENTRO do span suspeito e um
222
+ // de FORA (controle positivo). Regra escrita no arquivo e ausente aqui é CSS morto.
223
+ (() => {
224
+ const live = new Set();
225
+ for (const sh of document.styleSheets) for (const r of sh.cssRules) if (r.selectorText) live.add(r.selectorText);
226
+ const probe = (sel) => ({ sel, naCSSOM: live.has(sel), el: document.querySelector(sel) && getComputedStyle(document.querySelector(sel)).padding });
227
+ return [probe('.chip'), probe('.edge-card')]; // troque pelos seletores do span e do controle
228
+ })()
229
+ ```
230
+
231
+ Suspeita do passo 1 sem o passo 2 é suspeita; passo 2 sem controle positivo é leitura de um
232
+ instrumento que pode estar cego. Em despacho de agente, a cláusula "zero token novo" **não** protege
233
+ disto — se for pedir, peça o balanço por bloco no relatório, e re-meça.
234
+
235
+ ### 3.6 Julgar um Ciclo 2B
236
+
237
+ `[S]` Em modo 2B não há Playwright para dirigir gate nem interatividade para contar (§3.1 dá
238
+ `0s/0v` **por definição** — não é veredito). §3.2, §3.3 e §3.5 continuam valendo para o trilho. O julgamento é: rode `scripts/audit-ciclo-modelagem.py`,
239
+ cole a tabela de saída inteira, **e** confira por leitura duas coisas que o instrumento não lê:
240
+ **(i)** um `open` ao acaso — o PRD realmente não diz aquilo? **(ii)** um `prd` ao acaso — a linha
241
+ citada existe de fato no PRD?
242
+
158
243
  ---
159
244
 
160
245
  ## 4 · Artefato falho é evidência — não conserte