@codapult/guard 0.2.0 → 0.4.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.
@@ -1,33 +1,59 @@
1
- import type { ProjectModel } from './discovery/discovery.js';
2
- import { discoverProject, discoverProjectWithMetrics, findGuardRoot } from './discovery/discovery.js';
1
+ import { type ProjectModel } from './discovery/discovery.js';
2
+ import { clearDiscoveryCache, discoverProject, discoverProjectWithMetrics, findGuardRoot } from './discovery/discovery.js';
3
3
  import { type GuardImpactAnalysis } from './analysis/impact.js';
4
- export type GuardSeverity = 'error' | 'warning' | 'info';
4
+ import type { GuardAdapterName, GuardApprovalMode, GuardContractKind, GuardBudgetMetric, GuardRuleKind, GuardRuleStatus, GuardSeverity, GuardToolMode } from './model/types.js';
5
+ export type { GuardAdapterName, GuardApprovalMode, GuardContractKind, GuardBudgetMetric, GuardRuleKind, GuardRuleStatus, GuardSeverity, GuardToolMode, } from './model/types.js';
5
6
  export type GuardOutcomeStatus = 'pass' | 'fail' | 'warning' | 'needs-review' | 'not-configured';
6
- export declare function classifyGuardOutcome(input: {
7
- configured?: boolean;
8
- errors?: number;
9
- warnings?: number;
10
- needsReview?: boolean;
11
- }): GuardOutcomeStatus;
12
- export type GuardRuleKind = 'forbidden-import' | 'client-forbidden-import';
13
- export type GuardRuleStatus = 'active' | 'proposed';
14
- export type GuardContractKind = 'guidance' | 'import-boundary' | 'required-call';
7
+ export interface GuardOutcomeInput {
8
+ configured?: boolean | undefined;
9
+ errors?: number | undefined;
10
+ warnings?: number | undefined;
11
+ needsReview?: boolean | undefined;
12
+ }
13
+ interface GuardStateLockOptions {
14
+ waitMs?: number | undefined;
15
+ noWait?: boolean | undefined;
16
+ }
17
+ interface GuardBaselineUpdateOptions {
18
+ add?: string[] | undefined;
19
+ remove?: string[] | undefined;
20
+ reason?: string | undefined;
21
+ }
22
+ interface GuardConfigWriteOptions extends GuardStateLockOptions {
23
+ expectedRevision?: number | undefined;
24
+ }
25
+ interface GuardPendingProposal {
26
+ id: string;
27
+ type: 'rule' | 'contract';
28
+ }
29
+ export interface GuardSensitiveText {
30
+ value: string;
31
+ redacted: boolean;
32
+ redactionCount: number;
33
+ }
34
+ export interface GuardInitializationResult {
35
+ config: GuardConfig;
36
+ report: GuardReport;
37
+ }
38
+ export declare function classifyGuardOutcome(input: GuardOutcomeInput): GuardOutcomeStatus;
15
39
  export interface GuardContract {
16
40
  id: string;
17
41
  statement: string;
18
- kind?: GuardContractKind;
19
- severity?: GuardSeverity;
20
- scope?: string[];
21
- entrypoints?: string[];
22
- exclude?: string[];
23
- guidance?: string[];
24
- references?: string[];
25
- mustImport?: string[];
26
- mustNotImport?: string[];
27
- mustCall?: string[];
28
- status?: GuardRuleStatus;
29
- confidence?: 'high' | 'medium' | 'low';
30
- evidence?: string[];
42
+ kind?: GuardContractKind | undefined;
43
+ severity?: GuardSeverity | undefined;
44
+ scope?: string[] | undefined;
45
+ entrypoints?: string[] | undefined;
46
+ exclude?: string[] | undefined;
47
+ guidance?: string[] | undefined;
48
+ references?: string[] | undefined;
49
+ mustImport?: string[] | undefined;
50
+ mustNotImport?: string[] | undefined;
51
+ mustCall?: string[] | undefined;
52
+ fromPackages?: string[] | undefined;
53
+ mustNotImportPackages?: string[] | undefined;
54
+ status?: GuardRuleStatus | undefined;
55
+ confidence?: 'high' | 'medium' | 'low' | undefined;
56
+ evidence?: string[] | undefined;
31
57
  }
