wangdl
e769d67908
fix(M-AI-08): export LearningAnalysisSnapshotBuilder from AiJobModule
...
Deploy API Server / build-and-unit (push) Successful in 40s
Deploy API Server / current-integration (push) Successful in 3m4s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / deploy (push) Successful in 1m2s
Required by LearningAnalysisExecutionRouter in AiRuntimeModule.
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 22:12:06 +08:00
wangdl
9cf85023d1
feat(M-AI-08-05): learning analysis projector + atomic idempotency
...
Deploy API Server / build-and-unit (push) Failing after 27s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- LearningAnalysisProjector: AiLearningAnalysis + WeakPointCandidate + Recommendation
- All in one transaction via ProjectionExecutor
- Entry idempotency via Artifact check + P2002 fallback
- Artifact types: learning_analysis, weak_point, recommendation
- Registered in RESULT_PROJECTORS factory
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:44:29 +08:00
wangdl
06a0e21bbf
feat(M-AI-08-04): learning analysis validator + engine integration
...
Deploy API Server / build-and-unit (push) Failing after 28s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- Schema validation: strengths/weaknesses/trends/risks/recommendations limits
- Evidence validation: sourceType enum, metricKey required
- Business validation: insufficientData confidence cap, evidence-required conclusions
- Content safety: medical diagnosis, personality judgment, markdown code blocks
- Engine: validate after executor in learning_analysis dispatch
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:43:15 +08:00
wangdl
1bb131a1bc
feat(M-AI-08-03): learning analysis prompt + schema + executor + engine dispatch
...
Deploy API Server / build-and-unit (push) Failing after 27s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
Resolves A1/A2: learning-analysis prompt and Zod output schema created.
- Prompt: 6 analysis dimensions, evidence-required, no medical diagnosis
- Schema: strengths/weaknesses/trends/risks/recommendations with evidenceRefs
- Executor: AiGateway only, constructs user message from snapshot metrics
- Engine dispatch for learning_analysis job type
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:41:25 +08:00
wangdl
d537ff3bd0
feat(M-AI-08-02): learning analysis snapshot builder + definition
...
Deploy API Server / build-and-unit (push) Failing after 29s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- LearningAnalysisSnapshotBuilder: aggregates 6 data dimensions from trusted server sources
- Windows: behavior 7 days / scores 30 days (matches legacy)
- Data quality: availableSources/missingSources/insufficientDataReasons
- Definition: learning_analysis, ai-background, primary tier
- contentHash: stable via sorted keys + SHA-256
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:36:57 +08:00
wangdl
452144d9c0
fix: export QuizGenerationSnapshotBuilder from AiJobModule
...
Deploy API Server / build-and-unit (push) Successful in 39s
Deploy API Server / current-integration (push) Successful in 3m4s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / deploy (push) Successful in 1m0s
Required by QuizExecutionRouter in AiRuntimeModule (forwardRef context).
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:12:15 +08:00
wangdl
89ad00b4ee
fix: bidirectional forwardRef for AiRuntimeModule <-> AiJobModule
...
Deploy API Server / build-and-unit (push) Successful in 39s
Deploy API Server / backward-compat (push) Has been cancelled
Deploy API Server / deploy (push) Has been cancelled
Deploy API Server / current-integration (push) Has been cancelled
Both sides of the circular dependency need forwardRef().
AiJobModule's import of AiRuntimeModule also wrapped.
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 21:10:16 +08:00
wangdl
a59446266a
feat(M-AI-07-04): quiz generation Projector + atomic idempotency
...
Deploy API Server / build-and-unit (push) Successful in 36s
Deploy API Server / backward-compat (push) Has been cancelled
Deploy API Server / deploy (push) Has been cancelled
Deploy API Server / current-integration (push) Has been cancelled
- QuizGenerationProjector: Quiz + QuizQuestion x N + Artifact in one tx
- Entry idempotency via Artifact check + P2002 fallback
- Quiz fields: sourceType=ai, sourceId=job.id, status=ready
- Invalid questions filtered (missing stem/answer)
- Registered in RESULT_PROJECTORS factory
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 20:43:55 +08:00
wangdl
d368f1a97f
feat(M-AI-07-03): quiz generation Executor + Validator + prompt/schema
...
Deploy API Server / build-and-unit (push) Successful in 37s
Deploy API Server / backward-compat (push) Has been cancelled
Deploy API Server / deploy (push) Has been cancelled
Deploy API Server / current-integration (push) Has been cancelled
Resolves A1/A2: bring quiz prompt + output schema in-house from Runtime.
- quiz-generation.prompt.ts: system prompt with question design principles
- quiz-generation.schema.ts: Zod schema (choice/fill/judge types)
- Registered in PromptTemplateService with key 'quiz-generation' v1.0.0
- Executor: AiGateway call with knowledge items + generation params
- Validator: per-type validation (choice options/index, judge true/false)
- Engine dispatch for quiz_generation job type
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 20:40:12 +08:00
wangdl
9cac4781bd
feat(M-AI-07-02): quiz generation Job Definition + Snapshot Builder
...
Deploy API Server / build-and-unit (push) Successful in 35s
Deploy API Server / current-integration (push) Successful in 3m3s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / deploy (push) Successful in 1m4s
- quiz_generation Definition: ai-interactive, primary tier, 180s timeout
- Snapshot Builder: KB ownership validation, content truncation (2k chars)
- Parameter normalization: questionCount [1,50], types, difficulty
- Stable contentHash via sorted keys + SHA256
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 20:34:33 +08:00
wangdl
f1e529b99e
feat: M-AI-06 Feynman ReviewCard Child Job 与可靠生成
...
Deploy API Server / build-and-unit (push) Failing after 26s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
完成 M-AI-06 全部 7 个 Issue:
- 01: 审计冻结契约 (docs/architecture/m-ai-06-review-card-child-job-contract.md)
- 02: AiJobCreationService.createInTransaction(tx, input)
- 03: ReviewCard Generation Job Definition + Snapshot Builder
- 04: ReviewCard Generation Executor + 输出验证 Validator
- 05: ReviewCard Generation Projector + 卡片幂等 + Engine 接入
- 06: FeynmanProjector 接入 FEYNMAN_REVIEW_CARD_MODE Feature Flag
- 07: E2E 测试 (test/m-ai-06-review-card-child.e2e-spec.ts)
核心变更:
- 新增 10 个文件, 修改 7 个文件
- 新增 createInTransaction() 外部事务支持
- 新增 review_card_generation Job Type (ai-background / cheap tier)
- FeynmanProjector 根据 Feature Flag 路由 child_job / legacy_event
- Projector 入口幂等 + P2002 回退双重保障
- 测试: 单元 482 passed, E2E 待 CI 执行
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-22 19:27:14 +08:00
wangdl
8987598eb8
feat(M-AI-05): track Feynman unified engine migration implementation
...
23 files (+4676/-10):
- Contract: m-ai-05-feynman-migration-contract.md (737 lines)
- Gate audit: m-ai-05-gate-audit.md (318 lines)
- Job Definition + Snapshot Builder + Registration
- Executor + BusinessValidator + ReferenceValidator
- Projector (atomic transaction + 3-layer idempotency)
- ExecutionRouter (FeatureFlag + idempotencyKey)
- ObservabilityService (structured logging + counters)
- Engine: feynman_evaluation execution branch
- AiJobCreationService: feynman_evaluation safety branch
- Controller/Module: Router injection
- CI: path detection for m-ai-05
- E2E: 8 HTTP-layer scenarios (14 total)
- Unit tests: 104 new tests (5 spec files)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 17:44:58 +08:00
wangdl
0ec58669dd
feat(M-AI-04): Active Recall 端到端迁移至统一 Job Engine
...
Deploy API Server / build-and-unit (push) Successful in 37s
Deploy API Server / current-integration (push) Failing after 1m35s
Deploy API Server / backward-compat (push) Successful in 17s
Deploy API Server / deploy (push) Has been skipped
M-AI-04-01: 审计并冻结迁移契约 (文档)
M-AI-04-02: 注册 JobDefinition + SnapshotBuilder (28 tests)
M-AI-04-03: Executor + BusinessValidator + ReferenceValidator (31 tests)
M-AI-04-04: Projector + Artifact + 幂等写入 (19 tests)
M-AI-04-05: 入口集成 (Router + CreationService + Engine + Executor)
M-AI-04-06: 状态兼容 + 结构化日志 + 指标计数器 (255 tests)
M-AI-04-07: 真实业务 E2E + CI 触发 + FeatureFlag 受控切换 (11 tests)
P0 修复:
- 跨用户 question 所有权校验 (active-recall.service.ts)
- E2E infra 不可用时 HARD FAIL (fail() 替代静默 skip)
添加文件:
- docs/architecture/m-ai-04-active-recall-migration-contract.md
- 12 个 ai-job 模块文件 (Definition/Snapshot/Executor/Validator/Projector/Router/Observability)
- test/m-ai-04-active-recall.e2e-spec.ts + setup
修改文件:
- active-recall.service.ts, active-recall.module.ts
- ai-job-creation.service.ts, ai-job-execution-engine.ts, ai-job.module.ts
- .gitea/workflows/deploy.yml (CI 变更检测)
- test/jest-e2e.json (setupFiles + globals)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 14:55:33 +08:00
wangdl
bbac2e358c
fix: use useFactory returning array + Array.isArray guard for RESULT_PROJECTORS
...
Deploy API Server / build-and-unit (push) Successful in 35s
Deploy API Server / current-integration (push) Successful in 30s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / m-ai-03-synthetic-e2e (push) Failing after 10s
Deploy API Server / deploy (push) Has been skipped
Two changes to fix 'projectors is not iterable' TypeError:
1. ai-job.module.ts: Replace useClass+multi:true with useFactory that
explicitly returns [p] — avoids NestJS multi-provider array-wrapping
ambiguity. SyntheticResultProjector back as standalone provider.
2. projection-executor.service.ts: Replace truthiness check with
Array.isArray() guard for defense-in-depth.
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 12:16:40 +08:00
wangdl
5b0d105788
fix: use useClass instead of useFactory for RESULT_PROJECTORS multi-provider
...
Deploy API Server / build-and-unit (push) Successful in 34s
Deploy API Server / current-integration (push) Successful in 30s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / m-ai-03-synthetic-e2e (push) Failing after 11s
Deploy API Server / deploy (push) Has been skipped
The useFactory pattern returned the SyntheticResultProjector object directly
but NestJS multi-provider resolution didn't wrap it in an array, causing
'projectors is not iterable' in ProjectionExecutor. useClass is the standard
NestJS pattern for registering a class as a multi-provider element.
Also removed the redundant standalone SyntheticResultProjector provider
since useClass handles instantiation internally.
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 12:00:27 +08:00
wangdl
7f326b078a
fix: register SyntheticResultProjector in AiJobModule providers
...
Deploy API Server / build-and-unit (push) Successful in 34s
Deploy API Server / current-integration (push) Successful in 29s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / m-ai-03-synthetic-e2e (push) Failing after 9s
Deploy API Server / deploy (push) Has been skipped
RESULT_PROJECTORS factory injects SyntheticResultProjector but it wasn't
registered as a provider, causing NestJS DI resolution to fail at module
compilation. Added it to providers array — has zero dependencies, so just
needs registration.
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 11:56:50 +08:00
wangdl
2cf9579935
feat: M-AI-03 Synthetic Job Definition + 环境门控 + 测试
...
Deploy API Server / build-and-unit (push) Failing after 28s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- synthetic-job-definition.ts: SyntheticDefinition + isSyntheticEnabled() + assertNotProduction()
- synthetic-registration.service.ts: onModuleInit 条件注册(仅 test+SYNTHETIC_ENABLED)
- synthetic-job-definition.spec.ts: 13 测试(环境门控/Definition 合法性/Registry)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 10:11:16 +08:00
wangdl
c91a290536
feat: M-AI-03 Job 查询/取消/Admin/可观测性
...
Deploy API Server / build-and-unit (push) Failing after 28s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- AiJobController: GET /api/ai/jobs/:jobId, POST /cancel(JWT 用户隔离)
- 公开响应不含 validatedOutput/internalErrorMessage/Snapshot/Credential
- 终态取消幂等返回
- AiJobAdminController: Admin 列表/详情/重试/队列状态/Outbox 状态
- 重试:创建新 Job + parentJobId + 复制 Snapshot + OutboxEvent
- AiJobService: 用户/Admin 共享业务逻辑
- WorkerHeartbeat: activeJobCount 改为真实活跃数(ai-interactive + ai-background)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 10:08:57 +08:00
wangdl
4cfcb7afe5
feat: M-AI-03 Result Projector 与 Artifact 原子提交框架
...
Deploy API Server / build-and-unit (push) Failing after 29s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- result-projector.interface.ts: ResultProjector 接口冻结(ADR-003 §6.1)
project(tx, context) → ArtifactReference[]
- synthetic-result-projector.ts: 测试用 Synthetic Projector
幂等:已有 Artifact 时直接返回
- projection-executor.service.ts: ProjectionExecutor
事务内:projector.project(tx) + markSucceeded(tx) 原子提交
幂等检查:Job 已终态 → 跳过
NestJS multi-provider 注入 RESULT_PROJECTORS
- ai-job-execution-engine.ts: PROJECT 阶段改为调用 ProjectionExecutor
- ai-job.module.ts: 注册 ProjectionExecutor + SyntheticResultProjector
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-21 09:49:25 +08:00
wangdl
d82ae8ba71
feat: M-AI-03 统一 AiJob Worker Execution Engine
...
Deploy API Server / build-and-unit (push) Failing after 29s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- AiJobExecutionEngineImpl: 完整 5 阶段管线
PREPARE: read Job → terminal check → cancel check → Registry.get → CAS lockJob
RESOLVE: load Snapshot → schemaVersion check → AbortController timeout
EXECUTE: AiGatewayService.generate() (不直接导入 Provider SDK)
PROJECT: write validatedOutput + outputHash (#292 替换为 Projector)
COMPLETE: usageLog → markSucceeded
- 错误分类: classifyError() — 7 种错误码, retryable/permanent 分流
provider_rate_limited/timeout/unavailable → retryable → 抛给 BullMQ
schema/business/reference validation → permanent → markFailed
cancelled → markCancelled (3 个检查点: 执行前/Provider前/Projector前)
- Usage logging: 每次 Provider 调用写 AiUsageLog (jobId/attemptNo/credentialMode/token)
- AiJobModule: 使用 AI_JOB_EXECUTION_ENGINE token 注册,替换 #288 的 no-op
- 10 个单元测试: 全链路成功/终态跳过/取消(2)/错误分类(3)/锁冲突/Schema不兼容/UsageLog
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 18:30:02 +08:00
wangdl
6668bba9b4
feat: M-AI-03 Outbox Dispatcher — 可靠投递 ai.job.enqueue 到 BullMQ
...
Deploy API Server / build-and-unit (push) Failing after 29s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- OutboxDispatcher: 每 5s 轮询 OutboxEvent 表,CAS 领取 → 验证 → BullMQ 投递 → 标记 published
- 采用 ADR-003 §4.3 先 CAS 后投递算法:markProcessing(CAS) → queue.add() → markPublished
- BullMQ jobId = AiJob.id(幂等重复 add)
- 崩溃窗口保护:bullmq jobId 幂等 + releaseExpiredLocks(60s)
- 错误处理:永久失败(未知eventType/Job不存在/非法queueName/超过最大尝试)
vs 暂时失败(exponential backoff 回退 pending)
- 仅在 WorkerModule 注册(API 进程不运行 Dispatcher)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 18:20:22 +08:00
wangdl
f0183c03c4
feat: M-AI-03 事务化 AiJob 创建、Snapshot 与 Enqueue Outbox
...
Deploy API Server / build-and-unit (push) Failing after 30s
Deploy API Server / current-integration (push) Has been skipped
Deploy API Server / backward-compat (push) Has been skipped
Deploy API Server / deploy (push) Has been skipped
- AiJobCreationService: 在一个 Prisma Transaction 内原子创建 Job+Snapshot+Outbox
- 幂等性: (userId, jobType, idempotencyKey) UNIQUE 约束防重复
- Job 元数据从 JobDefinition 写入 (queueName/priority/maxAttempts/timeoutMs 等)
- overrides 支持覆盖 priority/credentialMode/credentialId
- Outbox payload 仅含 {jobId},不含 userId/credentialId/snapshot
- 依赖 SnapshotBuilderService + OutboxRepository,AiJobModule 导入 AiRuntimeModule
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 18:13:15 +08:00
wangdl
e4b922e7e4
feat: M-AI-03 Job Definition Registry 与注册校验
...
Deploy API Server / build-and-unit (push) Successful in 32s
Deploy API Server / current-integration (push) Successful in 28s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / deploy (push) Successful in 58s
- JobDefinition 接口冻结(job-definition.types.ts):对齐 ADR-003 §2.1,
涵盖 queue/execution/input/output/prompt/model/credential/security
- JobDefinitionRegistry:启动时注册、运行时只读、Object.freeze 防篡改
- 10 类校验错误:DuplicateJobType/UnknownJobType/InvalidJobType/
InvalidQueueName/MissingSchema/InvalidTimeout/InvalidRetries/
InvalidCredentialMode/InvalidPromptKey/MissingBackoff
- 43 个单元测试覆盖所有校验路径 + 顺序稳定性 + 禁止覆盖
- 更新 AiJobModule 注册新 Provider
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 17:24:57 +08:00
wangdl
b08d27a449
feat: M-AI-03 AiJob 状态机与原子状态仓储
...
Deploy API Server / build-and-unit (push) Successful in 33s
Deploy API Server / current-integration (push) Successful in 29s
Deploy API Server / backward-compat (push) Successful in 0s
Deploy API Server / deploy (push) Successful in 1m4s
- AiJobStateMachine: 5 状态(queued/running/succeeded/failed/cancelled)、
合法/非法迁移验证、终态判断、双向 Shadow Write 映射
- AiJobLifecycleRepository: 唯一 lifecycleStatus 写入入口、
CAS(条件 UPDATE WHERE lifecycleStatus IN (...))抢锁/续锁/标记成功/失败/取消、
可选 tx 参数支持 Projector 事务内调用
- requestCancellation: queued 直接取消 → cancelled、
running 设置 cancelRequestedAt 信号
- 6 个类型化错误(JobLockConflict/JobNotActive/JobAlreadyTerminal/
JobNotCancellable/JobExtendLock/IllegalStateTransition)
- 41 个单元测试全部通过
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 17:17:12 +08:00