@llm-dev-ops/agentics-cli 1.5.32 → 1.5.34

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 +1 @@
1
- {"version":3,"file":"auto-chain.d.ts","sourceRoot":"","sources":["../../src/pipeline/auto-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,wBAAwB,CAAC;AA+BhC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6MD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAsgC1B;AA6PD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CA0DzE"}
1
+ {"version":3,"file":"auto-chain.d.ts","sourceRoot":"","sources":["../../src/pipeline/auto-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,wBAAwB,CAAC;AA+BhC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6MD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA+5B1B;AA6PD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CA0DzE"}
@@ -663,8 +663,8 @@ The prompts must be production-grade — they will be given directly to a coding
663
663
  ? fs.readdirSync(promptsDir).filter(f => f.startsWith('impl-'))
664
664
  : [];
665
665
  if (generatedPrompts.length === 0) {
666
- console.error(' [PROMPTS] Ruflo swarm did not produce prompts — writing directly from ADRs/DDDs/SPARC');
667
- // ── Read full ADR markdown files (not just JSON index) ──
666
+ console.error(' [PROMPTS] Ruflo swarm did not produce prompts — writing SPARC+ADR-driven build phases');
667
+ // ── Read all source material ──
668
668
  const adrMarkdownByFile = new Map();
669
669
  for (const f of adrFiles) {
670
670
  try {
@@ -672,7 +672,6 @@ The prompts must be production-grade — they will be given directly to a coding
672
672
  }
673
673
  catch { /* skip */ }
674
674
  }
675
- // Read ADR index for structured data
676
675
  const adrIndexPath = path.join(adrDir, 'adr-index.json');
677
676
  let adrs = [];
678
677
  if (fs.existsSync(adrIndexPath)) {
@@ -685,17 +684,9 @@ The prompts must be production-grade — they will be given directly to a coding
685
684
  for (const f of adrFiles) {
686
685
  const content = adrMarkdownByFile.get(f) ?? '';
687
686
  const titleMatch = content.match(/^#\s+(.+)/m);
688
- adrs.push({
689
- id: f.replace(/\.md$/, ''),
690
- title: titleMatch?.[1] ?? f,
691
- context: content.slice(0, 500),
692
- decision: '',
693
- consequences: [],
694
- alternatives: [],
695
- });
687
+ adrs.push({ id: f.replace(/\.md$/, ''), title: titleMatch?.[1] ?? f, context: content.slice(0, 500), decision: '', consequences: [], alternatives: [] });
696
688
  }
697
689
  }
698
- // Find the full markdown for each ADR (match by ID in filename)
699
690
  function getAdrMarkdown(adr) {
700
691
  for (const [filename, content] of adrMarkdownByFile) {
701
692
  if (filename.startsWith(adr.id))
@@ -703,285 +694,203 @@ The prompts must be production-grade — they will be given directly to a coding
703
694
  }
704
695
  return '';
705
696
  }
706
- let dddContexts = [];
707
- let contextMap = [];
708
- let glossary = [];
697
+ // Read DDD as reference material (not as driver)
698
+ let dddContent = '';
709
699
  const dddModelPath = dddDir ? path.join(dddDir, 'domain-model.json') : '';
710
700
  if (dddModelPath && fs.existsSync(dddModelPath)) {
711
701
  try {
712
- const model = JSON.parse(fs.readFileSync(dddModelPath, 'utf-8'));
713
- dddContexts = (model.contexts ?? []).map((c) => ({
714
- name: String(c['name'] ?? 'unknown'),
715
- description: String(c['description'] ?? ''),
716
- aggregates: Array.isArray(c['aggregates']) ? c['aggregates'] : [],
717
- domainEvents: Array.isArray(c['domainEvents']) ? c['domainEvents'] : [],
718
- commands: Array.isArray(c['commands']) ? c['commands'] : [],
719
- queries: Array.isArray(c['queries']) ? c['queries'] : [],
720
- }));
721
- contextMap = Array.isArray(model.contextMap) ? model.contextMap : [];
722
- glossary = Array.isArray(model.ubiquitousLanguageGlossary) ? model.ubiquitousLanguageGlossary : [];
702
+ dddContent = fs.readFileSync(dddModelPath, 'utf-8');
723
703
  }
724
- catch { /* empty */ }
704
+ catch { /* skip */ }
725
705
  }
726
- // ── Read SPARC specification + architecture markdown ──
706
+ // Also read DDD markdown if available
707
+ if (dddDir) {
708
+ for (const f of ['domain-model.md', 'ddd-model.md']) {
709
+ const p = path.join(dddDir, f);
710
+ if (fs.existsSync(p)) {
711
+ try {
712
+ dddContent += '\n\n' + fs.readFileSync(p, 'utf-8');
713
+ break;
714
+ }
715
+ catch { /* skip */ }
716
+ }
717
+ }
718
+ }
719
+ // Read SPARC documents
727
720
  let sparcSpec = '';
728
721
  let sparcArch = '';
722
+ let sparcPseudocode = '';
723
+ let sparcRefinement = '';
729
724
  if (sparcDir) {
730
- for (const [file, target] of [['specification.md', 'spec'], ['architecture.md', 'arch']]) {
725
+ for (const [file, setter] of [
726
+ ['specification.md', 'spec'], ['architecture.md', 'arch'],
727
+ ['pseudocode.md', 'pseudo'], ['refinement.md', 'refine'],
728
+ ]) {
731
729
  const p = path.join(sparcDir, file);
732
730
  if (fs.existsSync(p)) {
733
731
  try {
734
732
  const content = fs.readFileSync(p, 'utf-8');
735
- if (target === 'spec')
733
+ if (setter === 'spec')
736
734
  sparcSpec = content;
737
- else
735
+ else if (setter === 'arch')
738
736
  sparcArch = content;
737
+ else if (setter === 'pseudo')
738
+ sparcPseudocode = content;
739
+ else if (setter === 'refine')
740
+ sparcRefinement = content;
739
741
  }
740
742
  catch { /* skip */ }
741
743
  }
742
744
  }
743
745
  }
744
- // ── Determine build order: use DDD contexts if available, else group ADRs ──
745
- const useDDD = dddContexts.length > 0;
746
- const totalSteps = useDDD ? dddContexts.length : Math.max(adrs.length, 1);
747
- // Map ADRs to contexts by keyword matching on full text
748
- function findRelatedAdrs(contextName) {
749
- const keywords = contextName.toLowerCase().split(/[-_\s]+/).filter(k => k.length > 2);
750
- return adrs.filter(a => {
751
- const text = `${a.title} ${a.context} ${a.decision} ${(a.consequences ?? []).join(' ')}`.toLowerCase();
752
- return keywords.some(kw => text.includes(kw));
746
+ const buildPhases = [
747
+ // Foundation
748
+ { title: 'Project Foundation & Configuration', slug: 'foundation', description: 'Set up project structure, build tooling, dependency management, and configuration. Establish the base folder layout (src/, backend/, frontend/, erp/, integrations/) and configure TypeScript/Rust build pipelines.', folder: 'src', adrKeywords: ['language', 'framework', 'typescript', 'rust', 'build', 'configuration', 'deployment'], includeSparc: 'spec', includeDdd: false },
749
+ { title: 'Core Domain Types & Shared Models', slug: 'core-types', description: 'Define the core domain types, enums, interfaces, and shared models that all other modules will import. These are the foundational data structures of the platform.', folder: 'src', adrKeywords: ['data', 'model', 'schema', 'type', 'domain'], includeSparc: 'arch', includeDdd: true },
750
+ { title: 'Database Schema & Persistence Layer', slug: 'database', description: 'Design and implement the database schema, migrations, connection pooling, and repository interfaces. Create the persistence layer that the backend services will use.', folder: 'backend', adrKeywords: ['database', 'postgres', 'sql', 'bigquery', 'persistence', 'storage', 'migration'], includeSparc: 'none', includeDdd: true },
751
+ // Backend services
752
+ { title: 'Backend API & Service Layer', slug: 'backend-api', description: 'Implement the HTTP API routes, request validation, service layer, and business logic orchestration. Wire up the API to the domain types and persistence layer.', folder: 'backend', adrKeywords: ['api', 'service', 'endpoint', 'route', 'rest', 'http'], includeSparc: 'pseudo', includeDdd: true },
753
+ { title: 'Business Logic & Domain Services', slug: 'business-logic', description: 'Implement the core business logic that is unique to this platform. This is where the domain-specific algorithms, calculations, rules, and decision logic live.', folder: 'backend', adrKeywords: ['logic', 'algorithm', 'calculation', 'rule', 'decision', 'simulation', 'optimization', 'model'], includeSparc: 'pseudo', includeDdd: true },
754
+ { title: 'Authentication & Authorization', slug: 'auth', description: 'Implement authentication (login, tokens, sessions) and authorization (roles, permissions, access control) as specified in the security ADRs.', folder: 'backend', adrKeywords: ['auth', 'security', 'token', 'jwt', 'oauth', 'identity', 'permission', 'role', 'access'], includeSparc: 'none', includeDdd: false },
755
+ // ERP & Integrations
756
+ { title: 'ERP Integration Layer', slug: 'erp-integration', description: 'Build the ERP integration adapters, data mapping, and sync logic for the ERP system specified in requirements.', folder: 'erp', adrKeywords: ['erp', 'netsuite', 'sap', 'dynamics', 'oracle', 'workday', 'integration'], includeSparc: 'none', includeDdd: false },
757
+ { title: 'External System Integrations', slug: 'external-integrations', description: 'Implement connectors for external systems, APIs, data sources, and third-party services mentioned in the requirements.', folder: 'integrations', adrKeywords: ['integration', 'connector', 'external', 'api', 'webhook', 'sync', 'import', 'export'], includeSparc: 'none', includeDdd: false },
758
+ // Frontend
759
+ { title: 'Frontend Application Shell', slug: 'frontend-shell', description: 'Set up the frontend application framework, routing, layout, and component library. Create the application shell that feature pages will plug into.', folder: 'frontend', adrKeywords: ['frontend', 'ui', 'dashboard', 'react', 'vue', 'angular', 'component'], includeSparc: 'none', includeDdd: false },
760
+ { title: 'Frontend Feature Pages & Components', slug: 'frontend-features', description: 'Build the feature-specific pages, forms, data tables, charts, and interactive components that let users interact with the platform.', folder: 'frontend', adrKeywords: ['dashboard', 'page', 'form', 'table', 'chart', 'visualization', 'report'], includeSparc: 'none', includeDdd: true },
761
+ // Quality & Operations
762
+ { title: 'Error Handling, Logging & Monitoring', slug: 'observability', description: 'Implement structured logging, error handling, health checks, metrics, and monitoring endpoints.', folder: 'backend', adrKeywords: ['logging', 'error', 'monitoring', 'health', 'metric', 'observability', 'alert'], includeSparc: 'refine', includeDdd: false },
763
+ { title: 'Testing & Quality Assurance', slug: 'testing', description: 'Write comprehensive unit tests, integration tests, and end-to-end tests. Test the business logic, API endpoints, ERP integration, and frontend components.', folder: 'tests', adrKeywords: ['test', 'quality', 'tdd', 'coverage', 'validation'], includeSparc: 'refine', includeDdd: false },
764
+ { title: 'Deployment & Infrastructure', slug: 'deployment', description: 'Create Dockerfiles, CI/CD pipelines, cloud deployment configs, environment templates, and infrastructure-as-code for the target cloud platform.', folder: 'src', adrKeywords: ['deploy', 'docker', 'cloud', 'gcp', 'aws', 'azure', 'kubernetes', 'terraform', 'ci', 'cd', 'infrastructure'], includeSparc: 'none', includeDdd: false },
765
+ { title: 'Security Hardening & Compliance', slug: 'security', description: 'Implement security controls, input validation, audit logging, data encryption, and compliance requirements specified in the ADRs.', folder: 'backend', adrKeywords: ['security', 'audit', 'compliance', 'encryption', 'governance', 'gdpr', 'sox', 'pci'], includeSparc: 'refine', includeDdd: false },
766
+ { title: 'Documentation & API Reference', slug: 'documentation', description: 'Write API documentation, architecture overview, deployment guide, and user documentation.', folder: 'docs', adrKeywords: ['documentation', 'api', 'reference', 'guide'], includeSparc: 'spec', includeDdd: false },
767
+ ];
768
+ // Filter to only phases that have matching ADRs or are always-included foundational phases
769
+ const alwaysInclude = new Set(['foundation', 'core-types', 'database', 'backend-api', 'business-logic', 'testing', 'deployment']);
770
+ const activeBuildPhases = buildPhases.filter(phase => {
771
+ if (alwaysInclude.has(phase.slug))
772
+ return true;
773
+ // Check if any ADR matches this phase's keywords
774
+ return adrs.some(adr => {
775
+ const adrText = `${adr.title} ${adr.context} ${adr.decision}`.toLowerCase();
776
+ return phase.adrKeywords.some(kw => adrText.includes(kw));
753
777
  });
778
+ });
779
+ // Also check the scenario query for additional phases
780
+ const queryLower = scenarioQuery.toLowerCase();
781
+ for (const phase of buildPhases) {
782
+ if (!activeBuildPhases.includes(phase)) {
783
+ if (phase.adrKeywords.some(kw => queryLower.includes(kw))) {
784
+ activeBuildPhases.push(phase);
785
+ }
786
+ }
754
787
  }
755
- // Find upstream dependencies for a context from the context map
756
- function findUpstreams(contextName) {
757
- return contextMap
758
- .filter(r => r.downstream === contextName)
759
- .map(r => `${r.upstream} (${r.type})`);
760
- }
761
- // Build list of previously completed contexts for dependency tracking
762
- const completedContexts = [];
788
+ const totalSteps = activeBuildPhases.length;
789
+ const completedPhases = [];
763
790
  for (let i = 0; i < totalSteps; i++) {
791
+ const phase = activeBuildPhases[i];
764
792
  const order = i + 1;
765
- if (useDDD) {
766
- // ── DDD-driven prompt: full bounded context details + related ADRs ──
767
- const ctx = dddContexts[i];
768
- const slug = ctx.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50);
769
- const filename = `impl-${String(order).padStart(3, '0')}-${slug}.md`;
770
- const relatedAdrs = findRelatedAdrs(ctx.name);
771
- const upstreams = findUpstreams(ctx.name);
772
- const lines = [
773
- `# Build Step ${order} of ${totalSteps}: ${ctx.name}`,
774
- '',
775
- '**The implementation must be production ready, enterprise grade, commercially viable, bug and error free, without compilation errors.**',
776
- '',
777
- ];
778
- // Dependencies
779
- if (upstreams.length > 0) {
780
- lines.push(`> **Dependencies:** This context depends on: ${upstreams.join(', ')}. Import from those modules.`);
781
- }
782
- else if (order > 1) {
783
- lines.push(`> This step builds on steps 1-${order - 1}. Import from previously built modules.`);
784
- }
785
- else {
786
- lines.push('> This is the foundation step. Build the core types and interfaces that later steps will import.');
787
- }
793
+ const filename = `impl-${String(order).padStart(3, '0')}-${phase.slug}.md`;
794
+ const lines = [
795
+ `# Implementation Prompt ${order} of ${totalSteps}: ${phase.title}`,
796
+ '',
797
+ '**The implementation must be production ready, enterprise grade, commercially viable, bug and error free, without compilation errors.**',
798
+ '',
799
+ `**Target folder:** \`${phase.folder}/\``,
800
+ '',
801
+ ];
802
+ // Dependencies
803
+ if (order > 1) {
804
+ lines.push(`> This step builds on steps 1-${order - 1}. Import from previously built modules.`);
805
+ }
806
+ else {
807
+ lines.push('> This is the foundation step. Establish the project structure and base configuration.');
808
+ }
809
+ lines.push('');
810
+ // Previously built phases
811
+ if (completedPhases.length > 0) {
812
+ lines.push('## Previously Completed (available for import)', '');
813
+ for (const prev of completedPhases)
814
+ lines.push(`- ${prev}`);
788
815
  lines.push('');
789
- // Previously built contexts
790
- if (completedContexts.length > 0) {
791
- lines.push('## Already Built (available for import)');
792
- lines.push('');
793
- for (const prev of completedContexts) {
794
- lines.push(`- **${prev}** — completed`);
795
- }
796
- lines.push('');
797
- }
798
- // Project objective (first time only, abbreviated after)
799
- if (order === 1) {
800
- lines.push('## Project Objective', '', scenarioQuery, '');
801
- }
802
- else {
803
- lines.push(`## Project Objective`, '', scenarioQuery.split('\n')[0]?.slice(0, 300) ?? scenarioQuery.slice(0, 300), '', '> See impl-001 for full project context.', '');
804
- }
805
- // Full DDD bounded context specification
806
- lines.push(`## Bounded Context: ${ctx.name}`, '');
807
- lines.push(ctx.description, '');
808
- if (ctx.aggregates.length > 0) {
809
- lines.push('### Aggregates', '');
810
- for (const agg of ctx.aggregates) {
811
- lines.push(`#### ${agg.name} (root: ${agg.root ?? agg.name})`);
812
- if (agg.entities?.length)
813
- lines.push(`- **Entities:** ${agg.entities.join(', ')}`);
814
- if (agg.valueObjects?.length)
815
- lines.push(`- **Value Objects:** ${agg.valueObjects.join(', ')}`);
816
- lines.push('');
817
- }
818
- }
819
- if (ctx.commands.length > 0) {
820
- lines.push('### Commands', '');
821
- for (const cmd of ctx.commands)
822
- lines.push(`- ${cmd}`);
823
- lines.push('');
824
- }
825
- if (ctx.queries.length > 0) {
826
- lines.push('### Queries', '');
827
- for (const q of ctx.queries)
828
- lines.push(`- ${q}`);
829
- lines.push('');
830
- }
831
- if (ctx.domainEvents.length > 0) {
832
- lines.push('### Domain Events', '');
833
- for (const evt of ctx.domainEvents)
834
- lines.push(`- ${evt}`);
835
- lines.push('');
836
- }
837
- // Related ADRs — include FULL markdown content, not just title/decision
838
- if (relatedAdrs.length > 0) {
839
- lines.push(`## Architecture Decisions Governing This Context (${relatedAdrs.length} ADRs)`, '');
840
- for (const adr of relatedAdrs) {
841
- const fullMarkdown = getAdrMarkdown(adr);
842
- if (fullMarkdown) {
843
- lines.push(fullMarkdown, '');
844
- }
845
- else {
846
- lines.push(`### ${adr.id}: ${adr.title}`, '');
847
- if (adr.context)
848
- lines.push(`**Context:** ${adr.context}`, '');
849
- if (adr.decision)
850
- lines.push(`**Decision:** ${adr.decision}`, '');
851
- if (adr.consequences?.length) {
852
- lines.push('**Consequences:**');
853
- for (const c of adr.consequences)
854
- lines.push(`- ${c}`);
855
- lines.push('');
856
- }
857
- if (adr.alternatives?.length) {
858
- lines.push('**Alternatives Considered:**');
859
- for (const a of adr.alternatives)
860
- lines.push(`- ${a}`);
861
- lines.push('');
862
- }
863
- }
864
- }
865
- }
866
- else {
867
- // No keyword match — include cross-cutting ADRs (infra, security, deployment)
868
- const crossCuttingAdrs = adrs.filter(a => {
869
- const text = `${a.title} ${a.decision}`.toLowerCase();
870
- return /security|auth|deploy|infra|database|logging|error.handling|api.design/i.test(text);
871
- });
872
- if (crossCuttingAdrs.length > 0) {
873
- lines.push(`## Cross-Cutting Architecture Decisions (${crossCuttingAdrs.length} ADRs)`, '');
874
- for (const adr of crossCuttingAdrs) {
875
- const fullMarkdown = getAdrMarkdown(adr);
876
- if (fullMarkdown) {
877
- lines.push(fullMarkdown, '');
878
- }
879
- else {
880
- lines.push(`### ${adr.id}: ${adr.title}`, '');
881
- if (adr.decision)
882
- lines.push(`**Decision:** ${adr.decision}`, '');
883
- }
884
- }
885
- }
886
- }
887
- // SPARC architecture excerpt for first prompt
888
- if (order === 1 && sparcArch) {
889
- lines.push('## SPARC Architecture Reference', '', sparcArch.slice(0, 3000), '');
890
- }
891
- // Relevant glossary terms
892
- const ctxKeywords = ctx.name.toLowerCase().split(/[-_\s]+/);
893
- const relevantTerms = glossary.filter(g => ctxKeywords.some(k => k.length > 2 && (g.term?.toLowerCase().includes(k) || g.definition?.toLowerCase().includes(k))));
894
- if (relevantTerms.length > 0) {
895
- lines.push('## Ubiquitous Language', '');
896
- for (const g of relevantTerms) {
897
- lines.push(`- **${g.term}**: ${g.definition}`);
898
- }
899
- lines.push('');
900
- }
901
- // Implementation instructions specific to this context
902
- lines.push('## Implementation Requirements', '', `- Implement ALL commands, queries, and domain events listed above for the ${ctx.name} context`, '- Create aggregate root classes with proper invariant enforcement', '- Define port interfaces (e.g., `${ctx.name}Port`) for external dependencies', '- Write adapter implementations for each port', '- Include London School TDD tests — mock at aggregate boundaries', '- Export public interfaces so downstream contexts can import them', '- Follow the technology stack and patterns specified in the ADRs above', '');
903
- fs.writeFileSync(path.join(promptsDir, filename), lines.join('\n'), { mode: 0o600, encoding: 'utf-8' });
904
- completedContexts.push(ctx.name);
816
+ }
817
+ // Project requirements full on first prompt, abbreviated after
818
+ if (order === 1) {
819
+ lines.push('## Project Requirements', '', scenarioQuery, '');
905
820
  }
906
821
  else {
907
- // ── ADR-driven prompt (no DDD model): one prompt per ADR with full content ──
908
- const adr = adrs[i];
909
- const slug = adr.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50);
910
- const filename = `impl-${String(order).padStart(3, '0')}-${slug}.md`;
911
- const fullMarkdown = getAdrMarkdown(adr);
912
- const lines = [
913
- `# Build Step ${order} of ${totalSteps}: ${adr.title}`,
914
- '',
915
- '**The implementation must be production ready, enterprise grade, commercially viable, bug and error free, without compilation errors.**',
916
- '',
917
- order > 1
918
- ? `> This step builds on steps 1-${order - 1}. Import from previously built modules.`
919
- : '> This is the foundation step. Build the core types and interfaces that later steps will import.',
920
- '',
921
- ];
922
- if (completedContexts.length > 0) {
923
- lines.push('## Already Built (available for import)', '');
924
- for (const prev of completedContexts)
925
- lines.push(`- **${prev}** completed`);
926
- lines.push('');
927
- }
928
- if (order === 1) {
929
- lines.push('## Project Objective', '', scenarioQuery, '');
930
- if (sparcSpec)
931
- lines.push('## SPARC Specification', '', sparcSpec.slice(0, 4000), '');
932
- if (sparcArch)
933
- lines.push('## SPARC Architecture', '', sparcArch.slice(0, 3000), '');
934
- }
935
- else {
936
- lines.push(`## Project Objective`, '', scenarioQuery.split('\n')[0]?.slice(0, 300) ?? '', '', '> See impl-001 for full project context and SPARC specification.', '');
937
- }
938
- // Full ADR content
939
- lines.push('## Architecture Decision', '');
940
- if (fullMarkdown) {
941
- lines.push(fullMarkdown, '');
822
+ // Include enough context but not the entire prompt every time
823
+ const firstParagraph = scenarioQuery.split(/\n\n/)[0] ?? scenarioQuery.slice(0, 400);
824
+ lines.push('## Project Requirements (Summary)', '', firstParagraph, '', '> See impl-001 for full project requirements.', '');
825
+ }
826
+ // Phase-specific description
827
+ lines.push(`## What to Build`, '', phase.description, '');
828
+ // SPARC reference for this phase
829
+ const sparcMap = { spec: sparcSpec, arch: sparcArch, pseudo: sparcPseudocode, refine: sparcRefinement, none: '' };
830
+ const sparcContent = sparcMap[phase.includeSparc] ?? '';
831
+ if (sparcContent) {
832
+ const sparcLabel = { spec: 'SPARC Specification', arch: 'SPARC Architecture', pseudo: 'SPARC Pseudocode', refine: 'SPARC Refinement', none: '' }[phase.includeSparc] ?? 'SPARC';
833
+ lines.push(`## ${sparcLabel} Reference`, '', sparcContent, '');
834
+ }
835
+ // Relevant ADRs — match by keywords and include FULL markdown
836
+ const matchedAdrs = adrs.filter(adr => {
837
+ const adrText = `${adr.title} ${adr.context} ${adr.decision}`.toLowerCase();
838
+ return phase.adrKeywords.some(kw => adrText.includes(kw));
839
+ });
840
+ // Always include cross-cutting ADRs in foundation prompt
841
+ if (order === 1 && matchedAdrs.length < adrs.length) {
842
+ for (const adr of adrs) {
843
+ if (!matchedAdrs.includes(adr))
844
+ matchedAdrs.push(adr);
942
845
  }
943
- else {
944
- lines.push(`### ${adr.id}: ${adr.title}`, '');
945
- if (adr.context)
946
- lines.push(`**Context:** ${adr.context}`, '');
947
- if (adr.decision)
948
- lines.push(`**Decision:** ${adr.decision}`, '');
949
- if (adr.consequences?.length) {
950
- lines.push('**Consequences:**');
951
- for (const c of adr.consequences)
952
- lines.push(`- ${c}`);
953
- lines.push('');
846
+ }
847
+ if (matchedAdrs.length > 0) {
848
+ lines.push(`## Relevant Architecture Decisions (${matchedAdrs.length} ADRs)`, '');
849
+ for (const adr of matchedAdrs) {
850
+ const fullMarkdown = getAdrMarkdown(adr);
851
+ if (fullMarkdown) {
852
+ lines.push(fullMarkdown, '', '---', '');
954
853
  }
955
- if (adr.alternatives?.length) {
956
- lines.push('**Alternatives Considered:**');
957
- for (const a of adr.alternatives)
958
- lines.push(`- ${a}`);
854
+ else {
855
+ lines.push(`### ${adr.id}: ${adr.title}`, '');
856
+ if (adr.context)
857
+ lines.push(`**Context:** ${adr.context}`, '');
858
+ if (adr.decision)
859
+ lines.push(`**Decision:** ${adr.decision}`, '');
860
+ if (adr.consequences?.length) {
861
+ lines.push('**Consequences:**');
862
+ for (const c of adr.consequences)
863
+ lines.push(`- ${c}`);
864
+ lines.push('');
865
+ }
959
866
  lines.push('');
960
867
  }
961
868
  }
962
- lines.push('## Implementation Requirements', '', '- Implement the decision described in the ADR above', '- Write clean, modular code following the technology stack specified', '- Include London School TDD tests — mock at boundaries', '- Export public interfaces for downstream consumers', '');
963
- fs.writeFileSync(path.join(promptsDir, filename), lines.join('\n'), { mode: 0o600, encoding: 'utf-8' });
964
- completedContexts.push(adr.title);
965
869
  }
870
+ // DDD reference — included as context, not as driver
871
+ if (phase.includeDdd && dddContent) {
872
+ lines.push('## Domain Model Reference (DDD)', '', '> Use this as reference for domain concepts, entity relationships, and business rules.', '');
873
+ // Include a reasonable excerpt
874
+ lines.push(dddContent.slice(0, 6000), '');
875
+ }
876
+ // Implementation instructions
877
+ lines.push('## Implementation Instructions', '', '- All code must be CUSTOM to this project — no generic boilerplate or placeholder logic', '- Follow the technology stack decisions from the ADRs above', '- Write production-quality code with proper error handling', '- Include unit tests for business logic (London School TDD)', '- Export public interfaces so later build phases can import them', `- Place all files in the \`${phase.folder}/\` directory`, '');
878
+ fs.writeFileSync(path.join(promptsDir, filename), lines.join('\n'), { mode: 0o600, encoding: 'utf-8' });
879
+ completedPhases.push(`${order}. ${phase.title}`);
966
880
  }
967
881
  // Write execution plan
968
- const planItems = useDDD
969
- ? dddContexts.map((ctx, i) => ({
970
- order: i + 1,
971
- file: `impl-${String(i + 1).padStart(3, '0')}-${ctx.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50)}.md`,
972
- title: ctx.name,
973
- upstreams: findUpstreams(ctx.name),
974
- adrs: findRelatedAdrs(ctx.name).map(a => a.id),
975
- }))
976
- : adrs.map((adr, i) => ({
977
- order: i + 1,
978
- file: `impl-${String(i + 1).padStart(3, '0')}-${adr.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 50)}.md`,
979
- title: adr.title,
980
- upstreams: [],
981
- adrs: [adr.id],
982
- }));
882
+ const planItems = activeBuildPhases.map((phase, i) => ({
883
+ order: i + 1,
884
+ file: `impl-${String(i + 1).padStart(3, '0')}-${phase.slug}.md`,
885
+ title: phase.title,
886
+ folder: phase.folder,
887
+ adrs: adrs.filter(a => {
888
+ const t = `${a.title} ${a.context} ${a.decision}`.toLowerCase();
889
+ return phase.adrKeywords.some(kw => t.includes(kw));
890
+ }).map(a => a.id),
891
+ }));
983
892
  fs.writeFileSync(path.join(promptsDir, 'execution-plan.json'), JSON.stringify({ totalSteps, prompts: planItems }, null, 2), { mode: 0o600, encoding: 'utf-8' });
984
- console.error(` [PROMPTS] Wrote ${totalSteps} implementation prompts from ${useDDD ? 'DDD bounded contexts' : 'ADRs'} (${adrs.length} ADRs, ${dddContexts.length} contexts, SPARC: ${sparcSpec ? 'yes' : 'no'})`);
893
+ console.error(` [PROMPTS] Wrote ${totalSteps} SPARC+ADR-driven implementation prompts (${adrs.length} ADRs, SPARC: ${sparcSpec ? 'yes' : 'no'}, DDD ref: ${dddContent ? 'yes' : 'no'})`);
985
894
  }
986
895
  copyPlanningArtifacts(runDir);
987
896
  }