@guanlin4924/devflow-pi 0.1.72 → 0.1.73

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanlin4924/devflow-pi",
3
- "version": "0.1.72",
3
+ "version": "0.1.73",
4
4
  "type": "module",
5
5
  "description": "Devflow 专项研发 Pi,基于固定版本 OMP Runtime 组装研发状态机、代码智能、设计、实现与质量门禁。",
6
6
  "license": "UNLICENSED",
package/src/constants.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export const PRODUCT_NAME = "Devflow Pi";
2
- export const PRODUCT_VERSION = "0.1.72";
2
+ export const PRODUCT_VERSION = "0.1.73";
3
3
  export const PROJECT_SCHEMA_VERSION = 1;
4
4
  export const OMP_RUNTIME_VERSION = "17.2.7";
5
5
 
@@ -402,11 +402,21 @@ export class InitializationStore {
402
402
  this.assertWritableRun(runId, leaseToken);
403
403
  const transaction = this.db.transaction(() => {
404
404
  const repository = input.repository ?? "";
405
- this.db.query("DELETE FROM evidence WHERE fact_id IN (SELECT id FROM facts WHERE run_id=? AND repository=? AND kind=?)").run(runId, repository, input.kind);
406
- this.db.query("DELETE FROM facts WHERE run_id=? AND repository=? AND kind=?").run(runId, repository, input.kind);
405
+ if (repository) {
406
+ this.db.query("DELETE FROM evidence WHERE fact_id IN (SELECT id FROM facts WHERE run_id=? AND repository=? AND kind=?)").run(runId, repository, input.kind);
407
+ this.db.query("DELETE FROM facts WHERE run_id=? AND repository=? AND kind=?").run(runId, repository, input.kind);
408
+ } else {
409
+ this.db.query("DELETE FROM evidence WHERE fact_id IN (SELECT id FROM facts WHERE run_id=? AND kind=?)").run(runId, input.kind);
410
+ this.db.query("DELETE FROM facts WHERE run_id=? AND kind=?").run(runId, input.kind);
411
+ }
407
412
  this.db.query("INSERT INTO collection_results(id,run_id,repository,kind,status,adapter,capability_json,diagnostics_json,created_at) VALUES (?,?,?,?,?,?,?,?,?) ON CONFLICT(run_id,repository,kind) DO UPDATE SET status=excluded.status,adapter=excluded.adapter,capability_json=excluded.capability_json,diagnostics_json=excluded.diagnostics_json,created_at=excluded.created_at").run(randomUUID(), runId, repository, input.kind, input.status, input.adapter, canonicalJson(input.capability ?? {}), canonicalJson(input.diagnostics ?? []), now());
408
- for (const fact of input.facts ?? []) {
413
+ const uniqueFacts = new Map<string, FactInput>();
414
+ for (const fact of input.facts ?? []) uniqueFacts.set(`${fact.repository ?? repository}\0${fact.objectKey}`, fact);
415
+ for (const fact of uniqueFacts.values()) {
409
416
  if (fact.kind !== input.kind) throw new Error(`Fact kind ${fact.kind} does not match collection ${input.kind}`);
417
+ if (repository && fact.repository !== undefined && fact.repository !== repository) {
418
+ throw new Error(`Fact repository ${fact.repository} does not match collection repository ${repository}`);
419
+ }
410
420
  if (!fact.objectKey || !fact.extractor) throw new Error("Facts require objectKey and extractor");
411
421
  if (fact.evidenceLevel === "observed" && !fact.sourcePath) throw new Error("Observed facts require source evidence");
412
422
  validateFactShape(fact);
@@ -165,6 +165,31 @@ function collect(files: SourceFile[], context: ProjectContext, config: ScanConfi
165
165
  facts.get("evidence")!.push({ kind: "evidence", repository: repository.name, objectKey: "input-policy", value: { source: "local-static", discoveredCommandsExecuted: false, gitMetadataRead: true, secretsStored: false }, evidenceLevel: "explicit_rule", extractor: "initializer@1", confidence: "exact" });
166
166
  facts.get("capability")!.push({ kind: "capability", repository: repository.name, objectKey: "collector:static@1", value: { supported: ["asset", "technology", "api", "page", "data_model", "integration", "rule", "toolchain"], limitations: ["static declarations only", "dynamic behavior unresolved", "no environment enablement inference"], project: context.manifest.name }, evidenceLevel: "explicit_rule", extractor: "initializer@1", confidence: "exact" });
167
167
  }
168
+ // A repository can declare the same route/model/page through more than one
169
+ // scanner (or declare it twice). The control-plane key is intentionally
170
+ // unique per run/kind/repository/object_key, so collapse duplicates before
171
+ // handing facts to the store while retaining the richest value/evidence.
172
+ for (const [kind, entries] of facts) {
173
+ const deduped = new Map<string, FactInput>();
174
+ for (const entry of entries) {
175
+ const key = `${entry.repository ?? ""}\0${entry.objectKey}`;
176
+ const previous = deduped.get(key);
177
+ if (!previous) {
178
+ deduped.set(key, entry);
179
+ continue;
180
+ }
181
+ deduped.set(key, {
182
+ ...previous,
183
+ ...entry,
184
+ repository: entry.repository ?? previous.repository,
185
+ value: { ...(previous.value ?? {}), ...(entry.value ?? {}) },
186
+ sourcePath: entry.sourcePath ?? previous.sourcePath,
187
+ sourceLine: entry.sourceLine ?? previous.sourceLine,
188
+ sourceFingerprint: entry.sourceFingerprint ?? previous.sourceFingerprint,
189
+ });
190
+ }
191
+ facts.set(kind, [...deduped.values()]);
192
+ }
168
193
  return facts;
169
194
  }
170
195