filegrc 0.11.0 → 0.12.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/src/index.js CHANGED
@@ -7,6 +7,7 @@ export {
7
7
  SUPPORTED_MODEL_VERSIONS
8
8
  } from "../model/index.js";
9
9
  export { buildAgentGuide, findResourceReferences, listResourceTypes, scaffoldResourceMutation } from "./agent.js";
10
+ export { saveAuditPopulation, scaffoldAuditPopulationCorrection } from "./audit-populations.js";
10
11
  export { assessAuditDocumentActivations, assessAuditPreparation, prepareAuditWorkspace } from "./audit-preparation.js";
11
12
  export { createNextAuditCycle, planNextAuditCycle } from "./audit-transition.js";
12
13
  export {
@@ -73,8 +74,12 @@ export {
73
74
  completeObligationEvent,
74
75
  completeObligationOccurrence,
75
76
  createObligationEvent,
77
+ activateObligationRule,
76
78
  planObligations,
77
- scaffoldObligationCompletion
79
+ saveObligationOccurrence,
80
+ scaffoldObligationCompletion,
81
+ scaffoldObligationOccurrence,
82
+ scaffoldObligationRuleActivation
78
83
  } from "./obligations.js";
79
84
  export {
80
85
  planExternalReviewerGovernance,
@@ -82,6 +87,17 @@ export {
82
87
  setupExternalReviewerGovernance
83
88
  } from "./external-reviewer.js";
84
89
  export { assessEvidenceMap, assessProgramReadiness } from "./program-readiness.js";
90
+ export {
91
+ approveReportingRouteSet,
92
+ assessReportingRoutePeriod,
93
+ assessReportingRouteSets,
94
+ cancelReportingRouteSet,
95
+ effectiveReportingRouteRequirements,
96
+ proposeReportingRouteSet,
97
+ reportingRouteLanesIndependent,
98
+ scaffoldReportingRouteSet
99
+ } from "./reporting-route-sets.js";
100
+ export { reportingRouteBindingExpectation } from "./reporting-route-integrity.js";
85
101
  export { planProgramAmendment } from "./program-amendment.js";
86
102
  export {
87
103
  buildAgentProgramPath,
@@ -896,10 +896,12 @@ export async function planModelMigration(input = process.cwd(), options = {}) {
896
896
  : sourceVersion === "1" ? V1_TARGET_MODEL_VERSION
897
897
  : sourceVersion === "2" ? "3"
898
898
  : sourceVersion === "3" ? "4"
899
- : sourceVersion === "4" ? "5"
900
- : sourceVersion === "5" ? "6"
901
- : sourceVersion === "6" ? "7"
902
- : ACTIVE_MODEL_VERSION;
899
+ : sourceVersion === "4" ? "5"
900
+ : sourceVersion === "5" ? "6"
901
+ : sourceVersion === "6" ? "7"
902
+ : sourceVersion === "7" ? "8"
903
+ : sourceVersion === "8" ? "9"
904
+ : ACTIVE_MODEL_VERSION;
903
905
  if (sourceVersion === requestedTarget) return emptyPlan(sourceVersion, requestedTarget);
904
906
  if (sourceVersion === "1" && requestedTarget === "2") {
905
907
  return planV1ToV2Migration(input, options);
@@ -919,9 +921,15 @@ export async function planModelMigration(input = process.cwd(), options = {}) {
919
921
  if (sourceVersion === "6" && requestedTarget === "7") {
920
922
  return planV6ToV7Migration(loaded);
921
923
  }
922
- if (sourceVersion === "7" && requestedTarget === ACTIVE_MODEL_VERSION) {
924
+ if (sourceVersion === "7" && requestedTarget === "8") {
923
925
  return planV7ToV8Migration(loaded);
924
926
  }
927
+ if (sourceVersion === "8" && requestedTarget === "9") {
928
+ return planV8ToV9Migration(loaded);
929
+ }
930
+ if (sourceVersion === "9" && requestedTarget === ACTIVE_MODEL_VERSION) {
931
+ return planV9ToV10Migration(loaded);
932
+ }
925
933
  if (sourceVersion === "1" && requestedTarget === ACTIVE_MODEL_VERSION) {
926
934
  throw new Error(
927
935
  "Model v1 workspaces must migrate to model v2 first. "
@@ -2190,6 +2198,214 @@ async function planV7ToV8Migration(loaded) {
2190
2198
  };
2191
2199
  }
2192
2200
 
2201
+ async function planV8ToV9Migration(loaded) {
2202
+ if (!loaded.workspace?.id) throw new Error("Model migration requires a valid Workspace record.");
2203
+ const targetModel = loadModel("9");
2204
+ const revisions = new Map(loaded.entries.map((entry) => [entry.record.id, contentRevision(entry.source)]));
2205
+ const automatic = [];
2206
+ const reviewRequired = [];
2207
+ const unsupported = [];
2208
+ const missing = [];
2209
+ const manualActions = [];
2210
+ const updates = [];
2211
+
2212
+ for (const original of loaded.resources) {
2213
+ const record = structuredClone(original);
2214
+ let changed = false;
2215
+ if (original.type === "workspace") {
2216
+ record.dataModelVersion = "9";
2217
+ changed = true;
2218
+ automatic.push(classifiedChange("automatic", original.id, "dataModelVersion", "Select model v9."));
2219
+ }
2220
+ if (original.type === "obligation" && !original.scheduleMode) {
2221
+ record.scheduleMode = "legacy";
2222
+ changed = true;
2223
+ automatic.push(classifiedChange(
2224
+ "automatic",
2225
+ original.id,
2226
+ "scheduleMode",
2227
+ "Keep the existing schedule in legacy mode until management reviews and activates an Obligation rule."
2228
+ ));
2229
+ reviewRequired.push(classifiedChange(
2230
+ "review-required",
2231
+ original.id,
2232
+ "ruleIds",
2233
+ "Review the reusable schedule and population rule before adopting rolled-up occurrence reconciliation."
2234
+ ));
2235
+ }
2236
+ if (original.type === "obligation-event" && Object.hasOwn(original, "transitionFingerprint")) {
2237
+ delete record.transitionFingerprint;
2238
+ changed = true;
2239
+ automatic.push(classifiedChange(
2240
+ "automatic",
2241
+ original.id,
2242
+ "transitionFingerprint",
2243
+ "Remove the obsolete reconciliation fingerprint. Git history preserves the original transition binding."
2244
+ ));
2245
+ }
2246
+ if (original.type === "collection-review" && original.status === "active" && !original.knowledgeCutoffAt) {
2247
+ reviewRequired.push(classifiedChange(
2248
+ "review-required",
2249
+ original.id,
2250
+ "knowledgeCutoffAt",
2251
+ "Record a new Collection Review against a clean Git revision before using it for historical population proof."
2252
+ ));
2253
+ }
2254
+ if (changed) updates.push(record);
2255
+ }
2256
+
2257
+ const updatedById = new Map(updates.map((record) => [record.id, record]));
2258
+ const migratedRecords = loaded.resources.map((record) => updatedById.get(record.id) || record);
2259
+ await collectTargetValidationActions(loaded, migratedRecords, targetModel, missing, manualActions);
2260
+ for (const item of [...missing, ...manualActions]) {
2261
+ unsupported.push(classifiedChange(
2262
+ "unsupported",
2263
+ item.resourceId,
2264
+ item.field,
2265
+ item.message || `Resolve ${item.field} before applying the model v9 migration.`
2266
+ ));
2267
+ }
2268
+ const ready = unsupported.length === 0;
2269
+ return {
2270
+ schemaVersion: 2,
2271
+ sourceModelVersion: "8",
2272
+ targetModelVersion: "9",
2273
+ ready,
2274
+ missing,
2275
+ conflicts: [],
2276
+ manualActions,
2277
+ classifications: { automatic, reviewRequired, unsupported },
2278
+ notes: [
2279
+ "Existing Obligation schedules remain in legacy mode until management activates reviewed rule revisions.",
2280
+ "Existing Collection Reviews remain records, but only new Git-bound reviews can prove a historical population."
2281
+ ],
2282
+ migrationReport: {},
2283
+ summary: {
2284
+ create: 0,
2285
+ update: updates.length,
2286
+ automatic: automatic.length,
2287
+ reviewRequired: reviewRequired.length,
2288
+ unsupported: unsupported.length
2289
+ },
2290
+ fileDiff: {
2291
+ create: [],
2292
+ update: updates.map((record) => ({
2293
+ type: record.type,
2294
+ id: record.id,
2295
+ before: loaded.resources.find(({ id }) => id === record.id),
2296
+ after: record
2297
+ }))
2298
+ },
2299
+ changes: {
2300
+ create: [],
2301
+ update: updates,
2302
+ expectedRevisions: Object.fromEntries(updates.map(({ id }) => [id, revisions.get(id)])),
2303
+ validateWholeWorkspace: true,
2304
+ targetModelVersion: "9"
2305
+ }
2306
+ };
2307
+ }
2308
+
2309
+ async function planV9ToV10Migration(loaded) {
2310
+ if (!loaded.workspace?.id) throw new Error("Model migration requires a valid Workspace record.");
2311
+ const targetModel = loadModel("10");
2312
+ const revisions = new Map(loaded.entries.map((entry) => [entry.record.id, contentRevision(entry.source)]));
2313
+ const automatic = [];
2314
+ const reviewRequired = [];
2315
+ const unsupported = [];
2316
+ const missing = [];
2317
+ const manualActions = [];
2318
+ const updates = [];
2319
+
2320
+ for (const original of loaded.resources) {
2321
+ const record = structuredClone(original);
2322
+ let changed = false;
2323
+ if (record.type === "workspace") {
2324
+ record.dataModelVersion = "10";
2325
+ automatic.push(classifiedChange("automatic", record.id, "dataModelVersion", "Select model v10."));
2326
+ changed = true;
2327
+ }
2328
+ if (record.type === "reporting-route") {
2329
+ if (record.status === "planned") {
2330
+ record.status = "deprecated-draft";
2331
+ automatic.push(classifiedChange(
2332
+ "automatic",
2333
+ record.id,
2334
+ "status",
2335
+ "Mark this unfinished model v9 route as a deprecated draft."
2336
+ ));
2337
+ changed = true;
2338
+ }
2339
+ reviewRequired.push(classifiedChange(
2340
+ "review-required",
2341
+ record.id,
2342
+ "reporting-route-set",
2343
+ "Scaffold one Reporting Route Set for the Program and purpose. Confirm the Program, paired lanes, approval authority, actual event time, timezone, and any structured source requirements instead of inferring them."
2344
+ ));
2345
+ }
2346
+ if (record.type === "attestation" && (record.reportingRouteId || record.reportingRouteRevision)) {
2347
+ reviewRequired.push(classifiedChange(
2348
+ "review-required",
2349
+ record.id,
2350
+ "reportingRouteSetId",
2351
+ "The preserved legacy scalar route binding cannot prove a Route Set revision. Keep the historical Attestation unchanged, and use a committed Route Set binding for future delivery proof."
2352
+ ));
2353
+ }
2354
+ if (changed) updates.push(record);
2355
+ }
2356
+
2357
+ const updatedById = new Map(updates.map((record) => [record.id, record]));
2358
+ const migratedRecords = loaded.resources.map((record) => updatedById.get(record.id) || record);
2359
+ await collectTargetValidationActions(loaded, migratedRecords, targetModel, missing, manualActions);
2360
+ for (const item of [...missing, ...manualActions]) {
2361
+ unsupported.push(classifiedChange(
2362
+ "unsupported",
2363
+ item.resourceId,
2364
+ item.field,
2365
+ item.message || `Resolve ${item.field} before applying the model v10 migration.`
2366
+ ));
2367
+ }
2368
+ return {
2369
+ schemaVersion: 2,
2370
+ sourceModelVersion: "9",
2371
+ targetModelVersion: "10",
2372
+ ready: unsupported.length === 0,
2373
+ missing,
2374
+ conflicts: [],
2375
+ manualActions,
2376
+ classifications: { automatic, reviewRequired, unsupported },
2377
+ notes: [
2378
+ "Legacy Reporting Routes remain visible as migration-only records and cannot become effective Route Sets.",
2379
+ "The migration does not infer a Program, purpose lineage, paired lane, authority, approval time, timezone, or evidence judgment.",
2380
+ "Use the Route Set scaffold and a reviewed Git diff to create current facts."
2381
+ ],
2382
+ migrationReport: {},
2383
+ summary: {
2384
+ create: 0,
2385
+ update: updates.length,
2386
+ automatic: automatic.length,
2387
+ reviewRequired: reviewRequired.length,
2388
+ unsupported: unsupported.length
2389
+ },
2390
+ fileDiff: {
2391
+ create: [],
2392
+ update: updates.map((record) => ({
2393
+ type: record.type,
2394
+ id: record.id,
2395
+ before: loaded.resources.find(({ id }) => id === record.id),
2396
+ after: record
2397
+ }))
2398
+ },
2399
+ changes: {
2400
+ create: [],
2401
+ update: updates,
2402
+ expectedRevisions: Object.fromEntries(updates.map(({ id }) => [id, revisions.get(id)])),
2403
+ validateWholeWorkspace: true,
2404
+ targetModelVersion: "10"
2405
+ }
2406
+ };
2407
+ }
2408
+
2193
2409
  function normalizeDocumentScopeDecision(value) {
2194
2410
  const candidate = typeof value === "object" && value
2195
2411
  ? value.workflowScope || value.scope