filegrc 0.16.21 → 0.16.22

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": "filegrc",
3
- "version": "0.16.21",
3
+ "version": "0.16.22",
4
4
  "description": "Zero-dependency Git-native GRC engine",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/retention.js CHANGED
@@ -170,7 +170,7 @@ export async function resourceReviewRevisions(loaded, ids, scopeHashInput = "leg
170
170
  const decisionHeading = heading || retentionPolicyHeading(loaded, entry, reviewer);
171
171
  const parts = [reviewSource(loaded, entry, scopeHashInput, false, decisionHeading, reviewer)];
172
172
  let matchedSection = !decisionHeading;
173
- for (const markdown of reviewMarkdownEntries(loaded, entry, false)) {
173
+ for (const markdown of reviewMarkdownEntries(loaded, entry, false, reviewer)) {
174
174
  try {
175
175
  const source = entry.reviewCommit
176
176
  ? entry.reviewFiles?.get(`data/${markdown.path}`)
@@ -218,7 +218,7 @@ export function resourceReviewRevisionsSync(loaded, ids, scopeHashInput = "legac
218
218
  const decisionHeading = legacySource ? heading : heading || retentionPolicyHeading(loaded, entry, reviewer);
219
219
  const parts = [reviewSource(loaded, entry, scopeHashInput, legacySource, decisionHeading, reviewer)];
220
220
  let matchedSection = !decisionHeading;
221
- for (const markdown of reviewMarkdownEntries(loaded, entry, legacySource)) {
221
+ for (const markdown of reviewMarkdownEntries(loaded, entry, legacySource, reviewer)) {
222
222
  try {
223
223
  const source = (historicalCommit || entry.reviewCommit)
224
224
  ? loaded.historicalFiles?.get(`data/${markdown.path}`)
@@ -370,11 +370,16 @@ function reviewSource(loaded, entry, scopeHashInput = "legacy", legacySource = f
370
370
  )), scopeHashInput);
371
371
  }
372
372
 
373
- function reviewMarkdownEntries(loaded, entry, legacySource) {
373
+ function reviewMarkdownEntries(loaded, entry, legacySource, reviewer = null) {
374
374
  // Control Markdown records the implementation procedure. Retention and
375
375
  // mapping decisions depend on the structured Control design instead.
376
376
  if (!legacySource && modelSupports(loaded.model, "retention-schedule-approval")
377
377
  && entry.record.type === "control") return [];
378
+ // A Component's Markdown explains how to retrieve evidence. Retention
379
+ // decisions depend on its information uses and scope, not those steps.
380
+ // Keep the Markdown in legacy hashes so committed approvals can be found.
381
+ if (!legacySource && reviewer?.type === "retention-schedule-item"
382
+ && entry.record.type === "component") return [];
378
383
  return markdownEntries(loaded.model, entry.record);
379
384
  }
380
385
 
package/src/workflow.js CHANGED
@@ -1,6 +1,6 @@
1
- import { cp, mkdtemp, rm } from "node:fs/promises";
1
+ import { cp, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
- import { join } from "node:path";
3
+ import { join, relative } from "node:path";
4
4
  import { modelSupports } from "../model/index.js";
5
5
  import { buildActionContext } from "./action-context.js";
6
6
  import { applicabilityReviewIsCurrent, applicabilityScopeRevision } from "./applicability-scope.js";
@@ -14,7 +14,7 @@ import {
14
14
  deleteResource,
15
15
  updateResource
16
16
  } from "./files.js";
17
- import { getGitSummary, getWorkspaceHistories } from "./git.js";
17
+ import { getGitSummary, getWorkspaceHistories, runGitCommandSync } from "./git.js";
18
18
  import {
19
19
  completeObligationAction,
20
20
  completeObligationEvent,
@@ -260,13 +260,39 @@ function contextualAction(item, loaded) {
260
260
 
261
261
  export async function previewWorkflowMutation(input, mutation) {
262
262
  const loaded = await loadWorkspace(input);
263
- const previewRoot = await mkdtemp(join(tmpdir(), "filegrc-workflow-preview-"));
263
+ const previewCheckout = await mkdtemp(join(tmpdir(), "filegrc-workflow-preview-"));
264
264
  try {
265
+ const repository = getGitSummary(loaded.root);
266
+ if (repository.available) {
267
+ // Legacy review bindings need committed source versions. A local clone
268
+ // gives preview the same history as update without touching the source.
269
+ runGitCommandSync(loaded.root, ["clone", "--shared", "--no-checkout", "--quiet", repository.root, previewCheckout], {
270
+ timeoutMs: 30_000
271
+ });
272
+ }
273
+ const previewRoot = repository.available
274
+ ? join(previewCheckout, relative(repository.root, loaded.root))
275
+ : previewCheckout;
276
+ await mkdir(previewRoot, { recursive: true });
277
+ if (repository.commit) {
278
+ // Restore the index and tracked workspace files. A no-checkout clone
279
+ // otherwise reports every source file as deleted and copied data as new.
280
+ runGitCommandSync(loaded.root, ["-C", previewCheckout, "reset", "--mixed", "HEAD"]);
281
+ if (runGitCommandSync(loaded.root, ["-C", previewRoot, "ls-files", "--", "."])) {
282
+ runGitCommandSync(loaded.root, ["-C", previewRoot, "restore", "--worktree", "--", "."]);
283
+ }
284
+ }
285
+ await rm(join(previewRoot, "data"), { recursive: true, force: true });
265
286
  await cp(join(loaded.root, "data"), join(previewRoot, "data"), {
266
287
  recursive: true,
267
288
  errorOnExist: true,
268
289
  force: false
269
290
  });
291
+ if (repository.available && !repository.clean && getGitSummary(previewRoot).clean) {
292
+ const marker = join(previewRoot, "preview-source-dirty.marker");
293
+ await writeFile(marker, "The source workspace has uncommitted files.\n");
294
+ runGitCommandSync(loaded.root, ["-C", previewRoot, "add", "-N", "-f", "--", "preview-source-dirty.marker"]);
295
+ }
270
296
  const before = await assessWorkflow(loaded.root, mutation?.assessment || {});
271
297
  const record = mutation?.record;
272
298
  const existing = record?.id
@@ -307,7 +333,7 @@ export async function previewWorkflowMutation(input, mutation) {
307
333
  workflow: after
308
334
  };
309
335
  } finally {
310
- await rm(previewRoot, { recursive: true, force: true });
336
+ await rm(previewCheckout, { recursive: true, force: true });
311
337
  }
312
338
  }
313
339