@agentxm/extension-publish 0.28.4 → 0.28.5

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.
@@ -48,6 +48,8 @@ export interface PlannedZipArchive {
48
48
  readonly archive: Uint8Array;
49
49
  readonly plan: ArchivePlan;
50
50
  }
51
+ /** Whether one archive-relative path survives the declared publish boundary. */
52
+ export declare const isArchivePathIncluded: (archivePath: string, ignore?: ReadonlyArray<string>) => boolean;
51
53
  /**
52
54
  * Build a zip archive of a directory.
53
55
  * Files are stored at the root of the zip (no enclosing directory).
@@ -21,6 +21,8 @@ import { expandGlob } from "./internal/glob.js";
21
21
  // eslint-disable-next-line no-restricted-syntax -- ZIP's driver API requires Date; this fixed value never reads the ambient clock.
22
22
  const DETERMINISTIC_MTIME = new Date(2020, 0, 1, 0, 0, 0, 0);
23
23
  const READ_CONCURRENCY = 16;
24
+ /** Whether one archive-relative path survives the declared publish boundary. */
25
+ export const isArchivePathIncluded = (archivePath, ignore = []) => ignore.every((pattern) => expandGlob(pattern, [archivePath]).length === 0);
24
26
  /**
25
27
  * Build a zip archive of a directory.
26
28
  * Files are stored at the root of the zip (no enclosing directory).
@@ -12,7 +12,8 @@ export { PublishFailed } from "./errors.js";
12
12
  export { PUBLISHABLE_TYPES, isPublishableType, type PublishableType } from "./publishable-types.js";
13
13
  export { runPublishLintGate, type PublishLintArgs } from "./lint-gate.js";
14
14
  export { PublishIgnoreError, protectedPublishPaths, publishArchiveOptions, resolvePublishIgnore, } from "./publish-ignore.js";
15
- export { buildZipArchive, planZipArchive, type ArchivePlan, type ArchivePlanFile, type ArchivePlanPattern, type BuildZipArchiveOptions, type PlannedZipArchive, } from "./archive.js";
15
+ export { buildZipArchive, isArchivePathIncluded, planZipArchive, type ArchivePlan, type ArchivePlanFile, type ArchivePlanPattern, type BuildZipArchiveOptions, type PlannedZipArchive, } from "./archive.js";
16
+ export { assessPublishSourceState, publishSourceRiskCondition, type PublishSourceAssessment, type PublishSourceDifference, type PublishSourceState, } from "./source-state.js";
16
17
  export { settlePublish, type PublishSettlement, type PublishSettlementFailure, type SettledPublish, } from "./settlement.js";
17
18
  export { exactPublishUploadBinding, previewPublishUploadBinding, publishAuthenticationPreconditions, type PublishGrant, type ResolvedPublishPreview, } from "./authorization.js";
18
19
  export { buildPublishJobs, type PublishPlanCandidate } from "./jobs.js";
package/dist/src/index.js CHANGED
@@ -12,7 +12,8 @@ export { PublishFailed } from "./errors.js";
12
12
  export { PUBLISHABLE_TYPES, isPublishableType } from "./publishable-types.js";
13
13
  export { runPublishLintGate } from "./lint-gate.js";
14
14
  export { PublishIgnoreError, protectedPublishPaths, publishArchiveOptions, resolvePublishIgnore, } from "./publish-ignore.js";
15
- export { buildZipArchive, planZipArchive, } from "./archive.js";
15
+ export { buildZipArchive, isArchivePathIncluded, planZipArchive, } from "./archive.js";
16
+ export { assessPublishSourceState, publishSourceRiskCondition, } from "./source-state.js";
16
17
  export { settlePublish, } from "./settlement.js";
17
18
  export { exactPublishUploadBinding, previewPublishUploadBinding, publishAuthenticationPreconditions, } from "./authorization.js";
18
19
  export { buildPublishJobs } from "./jobs.js";
@@ -0,0 +1,31 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { GitDirectoryComparison, type GitOperationFailed } from "@agentxm/extension-sources";
3
+ import type { PlanRiskCondition } from "@agentxm/workspace-operations";
4
+ import type { ArchivePlan } from "./archive.js";
5
+ export interface PublishSourceDifference {
6
+ readonly path: string;
7
+ readonly change: "added" | "modified" | "deleted";
8
+ }
9
+ export interface PublishSourceState {
10
+ readonly basis: "git-head";
11
+ readonly status: "matches-head" | "differs-from-head" | "no-head";
12
+ readonly revision?: string;
13
+ readonly directory: string;
14
+ readonly differences: ReadonlyArray<PublishSourceDifference>;
15
+ readonly differenceCount: number;
16
+ readonly truncated: boolean;
17
+ }
18
+ export interface PublishSourceAssessment {
19
+ /** Complete identity used to reject source evidence that changed after planning. */
20
+ readonly fingerprint: string;
21
+ /** Omitted when the package is not contained in a Git worktree. */
22
+ readonly state?: PublishSourceState;
23
+ }
24
+ /** Assess only source differences that can change the filtered Registry archive. */
25
+ export declare const assessPublishSourceState: (args: {
26
+ readonly directory: string;
27
+ readonly archivePlan: ArchivePlan;
28
+ readonly ignore?: ReadonlyArray<string>;
29
+ }) => Effect.Effect<PublishSourceAssessment, GitOperationFailed, GitDirectoryComparison>;
30
+ export declare const publishSourceRiskCondition: (fqn: string, state: PublishSourceState | undefined) => PlanRiskCondition | undefined;
31
+ //# sourceMappingURL=source-state.d.ts.map
@@ -0,0 +1,58 @@
1
+ import * as crypto from "node:crypto";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Option from "effect/Option";
4
+ import { GitDirectoryComparison, } from "@agentxm/extension-sources";
5
+ import { isArchivePathIncluded } from "./archive.js";
6
+ const PUBLIC_DIFFERENCE_LIMIT = 50;
7
+ const sourceFingerprint = (value) => crypto.createHash("sha256").update(JSON.stringify(value)).digest("hex");
8
+ const publicDifferences = (differences) => differences.slice(0, PUBLIC_DIFFERENCE_LIMIT).map(({ path, change }) => ({ path, change }));
9
+ /** Assess only source differences that can change the filtered Registry archive. */
10
+ export const assessPublishSourceState = (args) => Effect.gen(function* () {
11
+ const git = yield* GitDirectoryComparison;
12
+ const currentPaths = [...args.archivePlan.included, ...args.archivePlan.excluded]
13
+ .map(({ path }) => path)
14
+ .sort((left, right) => left.localeCompare(right));
15
+ const comparison = yield* git.compare({ directory: args.directory, currentPaths });
16
+ if (Option.isNone(comparison)) {
17
+ return { fingerprint: sourceFingerprint({ status: "outside-git" }) };
18
+ }
19
+ const materialDifferences = comparison.value.differences.filter(({ path }) => isArchivePathIncluded(path, args.ignore));
20
+ const status = comparison.value.headRevision === undefined
21
+ ? "no-head"
22
+ : materialDifferences.length === 0
23
+ ? "matches-head"
24
+ : "differs-from-head";
25
+ const state = {
26
+ basis: "git-head",
27
+ status,
28
+ ...(comparison.value.headRevision === undefined
29
+ ? {}
30
+ : { revision: comparison.value.headRevision }),
31
+ directory: comparison.value.repositoryDirectory,
32
+ differences: publicDifferences(materialDifferences),
33
+ differenceCount: materialDifferences.length,
34
+ truncated: materialDifferences.length > PUBLIC_DIFFERENCE_LIMIT,
35
+ };
36
+ return {
37
+ state,
38
+ fingerprint: sourceFingerprint({
39
+ state,
40
+ differences: materialDifferences,
41
+ }),
42
+ };
43
+ });
44
+ export const publishSourceRiskCondition = (fqn, state) => {
45
+ if (state === undefined || state.status === "matches-head")
46
+ return undefined;
47
+ const detail = state.status === "no-head"
48
+ ? `${fqn} is inside a Git worktree with no HEAD commit.`
49
+ : `${fqn} has ${state.differenceCount} Registry archive ${state.differenceCount === 1 ? "path" : "paths"} not represented by Git HEAD ${state.revision ?? "unknown"}.`;
50
+ return {
51
+ level: "override-required",
52
+ id: `publish/archive-not-at-head:${fqn}`,
53
+ policy: "accept-warnings",
54
+ requiredFlag: "--accept-warnings",
55
+ detail,
56
+ };
57
+ };
58
+ //# sourceMappingURL=source-state.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentxm/extension-publish",
3
- "version": "0.28.4",
3
+ "version": "0.28.5",
4
4
  "description": "AXM extension-publish feature: publish selection policy, publication validation, archive planning, authentication requirements, upload settlement, and recovery for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-MIT",