32
58
  export interface GuardRule {
33
59
  id: string;
@@ -35,36 +61,60 @@ export interface GuardRule {
35
61
  severity: GuardSeverity;
36
62
  kind: GuardRuleKind;
37
63
  patterns: string[];
38
- files?: string[];
39
- status?: GuardRuleStatus;
40
- confidence?: 'high' | 'medium' | 'low';
41
- evidence?: string[];
64
+ files?: string[] | undefined;
65
+ status?: GuardRuleStatus | undefined;
66
+ confidence?: 'high' | 'medium' | 'low' | undefined;
67
+ evidence?: string[] | undefined;
68
+ }
69
+ export interface GuardBudget {
70
+ id: string;
71
+ description: string;
72
+ metric: GuardBudgetMetric;
73
+ scope: string[];
74
+ limit: number;
75
+ severity: GuardSeverity;
76
+ reason: string;
77
+ status?: GuardRuleStatus | undefined;
78
+ evidence?: string[] | undefined;
42
79
  }
43
80
  export interface GuardConfig {
44
81
  version: 1;
82
+ revision?: number | undefined;
83
+ contentFingerprint?: string | undefined;
45
84
  rules: GuardRule[];
46
- contracts?: GuardContract[];
85
+ contracts?: GuardContract[] | undefined;
86
+ budgets?: GuardBudget[] | undefined;
87
+ approval?: GuardApprovalPolicy | undefined;
88
+ }
89
+ export interface GuardApprovalPolicy {
90
+ mode: GuardApprovalMode;
91
+ allowMcpApproval: boolean;
92
+ requireDistinctActor: boolean;
47
93
  }
48
94
  export interface GuardProposalFile {
49
95
  version: 1;
50
96
  generatedAt: string;
51
- proposalId?: string;
52
- projectFingerprint?: string;
53
- revision?: number;
54
- contentFingerprint?: string;
97
+ generatedBy?: string | undefined;
98
+ proposalId?: string | undefined;
99
+ projectFingerprint?: string | undefined;
100
+ revision?: number | undefined;
101
+ contentFingerprint?: string | undefined;
55
102
  rules: GuardRule[];
56
103
  contracts: GuardContract[];
57
104
  questions: string[];
58
- decisions?: GuardProposalDecision[];
105
+ decisions?: GuardProposalDecision[] | undefined;
59
106
  }
60
107
  export interface GuardProposalDecision {
61
108
  id: string;
62
109
  type: 'rule' | 'contract';
63
110
  decision: 'approved' | 'rejected';
64
111
  decidedAt: string;
65
- proposalId?: string;
66
- proposalFingerprint?: string;
67
- revision?: number;
112
+ proposalId?: string | undefined;
113
+ proposalFingerprint?: string | undefined;
114
+ revision?: number | undefined;
115
+ source?: 'cli' | 'mcp' | 'external' | undefined;
116
+ actor?: string | undefined;
117
+ commit?: string | undefined;
68
118
  }
69
119
  export type GuardProposalFreshness = 'current' | 'stale' | 'unknown';
70
120
  export interface GuardAgentConfig {
@@ -81,25 +131,24 @@ export interface GuardAgentConfig {
81
131
  checks: ('lint' | 'typecheck' | 'test' | 'build')[];
82
132
  };
83
133
  }
84
- export type GuardToolMode = 'auto' | 'on' | 'off';
85
- export type GuardAdapterName = 'dependency-graph' | 'security' | 'dependency-hygiene';
86
134
  export interface GuardFinding {
87
135
  ruleId: string;
88
136
  severity: GuardSeverity;
89
137
  file: string;
90
138
  line: number;
91
139
  importPath: string;
140
+ resolvedPath?: string | undefined;
92
141
  message: string;
93
142
  fingerprint: string;
94
143
  }
95
144
  export interface GuardFileChange {
96
145
  path: string;
97
146
  status: 'added' | 'modified' | 'deleted' | 'renamed';
98
- previousPath?: string;
147
+ previousPath?: string | undefined;
99
148
  }
100
149
  export interface GuardContractIssue {
101
150
  contractId: string;
102
- field: 'scope' | 'reference' | 'definition';
151
+ field: 'scope' | 'reference' | 'definition' | 'files';
103
152
  value: string;
104
153
  message: string;
105
154
  }
@@ -110,24 +159,24 @@ export interface GuardReport {
110
159
  scannedFiles: number;
111
160
  }
112
161
  interface ScanGuardOptions {
113
- changedOnly?: boolean;
114
- changedFiles?: Set<string>;
115
- baseline?: Set<string>;
116
- includeArchitectureInsights?: boolean;
162
+ changedOnly?: boolean | undefined;
163
+ changedFiles?: Set<string> | undefined;
164
+ baseline?: Set<string> | undefined;
165
+ includeArchitectureInsights?: boolean | undefined;
117
166
  }
118
167
  export interface GuardReviewPacket {
119
168
  version: 1;
120
169
  outcome: GuardOutcomeStatus;
121
- diffBase?: string;
170
+ diffBase?: string | undefined;
122
171
  changedFiles: string[];
123
172
  changes: GuardFileChange[];
124
173
  diff: string;
125
174
  truncated: boolean;
126
175
  redacted: boolean;
127
- diffError?: string;
176
+ diffError?: string | undefined;
128
177
  project: ProjectModel;
129
178
  contracts: GuardContract[];
130
- requirement?: string;
179
+ requirement?: string | undefined;
131
180
  deterministicFindings: GuardFinding[];
132
181
  impact: GuardImpactAnalysis;
133
182
  reviewInstructions: string[];
@@ -143,33 +192,48 @@ export declare const GUARD_CONVENTIONS_FILE: string;
143
192
  export declare const GUARD_AGENT_FILE: string;
144
193
  export declare const GUARD_CONTRACTS_FILE: string;
145
194
  export declare const GUARD_PROPOSALS_FILE: string;
195
+ export declare const GUARD_STATE_DIR: string;
196
+ export declare const GUARD_STATE_GENERATIONS_DIR: string;
197
+ export declare const GUARD_STATE_CURRENT_FILE: string;
146
198
  export declare const defaultGuardConfig: GuardConfig;
147
199
  export declare const defaultGuardAgentConfig: GuardAgentConfig;
148
200
  export declare class GuardAlreadyInitializedError extends Error {
149
201
  constructor();
150
202
  }
203
+ export declare class GuardConfigError extends Error {
204
+ constructor(path: string);
205
+ }
206
+ export declare class GuardStateBusyError extends Error {
207
+ constructor(path: string);
208
+ }
209
+ export declare class GuardStateStaleError extends Error {
210
+ constructor();
211
+ }
212
+ export declare class GuardBaselineReasonError extends Error {
213
+ constructor();
214
+ }
215
+ export declare function withGuardStateLock<T>(root: string, callback: () => T, options?: GuardStateLockOptions): T;
151
216
  export declare function isGuardContractsFile(value: unknown): value is {
152
217
  version: 1;
153
218
  contracts: GuardContract[];
154
219
  };
155
220
  export declare function isGuardProposalFile(value: unknown): value is GuardProposalFile;
156
221
  export declare function fingerprintProjectModel(model: ProjectModel): string;
222
+ export declare function fingerprintGuardConfig(guardConfig: GuardConfig): string;
157
223
  export declare function getGuardProposalFreshness(model: ProjectModel, proposals: GuardProposalFile | undefined): GuardProposalFreshness;
158
224
  export declare function loadGuardConfig(root: string): GuardConfig | undefined;
159
225
  export declare function loadGuardProposals(root: string): GuardProposalFile | undefined;
160
226
  export declare function isGuardAgentConfig(value: unknown): value is GuardAgentConfig;
161
227
  export declare function loadGuardAgentConfig(root: string): GuardAgentConfig;
162
228
  export declare function writeGuardAgentConfig(root: string, agentConfig?: GuardAgentConfig): void;
163
- export declare function loadGuardArtifact(root: string, relativePath: string): unknown;
164
229
  export declare function loadBaseline(root: string): Set<string>;
165
- export declare function updateBaseline(root: string, options?: {
166
- add?: string[];
167
- remove?: string[];
168
- reason?: string;
169
- }): Set<string>;
170
- export declare function writeGuardConfig(root: string, guardConfig: GuardConfig): void;
230
+ export declare function updateBaseline(root: string, options?: GuardBaselineUpdateOptions): Set<string>;
231
+ export declare function writeGuardConfig(root: string, guardConfig: GuardConfig, options?: GuardConfigWriteOptions): void;
171
232
  export declare function writeGuardProposals(root: string, proposals: GuardProposalFile): void;
172
- export declare function recordGuardProposalDecision(root: string, decisions: Pick<GuardProposalDecision, 'id' | 'type' | 'decision'>[]): void;
233
+ export declare function recordGuardProposalDecision(root: string, decisions: Pick<GuardProposalDecision, 'id' | 'type' | 'decision'>[], options?: Pick<GuardProposalDecision, 'source'>): void;
234
+ export declare function applyGuardProposalDecision(root: string, guardConfig: GuardConfig, decisions: Pick<GuardProposalDecision, 'id' | 'type' | 'decision'>[], options: Pick<GuardProposalDecision, 'source'>): void;
235
+ export declare function validateGuardProposalApproval(policy: GuardApprovalPolicy | undefined, proposals: GuardProposalFile | undefined): string | undefined;
236
+ export declare function getPendingGuardProposals(proposals: GuardProposalFile | undefined): GuardPendingProposal[];
173
237
  export declare function buildGuardProposals(model: ProjectModel, guardConfig: GuardConfig): GuardProposalFile;
174
238
  export declare function buildArchitectureMemory(model: ProjectModel): Record<string, unknown>;
175
239
  export declare function buildConventionsMemory(model: ProjectModel): Record<string, unknown>;
@@ -178,20 +242,21 @@ export declare function writeGuardMemory(root: string, model: ProjectModel): voi
178
242
  export declare function writeBaseline(root: string, findings: GuardFinding[], model?: ProjectModel): void;
179
243
  export declare function loadProjectModel(root: string): ProjectModel | undefined;
180
244
  export declare function writeProjectModel(root: string, model: ProjectModel): void;
245
+ /**
246
+ * Persist all derived project facts as one generation. Legacy root-level files remain as
247
+ * compatibility mirrors, while readers that understand generations always see a coherent set.
248
+ */
249
+ export declare function writeProjectState(root: string, model: ProjectModel, options?: GuardStateLockOptions): string;
181
250
  export declare function writeProjectSnapshot(root: string, model: ProjectModel): string;
251
+ export declare function loadGuardArtifact(root: string, relativePath: string): unknown;
182
252
  export declare function validateGuardContracts(root: string, contracts?: GuardContract[]): GuardContractIssue[];
253
+ export declare function validateGuardBudgets(root: string, budgets?: GuardBudget[]): GuardContractIssue[];
254
+ export declare function validateGuardPolicy(root: string, guardConfig: GuardConfig): GuardContractIssue[];
183
255
  /** @internal Redacts common credential shapes before a diff enters an AI review packet. */
184
- export declare function redactSensitiveText(value: string): {
185
- value: string;
186
- redacted: boolean;
187
- redactionCount: number;
188
- };
256
+ export declare function redactSensitiveText(value: string): GuardSensitiveText;
189
257
  export declare function scanGuard(root: string, guardConfig: GuardConfig, options?: ScanGuardOptions): GuardReport;
190
258
  export declare function buildGuardReviewPacket(root: string, guardConfig: GuardConfig, baseline?: Set<string>, maxDiffChars?: number, changedOnly?: boolean, requirement?: string, base?: string): GuardReviewPacket;
191
- export declare function initializeGuard(root: string, options?: {
192
- force?: boolean;
193
- }): {
194
- config: GuardConfig;
195
- report: GuardReport;
196
- };
197
- export { discoverProject, discoverProjectWithMetrics, findGuardRoot };
259
+ export declare function initializeGuard(root: string, options?: GuardConfigWriteOptions & {
260
+ force?: boolean | undefined;
261
+ }): GuardInitializationResult;
262
+ export { clearDiscoveryCache, discoverProject, discoverProjectWithMetrics, findGuardRoot };