@llm-dev-ops/agentics-cli 2.3.0 → 2.4.0
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/pipeline/auto-chain.d.ts +117 -0
- package/dist/pipeline/auto-chain.d.ts.map +1 -1
- package/dist/pipeline/auto-chain.js +1047 -35
- package/dist/pipeline/auto-chain.js.map +1 -1
- package/dist/pipeline/phase2/phases/prompt-generator.d.ts.map +1 -1
- package/dist/pipeline/phase2/phases/prompt-generator.js +152 -6
- package/dist/pipeline/phase2/phases/prompt-generator.js.map +1 -1
- package/dist/pipeline/phase4-5-pre-render/financial-model.d.ts +51 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.js +118 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.d.ts +53 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.js +130 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.d.ts +47 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.js +105 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.d.ts +42 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.js +117 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.js.map +1 -0
- package/dist/pipeline/phase5-build/phases/post-generation-validator.d.ts.map +1 -1
- package/dist/pipeline/phase5-build/phases/post-generation-validator.js +341 -1
- package/dist/pipeline/phase5-build/phases/post-generation-validator.js.map +1 -1
- package/dist/pipeline/types.d.ts +4 -1
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +9 -1
- package/dist/pipeline/types.js.map +1 -1
- package/dist/synthesis/domain-unit-registry.d.ts +1 -1
- package/dist/synthesis/domain-unit-registry.d.ts.map +1 -1
- package/dist/synthesis/domain-unit-registry.js +26 -0
- package/dist/synthesis/domain-unit-registry.js.map +1 -1
- package/dist/synthesis/financial-claim-extractor.d.ts +20 -0
- package/dist/synthesis/financial-claim-extractor.d.ts.map +1 -1
- package/dist/synthesis/financial-claim-extractor.js +31 -0
- package/dist/synthesis/financial-claim-extractor.js.map +1 -1
- package/dist/synthesis/financial-consistency-rules.d.ts +4 -0
- package/dist/synthesis/financial-consistency-rules.d.ts.map +1 -1
- package/dist/synthesis/financial-consistency-rules.js +51 -0
- package/dist/synthesis/financial-consistency-rules.js.map +1 -1
- package/dist/synthesis/roadmap-dates.d.ts +72 -0
- package/dist/synthesis/roadmap-dates.d.ts.map +1 -0
- package/dist/synthesis/roadmap-dates.js +203 -0
- package/dist/synthesis/roadmap-dates.js.map +1 -0
- package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.js +46 -0
- package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +139 -34
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/package.json +1 -1
|
@@ -54,6 +54,28 @@ export interface AutoChainResult {
|
|
|
54
54
|
* Called after every phase so even if later phases fail, earlier artifacts
|
|
55
55
|
* are still available.
|
|
56
56
|
*/
|
|
57
|
+
/**
|
|
58
|
+
* ADR-PIPELINE-074: scaffold body for `src/logger.ts`.
|
|
59
|
+
*
|
|
60
|
+
* Uses `node:async_hooks` AsyncLocalStorage so concurrent Express/Hono
|
|
61
|
+
* requests NEVER cross-contaminate log lines. The legacy
|
|
62
|
+
* `let currentCorrelationId` module-level mutable has been removed; any
|
|
63
|
+
* generator that reintroduces it is caught by PGV-016.
|
|
64
|
+
*
|
|
65
|
+
* Exports:
|
|
66
|
+
* - `Logger` interface with info/warn/error/child
|
|
67
|
+
* - `createLogger(service)` factory
|
|
68
|
+
* - `runWithCorrelation(id, fn)` — wraps an async scope with the ID
|
|
69
|
+
* - `getCorrelationId()` — returns the ID for the current async scope
|
|
70
|
+
* - `setCorrelationId(id)` — legacy shim; mutates the current store
|
|
71
|
+
*/
|
|
72
|
+
export declare const LOGGER_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-074)\n// Correlation IDs flow through an AsyncLocalStorage so concurrent requests\n// never cross-contaminate log lines. Import runWithCorrelation + createLogger\n// from here; NEVER reach for a module-level mutable to store the ID.\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nexport interface Logger {\n info(event: string, data?: Record<string, unknown>): void;\n warn(event: string, data?: Record<string, unknown>): void;\n error(event: string, error: Error, data?: Record<string, unknown>): void;\n child(bindings: Record<string, unknown>): Logger;\n}\n\ninterface LoggerContext {\n correlationId?: string;\n bindings: Record<string, unknown>;\n}\n\nconst storage = new AsyncLocalStorage<LoggerContext>();\n\n/**\n * Run `fn` with `correlationId` installed in the current async scope.\n * Every log line emitted inside `fn` and its async descendants will carry\n * this ID, and it will NOT leak to other concurrent requests.\n */\nexport function runWithCorrelation<T>(correlationId: string, fn: () => T): T {\n const parent = storage.getStore();\n const ctx: LoggerContext = {\n correlationId,\n bindings: parent?.bindings ?? {},\n };\n return storage.run(ctx, fn);\n}\n\n/** Returns the correlation ID for the current async scope, if any. */\nexport function getCorrelationId(): string | undefined {\n return storage.getStore()?.correlationId;\n}\n\n/**\n * Back-compat shim \u2014 deprecated. Retained for legacy callers, but\n * SHOULD NOT be used inside request handlers. Use runWithCorrelation.\n * Under AsyncLocalStorage, this mutates the current store in place;\n * outside an async scope it is a silent no-op.\n */\nexport function setCorrelationId(id: string | undefined): void {\n const ctx = storage.getStore();\n if (ctx) ctx.correlationId = id;\n}\n\nexport function createLogger(service: string): Logger {\n const build = (bindings: Record<string, unknown>): Logger => {\n const emit = (level: string, event: string, extra?: Record<string, unknown>): void => {\n const ctx = storage.getStore();\n const entry = {\n timestamp: new Date().toISOString(),\n level,\n service,\n event,\n ...(ctx?.correlationId ? { correlationId: ctx.correlationId } : {}),\n ...bindings,\n ...(ctx?.bindings ?? {}),\n ...extra,\n };\n process.stderr.write(JSON.stringify(entry) + '\\n');\n };\n return {\n info: (event, data) => emit('info', event, data),\n warn: (event, data) => emit('warn', event, data),\n error: (event, err, data) => emit('error', event, {\n error: err.message,\n stack: err.stack,\n ...data,\n }),\n child: (childBindings) => build({ ...bindings, ...childBindings }),\n };\n };\n return build({});\n}\n";
|
|
73
|
+
/**
|
|
74
|
+
* ADR-PIPELINE-074: concurrency-correctness test emitted alongside
|
|
75
|
+
* `src/logger.ts` in every generated project. Fails loudly if
|
|
76
|
+
* AsyncLocalStorage wiring regresses.
|
|
77
|
+
*/
|
|
78
|
+
export declare const LOGGER_CONCURRENCY_TEST_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-074)\n// Proves correlation IDs do NOT leak across concurrent async tasks.\n// Works with vitest and jest \u2014 both expose describe/it/expect as globals.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { describe, it, expect } from 'vitest';\nimport { runWithCorrelation, getCorrelationId } from './logger.js';\n\ndescribe('logger correlation-id async scoping (ADR-PIPELINE-074)', () => {\n it('does not leak correlation IDs across concurrent async tasks', async () => {\n const results: Array<{ requested: string; observed: string | undefined }> = [];\n const tasks: Promise<void>[] = [];\n for (let i = 0; i < 50; i++) {\n const id = `req-${i}`;\n tasks.push(\n runWithCorrelation(id, async () => {\n await new Promise((r) => setTimeout(r, Math.random() * 10));\n results.push({ requested: id, observed: getCorrelationId() });\n }),\n );\n }\n await Promise.all(tasks);\n for (const r of results) {\n expect(r.observed).toBe(r.requested);\n }\n });\n});\n";
|
|
57
79
|
/**
|
|
58
80
|
* ADR-PIPELINE-068: scaffold body for `src/simulation-lineage.ts`.
|
|
59
81
|
*
|
|
@@ -77,6 +99,101 @@ export declare const SIMULATION_LINEAGE_SCAFFOLD = "// Auto-generated by Agentic
|
|
|
77
99
|
* so existing imports keep working.
|
|
78
100
|
*/
|
|
79
101
|
export declare const CIRCUIT_BREAKER_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-069)\n// Owned by the scaffold \u2014 do NOT redeclare CircuitBreaker in generated code.\nimport { createLogger } from './logger.js';\n\n/** Simple circuit breaker for external service calls. */\nexport class CircuitBreaker {\n private failures = 0;\n private state: 'closed' | 'open' | 'half-open' = 'closed';\n private nextAttempt = 0;\n\n constructor(\n private readonly name: string,\n private readonly threshold = 5,\n private readonly cooldownMs = 30000,\n private readonly logger = createLogger('circuit-breaker'),\n ) {}\n\n async call<T>(fn: () => Promise<T>): Promise<T> {\n if (this.state === 'open') {\n if (Date.now() < this.nextAttempt) {\n throw new Error(`Circuit breaker '${this.name}' is OPEN \u2014 retry after ${new Date(this.nextAttempt).toISOString()}`);\n }\n this.state = 'half-open';\n this.logger.info('circuit.half-open', { name: this.name });\n }\n try {\n const result = await fn();\n if (this.state === 'half-open') {\n this.state = 'closed';\n this.failures = 0;\n this.logger.info('circuit.closed', { name: this.name });\n }\n return result;\n } catch (err) {\n this.failures++;\n if (this.failures >= this.threshold) {\n this.state = 'open';\n this.nextAttempt = Date.now() + this.cooldownMs;\n this.logger.warn('circuit.open', { name: this.name, failures: this.failures, retryAt: new Date(this.nextAttempt).toISOString() });\n }\n throw err;\n }\n }\n\n getState(): string { return this.state; }\n}\n";
|
|
102
|
+
/**
|
|
103
|
+
* ADR-PIPELINE-075: scaffold body for `src/persistence/repository.ts`.
|
|
104
|
+
*
|
|
105
|
+
* Defines the `Repository<T>` interface every stateful service should
|
|
106
|
+
* depend on. Each entity is identified by `idOf(entity)`, validated by a
|
|
107
|
+
* Zod schema on read, and bound to a table name for the SQLite backend.
|
|
108
|
+
*/
|
|
109
|
+
export declare const REPOSITORY_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-075)\n// Repository interface every stateful service should depend on.\n// Generators: use this instead of storing state in a Map<string, T>.\nimport type { ZodType } from 'zod';\n\nexport interface Repository<T> {\n save(entity: T): Promise<void>;\n get(id: string): Promise<T | null>;\n list(filter?: Partial<T>): Promise<readonly T[]>;\n delete(id: string): Promise<void>;\n}\n\nexport interface RepositoryOptions<T> {\n /** How to extract the primary key from an entity. */\n readonly idOf: (entity: T) => string;\n /** Zod schema used to re-validate rows on load (SQLite JSON columns are untrusted). */\n readonly schema: ZodType<T>;\n /** Table name for SQLite backend. Must match /^[a-zA-Z_][a-zA-Z0-9_]*$/. */\n readonly tableName: string;\n}\n\n/** Errors thrown by all Repository implementations. */\nexport class RepositoryError extends Error {\n constructor(message: string, public readonly code: string) {\n super(`${code}: ${message}`);\n this.name = 'RepositoryError';\n }\n}\n";
|
|
110
|
+
/**
|
|
111
|
+
* ADR-PIPELINE-075: scaffold body for `src/persistence/in-memory-repository.ts`.
|
|
112
|
+
*
|
|
113
|
+
* Test-friendly `Repository<T>` implementation backed by a Map. Validates
|
|
114
|
+
* on write AND read so test fixtures catch schema drift. Production
|
|
115
|
+
* services should swap in SqliteRepository via the composition root.
|
|
116
|
+
*/
|
|
117
|
+
export declare const IN_MEMORY_REPO_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-075)\n// In-memory Repository<T> for tests. Not for production use.\nimport type { Repository, RepositoryOptions } from './repository.js';\n\nexport class InMemoryRepository<T> implements Repository<T> {\n private readonly rows = new Map<string, T>();\n constructor(private readonly options: RepositoryOptions<T>) {}\n\n async save(entity: T): Promise<void> {\n const validated = this.options.schema.parse(entity);\n this.rows.set(this.options.idOf(validated), validated);\n }\n\n async get(id: string): Promise<T | null> {\n const row = this.rows.get(id);\n return row === undefined ? null : row;\n }\n\n async list(filter?: Partial<T>): Promise<readonly T[]> {\n const all = Array.from(this.rows.values());\n if (!filter) return all;\n return all.filter(row =>\n Object.entries(filter).every(\n ([k, v]) => (row as Record<string, unknown>)[k] === v,\n ),\n );\n }\n\n async delete(id: string): Promise<void> {\n this.rows.delete(id);\n }\n\n /** Test helper \u2014 never call from production code. */\n clear(): void {\n this.rows.clear();\n }\n\n /** Test helper \u2014 returns the current row count. */\n get size(): number {\n return this.rows.size;\n }\n}\n";
|
|
118
|
+
/**
|
|
119
|
+
* ADR-PIPELINE-075: scaffold body for `src/persistence/sqlite-repository.ts`.
|
|
120
|
+
*
|
|
121
|
+
* Production `Repository<T>` backed by better-sqlite3. Stores each entity
|
|
122
|
+
* as a JSON column keyed by its primary key. Zod re-validates on read
|
|
123
|
+
* because the JSON column is untrusted at runtime.
|
|
124
|
+
*
|
|
125
|
+
* Generated projects must add better-sqlite3 + @types/better-sqlite3 to
|
|
126
|
+
* their package.json — the cross-cutting prompt footer reminds the coding
|
|
127
|
+
* agent to include these deps.
|
|
128
|
+
*/
|
|
129
|
+
export declare const SQLITE_REPO_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-075)\n// SQLite-backed Repository<T> using better-sqlite3.\n// Requires: better-sqlite3 in dependencies, @types/better-sqlite3 in devDependencies.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { Repository, RepositoryOptions } from './repository.js';\nimport { RepositoryError } from './repository.js';\n\n// Minimal structural type \u2014 works with better-sqlite3 without importing it\n// into the scaffold (so the scaffold compiles even when the dependency\n// isn't installed in the pipeline's own test environment).\nexport interface BetterSqliteDatabase {\n exec(sql: string): void;\n prepare(sql: string): {\n run(...params: any[]): { changes: number; lastInsertRowid: number | bigint };\n get(...params: any[]): any;\n all(...params: any[]): any[];\n };\n}\n\nexport interface SqliteRepositoryDeps {\n readonly db: BetterSqliteDatabase;\n}\n\nexport class SqliteRepository<T> implements Repository<T> {\n constructor(\n private readonly deps: SqliteRepositoryDeps,\n private readonly options: RepositoryOptions<T>,\n ) {\n this.assertSafeTableName();\n this.deps.db.exec(`\n CREATE TABLE IF NOT EXISTS ${this.options.tableName} (\n id TEXT PRIMARY KEY,\n data TEXT NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))\n );\n `);\n }\n\n private assertSafeTableName(): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(this.options.tableName)) {\n throw new RepositoryError(`unsafe table name: ${this.options.tableName}`, 'ECLI-REPO-001');\n }\n }\n\n async save(entity: T): Promise<void> {\n const validated = this.options.schema.parse(entity);\n const id = this.options.idOf(validated);\n const data = JSON.stringify(validated);\n this.deps.db\n .prepare(\n `INSERT INTO ${this.options.tableName} (id, data) VALUES (?, ?)\n ON CONFLICT(id) DO UPDATE SET data = excluded.data,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ','now')`,\n )\n .run(id, data);\n }\n\n async get(id: string): Promise<T | null> {\n const row = this.deps.db\n .prepare(`SELECT data FROM ${this.options.tableName} WHERE id = ?`)\n .get(id) as { data: string } | undefined;\n if (!row) return null;\n return this.options.schema.parse(JSON.parse(row.data));\n }\n\n async list(filter?: Partial<T>): Promise<readonly T[]> {\n const rows = this.deps.db\n .prepare(`SELECT data FROM ${this.options.tableName}`)\n .all() as Array<{ data: string }>;\n const parsed = rows.map(r => this.options.schema.parse(JSON.parse(r.data)));\n if (!filter) return parsed;\n return parsed.filter(row =>\n Object.entries(filter).every(\n ([k, v]) => (row as Record<string, unknown>)[k] === v,\n ),\n );\n }\n\n async delete(id: string): Promise<void> {\n this.deps.db.prepare(`DELETE FROM ${this.options.tableName} WHERE id = ?`).run(id);\n }\n}\n";
|
|
130
|
+
/**
|
|
131
|
+
* ADR-PIPELINE-075: scaffold body for `src/persistence/audit-repository.ts`.
|
|
132
|
+
*
|
|
133
|
+
* Append-only audit repository. NO update, NO delete — an audit entry is
|
|
134
|
+
* committed and lives forever. Services that need to mutate a past entry
|
|
135
|
+
* have to bypass the repository and talk raw SQL, which PGV and code
|
|
136
|
+
* review will catch.
|
|
137
|
+
*/
|
|
138
|
+
export declare const AUDIT_REPO_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-075)\n// Append-only audit repository. No update, no delete by design.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { BetterSqliteDatabase } from './sqlite-repository.js';\n\nexport interface AuditEntry {\n readonly entryId: string;\n readonly prevHash: string;\n readonly hash: string;\n readonly payload: Record<string, unknown>;\n readonly actor: string;\n readonly action: string;\n readonly entityType: string;\n readonly entityId: string;\n readonly createdAt: string;\n}\n\nexport interface AuditRepositoryDeps {\n readonly db: BetterSqliteDatabase;\n}\n\nexport class AppendOnlyAuditRepository {\n constructor(private readonly deps: AuditRepositoryDeps) {\n this.deps.db.exec(`\n CREATE TABLE IF NOT EXISTS audit_log (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT,\n entry_id TEXT NOT NULL UNIQUE,\n prev_hash TEXT NOT NULL,\n hash TEXT NOT NULL,\n payload TEXT NOT NULL,\n actor TEXT NOT NULL,\n action TEXT NOT NULL,\n entity_type TEXT NOT NULL,\n entity_id TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))\n );\n CREATE INDEX IF NOT EXISTS idx_audit_log_entity\n ON audit_log(entity_type, entity_id);\n `);\n }\n\n append(entry: AuditEntry): void {\n this.deps.db\n .prepare(\n `INSERT INTO audit_log\n (entry_id, prev_hash, hash, payload, actor, action, entity_type, entity_id, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n entry.entryId,\n entry.prevHash,\n entry.hash,\n JSON.stringify(entry.payload),\n entry.actor,\n entry.action,\n entry.entityType,\n entry.entityId,\n entry.createdAt,\n );\n }\n\n list(): readonly AuditEntry[] {\n const rows = this.deps.db\n .prepare(`SELECT * FROM audit_log ORDER BY sequence ASC`)\n .all() as Array<{\n entry_id: string;\n prev_hash: string;\n hash: string;\n payload: string;\n actor: string;\n action: string;\n entity_type: string;\n entity_id: string;\n created_at: string;\n }>;\n return rows.map(r => ({\n entryId: r.entry_id,\n prevHash: r.prev_hash,\n hash: r.hash,\n payload: JSON.parse(r.payload),\n actor: r.actor,\n action: r.action,\n entityType: r.entity_type,\n entityId: r.entity_id,\n createdAt: r.created_at,\n }));\n }\n\n listByEntity(entityType: string, entityId: string): readonly AuditEntry[] {\n const rows = this.deps.db\n .prepare(\n `SELECT * FROM audit_log\n WHERE entity_type = ? AND entity_id = ?\n ORDER BY sequence ASC`,\n )\n .all(entityType, entityId) as Array<{\n entry_id: string;\n prev_hash: string;\n hash: string;\n payload: string;\n actor: string;\n action: string;\n entity_type: string;\n entity_id: string;\n created_at: string;\n }>;\n return rows.map(r => ({\n entryId: r.entry_id,\n prevHash: r.prev_hash,\n hash: r.hash,\n payload: JSON.parse(r.payload),\n actor: r.actor,\n action: r.action,\n entityType: r.entity_type,\n entityId: r.entity_id,\n createdAt: r.created_at,\n }));\n }\n\n /** Total row count \u2014 used by verify() and reconciliation jobs. */\n size(): number {\n const row = this.deps.db\n .prepare('SELECT COUNT(*) AS n FROM audit_log')\n .get() as { n: number };\n return row.n;\n }\n}\n";
|
|
139
|
+
/**
|
|
140
|
+
* ADR-PIPELINE-078: scaffold body for `src/persistence/canonical-json.ts`.
|
|
141
|
+
*
|
|
142
|
+
* Deterministic JSON serialization for audit hash chains and idempotency
|
|
143
|
+
* keys. Follows JCS (RFC 8785) closely enough for the pipeline's needs:
|
|
144
|
+
* object keys are sorted lexicographically at every depth; arrays preserve
|
|
145
|
+
* order; strings, numbers, booleans, and null use standard JSON encoding.
|
|
146
|
+
*
|
|
147
|
+
* Rejects undefined, BigInt, and circular references. Date objects should
|
|
148
|
+
* be serialized as ISO strings at the boundary BEFORE passing to this
|
|
149
|
+
* function.
|
|
150
|
+
*/
|
|
151
|
+
export declare const CANONICAL_JSON_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-078)\n// Deterministic JSON for audit hash chains. Keys sorted at every depth.\n\nexport class CanonicalJsonError extends Error {\n constructor(message: string) {\n super(`ECLI-CJ-078: ${message}`);\n this.name = 'CanonicalJsonError';\n }\n}\n\n/**\n * Canonicalize `value` into a deterministic JSON string. Keys are sorted\n * at every level; arrays preserve order; primitives use standard encoding.\n */\nexport function canonicalJson(value: unknown): string {\n const visited = new WeakSet<object>();\n return serialize(value, visited);\n}\n\nfunction serialize(value: unknown, visited: WeakSet<object>): string {\n if (value === undefined) {\n throw new CanonicalJsonError('undefined is not canonicalizable \u2014 pass null instead');\n }\n if (value === null) return 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new CanonicalJsonError(`non-finite number: ${String(value)}`);\n }\n return JSON.stringify(value);\n }\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n if (typeof value === 'bigint') {\n throw new CanonicalJsonError('BigInt is not canonicalizable \u2014 convert to string at the boundary');\n }\n if (Array.isArray(value)) {\n if (visited.has(value)) throw new CanonicalJsonError('circular reference in array');\n visited.add(value);\n const parts = value.map(item => serialize(item, visited));\n visited.delete(value);\n return '[' + parts.join(',') + ']';\n }\n if (typeof value === 'object') {\n if (visited.has(value as object)) throw new CanonicalJsonError('circular reference in object');\n visited.add(value as object);\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record).sort();\n const pairs: string[] = [];\n for (const key of keys) {\n const v = record[key];\n if (v === undefined) continue;\n pairs.push(JSON.stringify(key) + ':' + serialize(v, visited));\n }\n visited.delete(value as object);\n return '{' + pairs.join(',') + '}';\n }\n throw new CanonicalJsonError(`unsupported value type: ${typeof value}`);\n}\n";
|
|
152
|
+
/**
|
|
153
|
+
* ADR-PIPELINE-078: scaffold body for `src/persistence/audit-hash.ts`.
|
|
154
|
+
*
|
|
155
|
+
* Wraps `canonicalJson` with audit-log-specific conventions. Every
|
|
156
|
+
* generated `AuditService.append()` method should call `hashAuditEntry`
|
|
157
|
+
* rather than rolling its own `JSON.stringify + createHash` chain.
|
|
158
|
+
*/
|
|
159
|
+
export declare const AUDIT_HASH_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-078)\n// Audit hash-chain helper. Import hashAuditEntry instead of hand-rolling\n// createHash('sha256').update(JSON.stringify(...)).\nimport { createHash } from 'node:crypto';\nimport { canonicalJson } from './canonical-json.js';\n\nexport interface HashChainInput {\n readonly prevHash: string;\n readonly entryId: string;\n readonly actor: string;\n readonly action: string;\n readonly entityType: string;\n readonly entityId: string;\n readonly payload: unknown;\n readonly createdAt: string;\n}\n\n/**\n * Deterministically hash an audit entry's content + its link to the\n * previous entry. Payload keys are sorted at every depth so mutations\n * at any nesting level change the hash.\n */\nexport function hashAuditEntry(input: HashChainInput): string {\n const body = canonicalJson({\n prevHash: input.prevHash,\n entryId: input.entryId,\n actor: input.actor,\n action: input.action,\n entityType: input.entityType,\n entityId: input.entityId,\n payload: input.payload,\n createdAt: input.createdAt,\n });\n return createHash('sha256').update(body).digest('hex');\n}\n";
|
|
160
|
+
/**
|
|
161
|
+
* ADR-PIPELINE-077: scaffold body for `src/erp/schema-provenance.ts`.
|
|
162
|
+
*
|
|
163
|
+
* Every generated ERP adapter file (schema.ts, <system>-adapter.ts, etc.)
|
|
164
|
+
* must export an `ERP_SCHEMA_PROVENANCE` constant of type
|
|
165
|
+
* `ErpSchemaProvenance` declaring whether the schema was invented,
|
|
166
|
+
* pulled from a catalog, or validated by an SME. Under
|
|
167
|
+
* `AGENTICS_ERP_STRICT=true`, `assertErpProvenanceOrFail` refuses to
|
|
168
|
+
* start when source='invented'. PGV-020 enforces presence, PGV-021
|
|
169
|
+
* enforces reviewer + catalog_version on validated entries.
|
|
170
|
+
*/
|
|
171
|
+
export declare const ERP_SCHEMA_PROVENANCE_SCAFFOLD = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-077)\n// Provenance tag for generated ERP schemas. MANDATORY on every file\n// under src/erp/ that exports Zod schemas targeting an external ERP.\n\nexport type ErpProvenanceSource = 'invented' | 'catalog' | 'validated';\n\nexport interface ErpSchemaProvenance {\n /** Target ERP system \u2014 e.g. 'Ramco Aviation', 'Oracle OPERA', 'SAP S/4HANA'. */\n readonly erp_system: string;\n /** Specific module the schema targets \u2014 'Flight Catering Order'. */\n readonly module: string;\n /** Validation stage: invented (no review), catalog (fields match), validated (SME-reviewed). */\n readonly source: ErpProvenanceSource;\n /** Version identifier of the catalog source, when known. */\n readonly catalog_version: string | null;\n /** ISO timestamp of SME review when source='validated'. */\n readonly validated_at: string | null;\n /** Reviewer name + role when source='validated'. */\n readonly reviewer: { name: string; role: string } | null;\n /** Free-text notes visible in startup logs and generated README. */\n readonly notes: string;\n}\n\n/**\n * Assert an ERP adapter is allowed to run in the current environment.\n * Under AGENTICS_ERP_STRICT=true, source='invented' throws ECLI-ERP-077\n * and the process exits with code 77.\n */\nexport function assertErpProvenanceOrFail(\n provenance: ErpSchemaProvenance,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n const strict = env['AGENTICS_ERP_STRICT'] === 'true';\n if (strict && provenance.source === 'invented') {\n throw new Error(\n `ECLI-ERP-077: ERP adapter for ${provenance.erp_system}/${provenance.module} has source='invented' ` +\n `and AGENTICS_ERP_STRICT=true. Pilot deployment requires an SME review \u2014 set source='validated' ` +\n `and provide reviewer + catalog_version before enabling strict mode.`,\n );\n }\n}\n\n/** Console-friendly banner for startup logs + demo output. */\nexport function formatProvenanceBanner(provenance: ErpSchemaProvenance): string {\n const icon = provenance.source === 'validated' ? '\u2705' :\n provenance.source === 'catalog' ? '\uD83D\uDFE1' :\n '\u26A0\uFE0F ';\n const lines: string[] = [\n `${icon} ERP SCHEMA PROVENANCE \u2014 ${provenance.erp_system} / ${provenance.module}`,\n ` source: ${provenance.source}`,\n ];\n if (provenance.catalog_version) lines.push(` catalog: ${provenance.catalog_version}`);\n if (provenance.validated_at) lines.push(` validated: ${provenance.validated_at}`);\n if (provenance.reviewer) lines.push(` reviewer: ${provenance.reviewer.name} (${provenance.reviewer.role})`);\n if (provenance.source === 'invented') {\n lines.push(\n ' ',\n ' WARNING: This schema has not been validated against a real ERP document catalog.',\n ' Pilot deployment requires an SME review before the first live call.',\n \" Set AGENTICS_ERP_STRICT=true in production to block runs until source='validated'.\",\n );\n }\n return lines.join('\\n');\n}\n\n/** Convenience wrapper \u2014 prints the banner to stderr. */\nexport function printProvenanceBanner(provenance: ErpSchemaProvenance): void {\n process.stderr.write(formatProvenanceBanner(provenance) + '\\n');\n}\n";
|
|
172
|
+
/**
|
|
173
|
+
* ADR-PIPELINE-076: scaffold body for `src/api/base-app.ts` (Hono variant).
|
|
174
|
+
*
|
|
175
|
+
* Ships a wire-complete base app so the coding agent never writes
|
|
176
|
+
* middleware/metrics/health plumbing from scratch. Generators extend
|
|
177
|
+
* via `createBaseApp({...}).route('/api/<domain>', yourRouter)` instead
|
|
178
|
+
* of rebuilding.
|
|
179
|
+
*
|
|
180
|
+
* Every generated project that imports `createBaseApp` gets:
|
|
181
|
+
* - correlation middleware (AsyncLocalStorage-scoped, ADR-074)
|
|
182
|
+
* - request logging with duration histogram
|
|
183
|
+
* - GET /health/live (process up check)
|
|
184
|
+
* - GET /health/ready (every readiness check passes)
|
|
185
|
+
* - GET /metrics (Prometheus text, ADR-051)
|
|
186
|
+
* - structured error handler (last)
|
|
187
|
+
*/
|
|
188
|
+
export declare const BASE_APP_SCAFFOLD_HONO = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-076)\n// Wire-complete Hono app base. DO NOT rewrite \u2014 extend via\n// `createBaseApp(deps).route('/api/...', yourRouter)` from your routes module.\nimport { Hono } from 'hono';\nimport { randomUUID } from 'node:crypto';\nimport { runWithCorrelation, createLogger } from '../logger.js';\nimport { incrementCounter, recordHistogram, metricsHandler } from '../middleware.js';\n\nexport interface HealthCheck {\n readonly name: string;\n readonly check: () => Promise<{ ok: boolean; detail?: string }>;\n}\n\nexport interface BaseAppDeps {\n readonly serviceName: string;\n readonly version: string;\n readonly readiness: readonly HealthCheck[];\n}\n\nexport interface BaseAppContextVariables {\n correlationId: string;\n startedAt: number;\n}\n\nconst baseLogger = createLogger('base-app');\n\n/**\n * Build the wire-complete base app.\n *\n * Returned Hono instance already has:\n * - correlation ID middleware (AsyncLocalStorage-scoped)\n * - request logging with duration histogram\n * - GET /health/live process-up check\n * - GET /health/ready runs every registered check\n * - GET /metrics Prometheus text format\n * - structured error handler\n *\n * Add domain routes with `.route('/api/<domain>', yourRouter)`.\n */\nexport function createBaseApp(\n deps: BaseAppDeps,\n): Hono<{ Variables: BaseAppContextVariables }> {\n const app = new Hono<{ Variables: BaseAppContextVariables }>();\n\n // Correlation ID \u2014 MUST be first so every downstream log carries it\n app.use('*', async (c, next) => {\n const id = c.req.header('x-correlation-id') ?? randomUUID();\n c.set('correlationId', id);\n c.set('startedAt', Date.now());\n c.header('X-Correlation-Id', id);\n await runWithCorrelation(id, async () => {\n await next();\n });\n });\n\n // Request logging + metrics\n app.use('*', async (c, next) => {\n await next();\n const durationMs = Date.now() - c.get('startedAt');\n const status = c.res.status;\n baseLogger.info('http.request', {\n method: c.req.method,\n path: c.req.path,\n status,\n durationMs,\n });\n incrementCounter('http_requests_total', {\n method: c.req.method,\n status: String(status),\n });\n recordHistogram('http_request_duration_ms', durationMs, {\n method: c.req.method,\n });\n });\n\n // Liveness \u2014 always returns OK if the process is running\n app.get('/health/live', (c) => {\n return c.json({\n status: 'ok',\n service: deps.serviceName,\n version: deps.version,\n uptime_sec: Math.round(process.uptime()),\n });\n });\n\n // Readiness \u2014 runs every registered check\n app.get('/health/ready', async (c) => {\n const results: Array<{ name: string; ok: boolean; detail?: string }> = [];\n for (const check of deps.readiness) {\n try {\n const r = await check.check();\n results.push({ name: check.name, ok: r.ok, ...(r.detail ? { detail: r.detail } : {}) });\n } catch (err) {\n results.push({\n name: check.name,\n ok: false,\n detail: err instanceof Error ? err.message : String(err),\n });\n }\n }\n const allOk = results.every((r) => r.ok);\n return c.json(\n { status: allOk ? 'ready' : 'not-ready', checks: results },\n allOk ? 200 : 503,\n );\n });\n\n // Metrics \u2014 Prometheus text format\n app.get('/metrics', (c) => {\n return c.text(metricsHandler(), 200, {\n 'Content-Type': 'text/plain; version=0.0.4',\n });\n });\n\n // Error handler \u2014 last, so it catches everything above\n app.onError((err, c) => {\n baseLogger.error('http.error', err as Error, {\n method: c.req.method,\n path: c.req.path,\n });\n const status = (err as { httpStatus?: number }).httpStatus ?? 500;\n return c.json(\n {\n error: {\n message: err.message,\n code: (err as { code?: string }).code ?? 'INTERNAL_ERROR',\n },\n },\n status as 500,\n );\n });\n\n return app;\n}\n";
|
|
189
|
+
/**
|
|
190
|
+
* ADR-PIPELINE-076: scaffold body for `src/api/base-app.ts` (Express variant).
|
|
191
|
+
*
|
|
192
|
+
* Used when the generator detects Express in Phase 4. Same guarantees as
|
|
193
|
+
* the Hono variant — wires correlation / logging / liveness / readiness
|
|
194
|
+
* / metrics / error handler in the correct order.
|
|
195
|
+
*/
|
|
196
|
+
export declare const BASE_APP_SCAFFOLD_EXPRESS = "// Auto-generated by Agentics pipeline (ADR-PIPELINE-076)\n// Wire-complete Express app base. DO NOT rewrite \u2014 mount your routes\n// onto the returned `app` instance instead.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport express from 'express';\nimport { randomUUID } from 'node:crypto';\nimport { runWithCorrelation, createLogger } from '../logger.js';\nimport { incrementCounter, recordHistogram, metricsHandlerExpress } from '../middleware.js';\n\nexport interface HealthCheck {\n readonly name: string;\n readonly check: () => Promise<{ ok: boolean; detail?: string }>;\n}\n\nexport interface BaseAppDeps {\n readonly serviceName: string;\n readonly version: string;\n readonly readiness: readonly HealthCheck[];\n}\n\nconst baseLogger = createLogger('base-app');\n\nexport function createBaseApp(deps: BaseAppDeps): express.Express {\n const app = express();\n app.use(express.json({ limit: '1mb' }));\n\n // Correlation ID \u2014 AsyncLocalStorage-scoped for the request's\n // entire async continuation.\n app.use((req: any, res: any, next: () => void) => {\n const id = (req.headers['x-correlation-id'] as string) || randomUUID();\n req.correlationId = id;\n res.setHeader('X-Correlation-Id', id);\n runWithCorrelation(id, next);\n });\n\n // Request logging + metrics\n app.use((req: any, res: any, next: () => void) => {\n const started = Date.now();\n res.on('finish', () => {\n const durationMs = Date.now() - started;\n baseLogger.info('http.request', {\n method: req.method,\n path: req.path,\n status: res.statusCode,\n durationMs,\n });\n incrementCounter('http_requests_total', {\n method: req.method,\n status: String(res.statusCode),\n });\n recordHistogram('http_request_duration_ms', durationMs, {\n method: req.method,\n });\n });\n next();\n });\n\n app.get('/health/live', (_req, res) => {\n res.json({\n status: 'ok',\n service: deps.serviceName,\n version: deps.version,\n uptime_sec: Math.round(process.uptime()),\n });\n });\n\n app.get('/health/ready', async (_req, res) => {\n const results: Array<{ name: string; ok: boolean; detail?: string }> = [];\n for (const check of deps.readiness) {\n try {\n const r = await check.check();\n results.push({ name: check.name, ok: r.ok, ...(r.detail ? { detail: r.detail } : {}) });\n } catch (err) {\n results.push({\n name: check.name,\n ok: false,\n detail: err instanceof Error ? err.message : String(err),\n });\n }\n }\n const allOk = results.every((r) => r.ok);\n res.status(allOk ? 200 : 503).json({\n status: allOk ? 'ready' : 'not-ready',\n checks: results,\n });\n });\n\n app.get('/metrics', metricsHandlerExpress);\n\n app.use((err: any, req: any, res: any, _next: () => void) => {\n baseLogger.error('http.error', err as Error, {\n method: req.method,\n path: req.path,\n });\n const status = err?.httpStatus ?? 500;\n res.status(status).json({\n error: {\n message: err?.message ?? 'Internal error',\n code: err?.code ?? 'INTERNAL_ERROR',\n },\n });\n });\n\n return app;\n}\n";
|
|
80
197
|
/**
|
|
81
198
|
* ADR-PIPELINE-069: Single source of truth for scaffold-owned modules.
|
|
82
199
|
*
|
|
@@ -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;AAqDD;;;;;;;;;GASG;AACH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,2BAA2B,6iJAqIvC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,omDA8CpC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,eAAO,MAAM,sBAAsB,EAAE,SAAS,mBAAmB,
|
|
1
|
+
{"version":3,"file":"auto-chain.d.ts","sourceRoot":"","sources":["../../src/pipeline/auto-chain.ts"],"names":[],"mappings":"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"}
|