@@ -18,6 +18,7 @@
18
18
  "exports": {
19
19
  ".": {
20
20
  "types": "./dist/src/index.d.ts",
21
+ "axm-source": "./src/index.ts",
21
22
  "default": "./dist/src/index.js"
22
23
  }
23
24
  },
@@ -37,11 +38,12 @@
37
38
  "dependencies": {
38
39
  "effect": "4.0.0-rc.112",
39
40
  "fflate": "^0.8.3",
40
- "@agentxm/extension-model": "^0.28.4",
41
- "@agentxm/registry-client": "^0.28.4",
42
- "@agentxm/extension-workspace": "^0.28.4",
43
- "@agentxm/registry-protocol": "^0.28.4",
44
- "@agentxm/workspace-operations": "^0.28.4"
41
+ "@agentxm/extension-sources": "^0.28.5",
42
+ "@agentxm/extension-model": "^0.28.5",
43
+ "@agentxm/registry-protocol": "^0.28.5",
44
+ "@agentxm/registry-client": "^0.28.5",
45
+ "@agentxm/workspace-operations": "^0.28.5",
46
+ "@agentxm/extension-workspace": "^0.28.5"
45
47
  },
46
48
  "devDependencies": {
47
49
  "@effect/platform-node": "4.0.0-rc.112",