@azizbekdevuz/gitguard-schema 1.0.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.
@@ -0,0 +1,88 @@
1
+ import { z } from 'zod';
2
+ // Conflict block extracted from a file
3
+ export const ConflictBlockSchema = z.object({
4
+ startLine: z.number(),
5
+ endLine: z.number(),
6
+ oursContent: z.string(),
7
+ theirsContent: z.string(),
8
+ context: z.string(), // surrounding lines for context
9
+ });
10
+ // Unmerged file with conflict details
11
+ export const UnmergedFileSchema = z.object({
12
+ path: z.string(),
13
+ stageOurs: z.string().optional(), // mode info
14
+ stageTheirs: z.string().optional(),
15
+ stageBase: z.string().optional(),
16
+ conflictBlocks: z.array(ConflictBlockSchema).max(3), // up to 3 blocks
17
+ });
18
+ // Branch info from porcelain v2
19
+ export const BranchInfoSchema = z.object({
20
+ head: z.string(), // branch name or "(detached)"
21
+ oid: z.string(), // current commit hash
22
+ upstream: z.string().optional(),
23
+ aheadBehind: z.object({
24
+ ahead: z.number(),
25
+ behind: z.number(),
26
+ }).optional(),
27
+ });
28
+ // Reflog entry
29
+ export const ReflogEntrySchema = z.object({
30
+ hash: z.string(),
31
+ selector: z.string(), // e.g., HEAD@{0}
32
+ action: z.string(),
33
+ message: z.string(),
34
+ });
35
+ // Log entry
36
+ export const LogEntrySchema = z.object({
37
+ hash: z.string(),
38
+ refs: z.array(z.string()), // decorations
39
+ message: z.string(),
40
+ });
41
+ // Rebase state info
42
+ export const RebaseStateSchema = z.object({
43
+ inProgress: z.boolean(),
44
+ type: z.enum(['merge', 'apply', 'none']),
45
+ headName: z.string().optional(), // original branch
46
+ onto: z.string().optional(),
47
+ currentStep: z.number().optional(),
48
+ totalSteps: z.number().optional(),
49
+ });
50
+ // Diff stat for a file
51
+ export const DiffStatSchema = z.object({
52
+ path: z.string(),
53
+ additions: z.number(),
54
+ deletions: z.number(),
55
+ binary: z.boolean().optional(),
56
+ });
57
+ // Main snapshot schema
58
+ export const SnapshotV1Schema = z.object({
59
+ version: z.literal(1),
60
+ timestamp: z.string().datetime(),
61
+ platform: z.enum(['win32', 'darwin', 'linux']),
62
+ repoRoot: z.string(),
63
+ gitDir: z.string(),
64
+ // Branch state
65
+ branch: BranchInfoSchema,
66
+ isDetachedHead: z.boolean(),
67
+ // Rebase state
68
+ rebaseState: RebaseStateSchema,
69
+ // Working tree status
70
+ unmergedFiles: z.array(UnmergedFileSchema).max(5), // increased for better conflict exploration
71
+ stagedFiles: z.array(z.string()),
72
+ modifiedFiles: z.array(z.string()),
73
+ untrackedFiles: z.array(z.string()),
74
+ // History
75
+ recentLog: z.array(LogEntrySchema).max(30),
76
+ recentReflog: z.array(ReflogEntrySchema).max(30),
77
+ // NEW: Commit graph for history visualization
78
+ commitGraph: z.string().optional(), // git log --graph --oneline output
79
+ // NEW: Diff stats for file-level summary
80
+ diffStats: z.array(DiffStatSchema).optional(),
81
+ // NEW: Merge metadata
82
+ mergeHead: z.string().optional(), // MERGE_HEAD commit if in merge
83
+ mergeMessage: z.string().optional(), // Default merge commit message
84
+ // Raw outputs for debugging
85
+ rawStatus: z.string(),
86
+ rawBranches: z.string(),
87
+ });
88
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@azizbekdevuz/gitguard-schema",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "typecheck": "tsc --noEmit",
16
+ "dev": "tsc --watch"
17
+ },
18
+ "dependencies": {
19
+ "zod": "^3.24.1"
20
+ },
21
+ "devDependencies": {
22
+ "typescript": "^5.7.2"
23
+ }
24
+ }
package/snapshot.json ADDED
File without changes
@@ -0,0 +1,134 @@
1
+ import { z } from 'zod';
2
+
3
+ // Issue types we detect
4
+ export const IssueTypeSchema = z.enum([
5
+ 'merge_conflict',
6
+ 'detached_head',
7
+ 'rebase_in_progress',
8
+ 'clean',
9
+ 'unknown',
10
+ ]);
11
+
12
+ export type IssueType = z.infer<typeof IssueTypeSchema>;
13
+
14
+ // Danger levels for plan steps
15
+ export const DangerLevelSchema = z.enum(['safe', 'caution', 'dangerous']);
16
+
17
+ export type DangerLevel = z.infer<typeof DangerLevelSchema>;
18
+
19
+ // Choice for conflict resolution
20
+ export const HunkChoiceSchema = z.enum(['ours', 'theirs', 'manual', 'combine']);
21
+
22
+ export type HunkChoice = z.infer<typeof HunkChoiceSchema>;
23
+
24
+ // ==========================================
25
+ // Repo Graph for Visualization
26
+ // ==========================================
27
+
28
+ export const GraphNodeSchema = z.object({
29
+ id: z.string(),
30
+ type: z.enum(['commit', 'branch', 'tag', 'head', 'remote']),
31
+ label: z.string(),
32
+ sha: z.string().optional(),
33
+ isCurrent: z.boolean().optional(),
34
+ isDetached: z.boolean().optional(),
35
+ });
36
+
37
+ export type GraphNode = z.infer<typeof GraphNodeSchema>;
38
+
39
+ export const GraphEdgeSchema = z.object({
40
+ from: z.string(),
41
+ to: z.string(),
42
+ type: z.enum(['parent', 'branch', 'merge']).optional(),
43
+ });
44
+
45
+ export type GraphEdge = z.infer<typeof GraphEdgeSchema>;
46
+
47
+ export const RepoGraphSchema = z.object({
48
+ nodes: z.array(GraphNodeSchema),
49
+ edges: z.array(GraphEdgeSchema),
50
+ headRef: z.string().optional(),
51
+ mergeHeadRef: z.string().optional(),
52
+ });
53
+
54
+ export type RepoGraph = z.infer<typeof RepoGraphSchema>;
55
+
56
+ // ==========================================
57
+ // Conflict Hunks
58
+ // ==========================================
59
+
60
+ export const ConflictHunkSchema = z.object({
61
+ index: z.number(),
62
+ startLine: z.number().optional(),
63
+ endLine: z.number().optional(),
64
+ baseText: z.string(),
65
+ oursText: z.string(),
66
+ theirsText: z.string(),
67
+ explanation: z.string().optional(),
68
+ suggestedChoice: HunkChoiceSchema.optional(),
69
+ suggestedContent: z.string().optional(),
70
+ });
71
+
72
+ export type ConflictHunk = z.infer<typeof ConflictHunkSchema>;
73
+
74
+ export const ConflictFileSchema = z.object({
75
+ path: z.string(),
76
+ highLevelSummary: z.string().optional(),
77
+ hunks: z.array(ConflictHunkSchema),
78
+ });
79
+
80
+ export type ConflictFile = z.infer<typeof ConflictFileSchema>;
81
+
82
+ // ==========================================
83
+ // Plan Steps
84
+ // ==========================================
85
+
86
+ export const PlanStepSchema = z.object({
87
+ index: z.number(),
88
+ title: z.string(),
89
+ rationale: z.string().optional(),
90
+ commands: z.array(z.string()),
91
+ verify: z.array(z.string()),
92
+ undo: z.array(z.string()),
93
+ dangerLevel: DangerLevelSchema,
94
+ });
95
+
96
+ export type PlanStep = z.infer<typeof PlanStepSchema>;
97
+
98
+ // ==========================================
99
+ // Full Analysis Result
100
+ // ==========================================
101
+
102
+ export const AnalysisResultSchema = z.object({
103
+ issueType: IssueTypeSchema,
104
+ summary: z.string(),
105
+ repoGraph: RepoGraphSchema.optional(),
106
+ conflicts: z.array(ConflictFileSchema).optional(),
107
+ plan: z.array(PlanStepSchema),
108
+ });
109
+
110
+ export type AnalysisResult = z.infer<typeof AnalysisResultSchema>;
111
+
112
+ // ==========================================
113
+ // Agent API Request/Response
114
+ // ==========================================
115
+
116
+ export const AnalyzeRequestSchema = z.object({
117
+ snapshot: z.any(), // SnapshotV1
118
+ options: z.object({
119
+ includeGraph: z.boolean().optional(),
120
+ maxConflictFiles: z.number().optional(),
121
+ maxHunksPerFile: z.number().optional(),
122
+ }).optional(),
123
+ });
124
+
125
+ export type AnalyzeRequest = z.infer<typeof AnalyzeRequestSchema>;
126
+
127
+ export const AnalyzeResponseSchema = z.object({
128
+ success: z.boolean(),
129
+ analysis: AnalysisResultSchema.optional(),
130
+ error: z.string().optional(),
131
+ durationMs: z.number().optional(),
132
+ });
133
+
134
+ export type AnalyzeResponse = z.infer<typeof AnalyzeResponseSchema>;
package/src/api.ts ADDED
@@ -0,0 +1,189 @@
1
+ import { z } from 'zod';
2
+ import { SnapshotV1Schema, type SnapshotV1 } from './snapshot.js';
3
+ import { PlanV1Schema, type PlanV1, VerificationResultSchema, type VerificationResult } from './plan.js';
4
+ import { SignalsSchema, type Signals } from './signals.js';
5
+
6
+ // ==========================================
7
+ // Session API Types
8
+ // ==========================================
9
+
10
+ // POST /api/sessions - Create new session
11
+ export const CreateSessionRequestSchema = z.object({
12
+ snapshot: SnapshotV1Schema,
13
+ });
14
+
15
+ export type CreateSessionRequest = z.infer<typeof CreateSessionRequestSchema>;
16
+
17
+ export const CreateSessionResponseSchema = z.object({
18
+ sessionId: z.string(),
19
+ });
20
+
21
+ export type CreateSessionResponse = z.infer<typeof CreateSessionResponseSchema>;
22
+
23
+ // GET /api/sessions/[id] - Get session details
24
+ export const TraceOutputSchema = z.object({
25
+ stage: z.string(),
26
+ output: z.unknown(),
27
+ createdAt: z.string(),
28
+ durationMs: z.number().nullable(),
29
+ });
30
+
31
+ export type TraceOutput = z.infer<typeof TraceOutputSchema>;
32
+
33
+ export const SessionSummarySchema = z.object({
34
+ id: z.string(),
35
+ title: z.string().nullable(),
36
+ createdAt: z.string(),
37
+ });
38
+
39
+ export type SessionSummary = z.infer<typeof SessionSummarySchema>;
40
+
41
+ export const GetSessionResponseSchema = z.object({
42
+ session: SessionSummarySchema,
43
+ snapshot: SnapshotV1Schema,
44
+ signals: SignalsSchema.nullable(),
45
+ plan: PlanV1Schema.nullable(),
46
+ traces: z.array(TraceOutputSchema),
47
+ });
48
+
49
+ export type GetSessionResponse = z.infer<typeof GetSessionResponseSchema>;
50
+
51
+ // ==========================================
52
+ // Plan API Types
53
+ // ==========================================
54
+
55
+ // POST /api/sessions/[id]/plan - Generate plan
56
+ export const GeneratePlanRequestSchema = z.object({
57
+ dangerousAllowed: z.boolean().optional().default(false),
58
+ });
59
+
60
+ export type GeneratePlanRequest = z.infer<typeof GeneratePlanRequestSchema>;
61
+
62
+ export const GeneratePlanResponseSchema = z.object({
63
+ plan: PlanV1Schema,
64
+ });
65
+
66
+ export type GeneratePlanResponse = z.infer<typeof GeneratePlanResponseSchema>;
67
+
68
+ // ==========================================
69
+ // Verify API Types
70
+ // ==========================================
71
+
72
+ // POST /api/sessions/[id]/verify - Verify progress
73
+ export const VerifyProgressRequestSchema = z.object({
74
+ snapshot: SnapshotV1Schema,
75
+ });
76
+
77
+ export type VerifyProgressRequest = z.infer<typeof VerifyProgressRequestSchema>;
78
+
79
+ export const VerifyProgressResponseSchema = VerificationResultSchema;
80
+
81
+ export type VerifyProgressResponse = VerificationResult;
82
+
83
+ // ==========================================
84
+ // Explain API Types
85
+ // ==========================================
86
+
87
+ // POST /api/sessions/[id]/explain - Get AI explanation
88
+ export const ExplainConflictRequestSchema = z.object({
89
+ type: z.literal('conflict'),
90
+ fileIndex: z.number(),
91
+ blockIndex: z.number(),
92
+ });
93
+
94
+ export const ExplainStateRequestSchema = z.object({
95
+ type: z.literal('state'),
96
+ });
97
+
98
+ export const ExplainRequestSchema = z.discriminatedUnion('type', [
99
+ ExplainConflictRequestSchema,
100
+ ExplainStateRequestSchema,
101
+ ]);
102
+
103
+ export type ExplainRequest = z.infer<typeof ExplainRequestSchema>;
104
+
105
+ // Conflict explanation response
106
+ export const ConflictExplanationSchema = z.object({
107
+ summary: z.string(),
108
+ oursInterpretation: z.string(),
109
+ theirsInterpretation: z.string(),
110
+ suggestedResolution: z.string(),
111
+ riskNotes: z.string().optional(),
112
+ });
113
+
114
+ export type ConflictExplanation = z.infer<typeof ConflictExplanationSchema>;
115
+
116
+ // State explanation response
117
+ export const StateExplanationSchema = z.object({
118
+ summary: z.string(),
119
+ howItHappened: z.string(),
120
+ currentPosition: z.string(),
121
+ safeNextSteps: z.array(z.string()),
122
+ warnings: z.array(z.string()).optional(),
123
+ });
124
+
125
+ export type StateExplanation = z.infer<typeof StateExplanationSchema>;
126
+
127
+ export const ExplainResponseSchema = z.object({
128
+ explanation: z.union([ConflictExplanationSchema, StateExplanationSchema]),
129
+ });
130
+
131
+ export type ExplainResponse = z.infer<typeof ExplainResponseSchema>;
132
+
133
+ // ==========================================
134
+ // Auth API Types
135
+ // ==========================================
136
+
137
+ // POST /api/auth/register - Register new user
138
+ export const RegisterRequestSchema = z.object({
139
+ name: z.string().optional(),
140
+ email: z.string().email(),
141
+ password: z.string().min(8),
142
+ });
143
+
144
+ export type RegisterRequest = z.infer<typeof RegisterRequestSchema>;
145
+
146
+ export const RegisterResponseSchema = z.object({
147
+ user: z.object({
148
+ id: z.string(),
149
+ name: z.string().nullable(),
150
+ email: z.string(),
151
+ }),
152
+ });
153
+
154
+ export type RegisterResponse = z.infer<typeof RegisterResponseSchema>;
155
+
156
+ // ==========================================
157
+ // Error Response
158
+ // ==========================================
159
+
160
+ export const ApiErrorSchema = z.object({
161
+ error: z.string(),
162
+ });
163
+
164
+ export type ApiError = z.infer<typeof ApiErrorSchema>;
165
+
166
+ // ==========================================
167
+ // History Types (for session list page)
168
+ // ==========================================
169
+
170
+ export const SessionListItemSchema = z.object({
171
+ id: z.string(),
172
+ title: z.string().nullable(),
173
+ createdAt: z.string(),
174
+ os: z.string().nullable(),
175
+ hasPlan: z.boolean(),
176
+ issueType: z.string().nullable(),
177
+ risk: z.string().nullable(),
178
+ });
179
+
180
+ export type SessionListItem = z.infer<typeof SessionListItemSchema>;
181
+
182
+ export const SessionListResponseSchema = z.object({
183
+ sessions: z.array(SessionListItemSchema),
184
+ total: z.number(),
185
+ page: z.number(),
186
+ pageSize: z.number(),
187
+ });
188
+
189
+ export type SessionListResponse = z.infer<typeof SessionListResponseSchema>;
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ export * from './snapshot.js';
2
+ export * from './signals.js';
3
+ export * from './api.js';
4
+
5
+ // Export from plan.js but exclude types that are redefined in analysis.js
6
+ export {
7
+ RiskLevelSchema,
8
+ RiskLevel,
9
+ PlanV1Schema,
10
+ PlanV1,
11
+ VerificationResultSchema,
12
+ VerificationResult,
13
+ } from './plan.js';
14
+
15
+ // Export everything from analysis.js (has updated IssueType, PlanStep, etc.)
16
+ export * from './analysis.js';
package/src/plan.ts ADDED
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+
3
+ // Issue types we handle
4
+ export const IssueTypeSchema = z.enum([
5
+ 'merge_conflict',
6
+ 'detached_head',
7
+ 'rebase_in_progress',
8
+ 'clean',
9
+ 'unknown',
10
+ ]);
11
+
12
+ export type IssueType = z.infer<typeof IssueTypeSchema>;
13
+
14
+ // Risk levels
15
+ export const RiskLevelSchema = z.enum(['low', 'medium', 'high']);
16
+
17
+ export type RiskLevel = z.infer<typeof RiskLevelSchema>;
18
+
19
+ // A single step in the recovery plan
20
+ export const PlanStepSchema = z.object({
21
+ id: z.string(),
22
+ title: z.string(),
23
+ description: z.string(),
24
+ commands: z.array(z.string()), // git commands to execute
25
+ expected: z.string(), // what should happen after running
26
+ undo: z.object({
27
+ possible: z.boolean(),
28
+ commands: z.array(z.string()), // commands to undo this step
29
+ description: z.string(),
30
+ }),
31
+ dangerous: z.boolean(), // requires explicit dangerous_allowed flag
32
+ warning: z.string().optional(), // warning text for dangerous operations
33
+ requiresUserInput: z.boolean().default(false), // e.g., editing conflict markers
34
+ userInputHint: z.string().optional(),
35
+ });
36
+
37
+ export type PlanStep = z.infer<typeof PlanStepSchema>;
38
+
39
+ // Complete recovery plan
40
+ export const PlanV1Schema = z.object({
41
+ version: z.literal(1),
42
+ timestamp: z.string().datetime(),
43
+ issueType: IssueTypeSchema,
44
+ issueSummary: z.string(),
45
+ risk: RiskLevelSchema,
46
+ steps: z.array(PlanStepSchema),
47
+
48
+ // Alternative safer approaches if dangerous operations are suggested
49
+ saferAlternatives: z.array(z.object({
50
+ description: z.string(),
51
+ tradeoff: z.string(), // what you lose by using safer approach
52
+ steps: z.array(PlanStepSchema),
53
+ })).optional(),
54
+
55
+ // Reflog-based recovery path (always included for safety)
56
+ reflogRecovery: z.object({
57
+ description: z.string(),
58
+ relevantEntries: z.array(z.string()), // reflog selectors like HEAD@{2}
59
+ recoveryCommand: z.string(),
60
+ }).optional(),
61
+ });
62
+
63
+ export type PlanV1 = z.infer<typeof PlanV1Schema>;
64
+
65
+ // Verification result after user runs some steps
66
+ export const VerificationResultSchema = z.object({
67
+ stepsCompleted: z.array(z.string()), // step IDs
68
+ issueResolved: z.boolean(),
69
+ remainingIssues: z.array(z.string()),
70
+ nextStepId: z.string().optional(),
71
+ guidance: z.string(),
72
+ });
73
+
74
+ export type VerificationResult = z.infer<typeof VerificationResultSchema>;
package/src/signals.ts ADDED
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { IssueTypeSchema, RiskLevelSchema } from './plan.js';
3
+
4
+ // Normalized signals from snapshot for agent processing
5
+ export const SignalsSchema = z.object({
6
+ // Detected issues
7
+ hasConflicts: z.boolean(),
8
+ conflictCount: z.number(),
9
+ conflictFiles: z.array(z.string()),
10
+
11
+ isDetachedHead: z.boolean(),
12
+ detachedAt: z.string().optional(), // commit hash
13
+
14
+ isRebaseInProgress: z.boolean(),
15
+ rebaseType: z.enum(['merge', 'apply', 'none']),
16
+ rebaseOnto: z.string().optional(),
17
+
18
+ // Branch context
19
+ currentBranch: z.string(),
20
+ upstreamBranch: z.string().optional(),
21
+ aheadCount: z.number(),
22
+ behindCount: z.number(),
23
+
24
+ // Working tree state
25
+ hasStagedChanges: z.boolean(),
26
+ hasUnstagedChanges: z.boolean(),
27
+ hasUntrackedFiles: z.boolean(),
28
+
29
+ // Recovery hints from reflog
30
+ recentCheckouts: z.array(z.object({
31
+ from: z.string(),
32
+ to: z.string(),
33
+ reflogSelector: z.string(),
34
+ })),
35
+ recentResets: z.array(z.object({
36
+ type: z.string(), // soft, mixed, hard
37
+ target: z.string(),
38
+ reflogSelector: z.string(),
39
+ })),
40
+
41
+ // Classification result
42
+ primaryIssue: IssueTypeSchema,
43
+ secondaryIssues: z.array(IssueTypeSchema),
44
+ estimatedRisk: RiskLevelSchema,
45
+ });
46
+
47
+ export type Signals = z.infer<typeof SignalsSchema>;