@sigil-engine/core 0.1.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.
Files changed (48) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/dist/cache.d.ts +24 -0
  3. package/dist/cache.d.ts.map +1 -0
  4. package/dist/cache.js +97 -0
  5. package/dist/cache.js.map +1 -0
  6. package/dist/diff.d.ts +34 -0
  7. package/dist/diff.d.ts.map +1 -0
  8. package/dist/diff.js +319 -0
  9. package/dist/diff.js.map +1 -0
  10. package/dist/extract.d.ts +27 -0
  11. package/dist/extract.d.ts.map +1 -0
  12. package/dist/extract.js +162 -0
  13. package/dist/extract.js.map +1 -0
  14. package/dist/index.d.ts +26 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +21 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/plugin.d.ts +103 -0
  19. package/dist/plugin.d.ts.map +1 -0
  20. package/dist/plugin.js +47 -0
  21. package/dist/plugin.js.map +1 -0
  22. package/dist/safety.d.ts +25 -0
  23. package/dist/safety.d.ts.map +1 -0
  24. package/dist/safety.js +139 -0
  25. package/dist/safety.js.map +1 -0
  26. package/dist/schema.d.ts +184 -0
  27. package/dist/schema.d.ts.map +1 -0
  28. package/dist/schema.js +33 -0
  29. package/dist/schema.js.map +1 -0
  30. package/dist/serialize.d.ts +16 -0
  31. package/dist/serialize.d.ts.map +1 -0
  32. package/dist/serialize.js +75 -0
  33. package/dist/serialize.js.map +1 -0
  34. package/package.json +35 -0
  35. package/src/cache.ts +133 -0
  36. package/src/diff.ts +421 -0
  37. package/src/extract.ts +196 -0
  38. package/src/index.ts +94 -0
  39. package/src/plugin.ts +186 -0
  40. package/src/safety.ts +185 -0
  41. package/src/schema.ts +270 -0
  42. package/src/serialize.ts +97 -0
  43. package/tests/cache.test.ts +47 -0
  44. package/tests/diff.test.ts +222 -0
  45. package/tests/plugin.test.ts +107 -0
  46. package/tests/schema.test.ts +132 -0
  47. package/tests/serialize.test.ts +92 -0
  48. package/tsconfig.json +20 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Extraction orchestrator — discovers plugins, runs them, merges results.
3
+ *
4
+ * PURE: This module returns a ContextDocument. It does NOT write to disk.
5
+ * I/O is handled by the CLI or calling code.
6
+ */
7
+ import { execSync } from "child_process";
8
+ import { resolve, basename } from "path";
9
+ import { existsSync, readFileSync } from "fs";
10
+ import { createEmptyDocument } from "./schema.js";
11
+ import { detectPlugins, getPlugins, } from "./plugin.js";
12
+ /**
13
+ * Extract a ContextDocument from a project.
14
+ *
15
+ * This is the primary API — it discovers applicable plugins,
16
+ * runs them, and merges results into a unified document.
17
+ *
18
+ * Returns a ContextDocument. Does NOT write to disk.
19
+ */
20
+ export async function extractContext(opts) {
21
+ const startTime = Date.now();
22
+ const projectPath = resolve(opts.projectPath);
23
+ const projectName = inferProjectName(projectPath);
24
+ const progress = opts.onProgress ?? (() => { });
25
+ progress({ phase: "init", message: `Parsing ${projectName} at ${projectPath}` });
26
+ // Discover which plugins apply to this project
27
+ progress({ phase: "detect", message: "Detecting project type..." });
28
+ let plugins;
29
+ if (opts.plugins && opts.plugins.length > 0) {
30
+ // Use explicitly specified plugins
31
+ const allPlugins = getPlugins();
32
+ plugins = allPlugins.filter((p) => opts.plugins.includes(p.name));
33
+ if (plugins.length === 0) {
34
+ throw new Error(`No registered plugins match: ${opts.plugins.join(", ")}. ` +
35
+ `Available: ${allPlugins.map((p) => p.name).join(", ") || "none"}`);
36
+ }
37
+ }
38
+ else {
39
+ // Auto-detect
40
+ plugins = await detectPlugins(projectPath);
41
+ if (plugins.length === 0) {
42
+ throw new Error("No plugins detected support for this project. " +
43
+ "Install a parser plugin (e.g., @sigil-engine/parser-typescript).");
44
+ }
45
+ }
46
+ progress({
47
+ phase: "detect",
48
+ message: `Detected plugins: ${plugins.map((p) => p.name).join(", ")}`,
49
+ });
50
+ // Create the document
51
+ const doc = createEmptyDocument(projectName);
52
+ // Run each plugin: init → extract → merge
53
+ for (const plugin of plugins) {
54
+ progress({
55
+ phase: "extract",
56
+ plugin: plugin.name,
57
+ message: `Running ${plugin.name} plugin...`,
58
+ });
59
+ const project = await plugin.init(projectPath);
60
+ progress({
61
+ phase: "extract",
62
+ plugin: plugin.name,
63
+ message: `${plugin.name}: found ${project.sourceFiles.length} source files`,
64
+ });
65
+ const result = await plugin.extract(project);
66
+ progress({
67
+ phase: "merge",
68
+ plugin: plugin.name,
69
+ message: `Merging ${plugin.name} results...`,
70
+ });
71
+ mergeResult(doc, result);
72
+ }
73
+ // Finalize metadata
74
+ const elapsed = Date.now() - startTime;
75
+ doc._extraction = {
76
+ extracted_at: new Date().toISOString(),
77
+ sigil_version: "0.1.0",
78
+ source_commit: getGitCommit(projectPath),
79
+ extraction_ms: elapsed,
80
+ plugins_used: plugins.map((p) => `${p.name}@${p.version}`),
81
+ };
82
+ progress({
83
+ phase: "done",
84
+ message: `Done in ${elapsed}ms — ${doc.entities.length} entities, ${doc.components.length} components, ${doc.routes.length} routes, ${doc.exports.length} exports`,
85
+ elapsed_ms: elapsed,
86
+ });
87
+ return doc;
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Merge plugin results into document
91
+ // ---------------------------------------------------------------------------
92
+ function mergeResult(doc, result) {
93
+ // Arrays: concatenate
94
+ if (result.entities)
95
+ doc.entities.push(...result.entities);
96
+ if (result.components)
97
+ doc.components.push(...result.components);
98
+ if (result.routes)
99
+ doc.routes.push(...result.routes);
100
+ if (result.exports)
101
+ doc.exports.push(...result.exports);
102
+ if (result.call_graph)
103
+ doc.call_graph.push(...result.call_graph);
104
+ if (result.component_graph)
105
+ doc.component_graph.push(...result.component_graph);
106
+ if (result.env_vars)
107
+ doc.env_vars.push(...result.env_vars);
108
+ if (result.dependencies)
109
+ doc.dependencies.push(...result.dependencies);
110
+ // Records: merge (later plugins can override earlier ones)
111
+ if (result.stack)
112
+ Object.assign(doc.stack, result.stack);
113
+ if (result.patterns)
114
+ Object.assign(doc.patterns, result.patterns);
115
+ if (result.conventions)
116
+ Object.assign(doc.conventions, result.conventions);
117
+ // Extensions: deep merge
118
+ if (result.extensions) {
119
+ doc.extensions = doc.extensions ?? {};
120
+ Object.assign(doc.extensions, result.extensions);
121
+ }
122
+ }
123
+ // ---------------------------------------------------------------------------
124
+ // Deduplication — remove exports already captured as components/entities
125
+ // ---------------------------------------------------------------------------
126
+ export function deduplicateExports(doc) {
127
+ const componentNames = new Set(doc.components.map((c) => c.name));
128
+ const entitySymbols = new Set(doc.entities.map((e) => e._meta.symbol));
129
+ doc.exports = doc.exports.filter((exp) => !componentNames.has(exp.name) && !entitySymbols.has(exp.name));
130
+ }
131
+ // ---------------------------------------------------------------------------
132
+ // Helpers
133
+ // ---------------------------------------------------------------------------
134
+ function inferProjectName(projectPath) {
135
+ const pkgPath = resolve(projectPath, "package.json");
136
+ if (existsSync(pkgPath)) {
137
+ try {
138
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
139
+ if (pkg.name && !pkg.name.startsWith("@"))
140
+ return pkg.name;
141
+ if (pkg.name)
142
+ return pkg.name.split("/").pop() ?? basename(projectPath);
143
+ }
144
+ catch {
145
+ // fall through
146
+ }
147
+ }
148
+ return basename(projectPath);
149
+ }
150
+ function getGitCommit(projectPath) {
151
+ try {
152
+ return execSync("git rev-parse --short HEAD", {
153
+ cwd: projectPath,
154
+ encoding: "utf-8",
155
+ stdio: ["pipe", "pipe", "pipe"],
156
+ }).trim();
157
+ }
158
+ catch {
159
+ return undefined;
160
+ }
161
+ }
162
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @sigil-engine/core — Public API
3
+ *
4
+ * The core engine for Sigil. Language-agnostic schema, plugin system,
5
+ * extraction orchestrator, diff engine, and serialization.
6
+ *
7
+ * Usage:
8
+ * import { extractContext, diffContexts, registerPlugin } from '@sigil-engine/core';
9
+ *
10
+ * registerPlugin(typescriptPlugin);
11
+ * const doc = await extractContext({ projectPath: './my-app' });
12
+ */
13
+ export type { ContextDocument, Meta, MetaType, StackInfo, ExtractionMeta, Entity, EntityField, EntityRelation, Component, ComponentProp, Route, RouteMethod, ExportedSymbol, Patterns, Conventions, Dependency, CallEdge, ComponentEdge, EnvVar, } from "./schema.js";
14
+ export { createEmptyDocument } from "./schema.js";
15
+ export type { ExtractorPlugin, ParsedProject, ExtractResult, ApplyIntent, ApplyResult, IntentType, IntentConfidence, ProgressCallback, ProgressEvent, ProgressPhase, } from "./plugin.js";
16
+ export { registerPlugin, getPlugins, detectPlugins, clearPlugins, } from "./plugin.js";
17
+ export type { ExtractOptions } from "./extract.js";
18
+ export { extractContext, deduplicateExports } from "./extract.js";
19
+ export type { DiffResult, Change, ChangeType, ChangeCategory } from "./diff.js";
20
+ export { diffContexts, formatDiff } from "./diff.js";
21
+ export { serializeYaml, serializeJson, deserializeYaml, deserializeJson, writeContextFile, readContextFile, } from "./serialize.js";
22
+ export type { FileCache, ChangedFiles } from "./cache.js";
23
+ export { readCache, writeCache, buildCacheFromFiles, getChangedFiles, } from "./cache.js";
24
+ export type { SafetyCheckpoint, ValidationResult, ConfirmCallback } from "./safety.js";
25
+ export { preApplySafety, postApplyValidation, rollbackApply, getGitStatus, } from "./safety.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,YAAY,EACV,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,cAAc,EACd,MAAM,EACN,WAAW,EACX,cAAc,EACd,SAAS,EACT,aAAa,EACb,KAAK,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,QAAQ,EACR,aAAa,EACb,MAAM,GACP,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,YAAY,EACV,eAAe,EACf,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @sigil-engine/core — Public API
3
+ *
4
+ * The core engine for Sigil. Language-agnostic schema, plugin system,
5
+ * extraction orchestrator, diff engine, and serialization.
6
+ *
7
+ * Usage:
8
+ * import { extractContext, diffContexts, registerPlugin } from '@sigil-engine/core';
9
+ *
10
+ * registerPlugin(typescriptPlugin);
11
+ * const doc = await extractContext({ projectPath: './my-app' });
12
+ */
13
+ export { createEmptyDocument } from "./schema.js";
14
+ export { registerPlugin, getPlugins, detectPlugins, clearPlugins, } from "./plugin.js";
15
+ export { extractContext, deduplicateExports } from "./extract.js";
16
+ export { diffContexts, formatDiff } from "./diff.js";
17
+ // Serialization
18
+ export { serializeYaml, serializeJson, deserializeYaml, deserializeJson, writeContextFile, readContextFile, } from "./serialize.js";
19
+ export { readCache, writeCache, buildCacheFromFiles, getChangedFiles, } from "./cache.js";
20
+ export { preApplySafety, postApplyValidation, rollbackApply, getGitStatus, } from "./safety.js";
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyBH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAgBlD,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAErD,gBAAgB;AAChB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AAIpB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Sigil Plugin System — the extensibility contract.
3
+ *
4
+ * Every language parser implements `ExtractorPlugin`. The core engine
5
+ * discovers registered plugins and orchestrates them.
6
+ *
7
+ * To add Python support:
8
+ * 1. Create @sigil-engine/parser-python
9
+ * 2. Implement ExtractorPlugin
10
+ * 3. Export a default plugin instance
11
+ * 4. Users install it — Sigil discovers it automatically
12
+ */
13
+ import type { ContextDocument } from "./schema.js";
14
+ /**
15
+ * The parsed project representation passed to plugins.
16
+ * Language-agnostic — each plugin casts or wraps this with its own type.
17
+ */
18
+ export interface ParsedProject {
19
+ /** Absolute path to the project root */
20
+ projectPath: string;
21
+ /** List of source file paths (absolute) */
22
+ sourceFiles: string[];
23
+ /** Package manifest (package.json, pyproject.toml, etc.) parsed as object */
24
+ manifest?: Record<string, unknown>;
25
+ }
26
+ /**
27
+ * Result returned by a plugin's extract method.
28
+ * Partial<ContextDocument> — plugins only fill what they understand.
29
+ */
30
+ export type ExtractResult = Partial<Omit<ContextDocument, "version" | "project" | "_extraction">>;
31
+ /**
32
+ * The core plugin contract. Every language parser implements this.
33
+ */
34
+ export interface ExtractorPlugin {
35
+ /** Unique plugin name (e.g., "typescript", "python", "go") */
36
+ name: string;
37
+ /** Semver version of the plugin */
38
+ version: string;
39
+ /** Languages/frameworks this plugin handles */
40
+ languages: string[];
41
+ /**
42
+ * Check if this plugin should run for the given project.
43
+ * Called before extract() — return false to skip.
44
+ *
45
+ * Example: typescript plugin checks for tsconfig.json or .ts files
46
+ */
47
+ detect(projectPath: string): boolean | Promise<boolean>;
48
+ /**
49
+ * Initialize the plugin for a specific project.
50
+ * Returns a ParsedProject (or plugin-specific extension of it).
51
+ * Called once before extract().
52
+ */
53
+ init(projectPath: string): ParsedProject | Promise<ParsedProject>;
54
+ /**
55
+ * Extract context from the project.
56
+ * Returns partial context — the orchestrator merges results from all plugins.
57
+ */
58
+ extract(project: ParsedProject): ExtractResult | Promise<ExtractResult>;
59
+ /**
60
+ * Optional: handle apply intents for elements this plugin created.
61
+ * Called by the apply engine when an intent targets a _meta.tags
62
+ * value owned by this plugin.
63
+ */
64
+ apply?(intent: ApplyIntent, projectPath: string): ApplyResult | Promise<ApplyResult>;
65
+ }
66
+ export type IntentType = "AddEntity" | "RemoveEntity" | "AddField" | "RemoveField" | "ModifyField" | "RenameSymbol" | "AddComponent" | "RemoveComponent" | "AddRoute" | "RemoveRoute" | "AddMethod" | "RemoveMethod" | "ModifyProps" | "ChangeSignature" | "MoveFile" | "AddDependency" | "RemoveDependency";
67
+ export type IntentConfidence = "deterministic" | "needs-ai";
68
+ export interface ApplyIntent {
69
+ type: IntentType;
70
+ confidence: IntentConfidence;
71
+ target_file?: string;
72
+ target_symbol?: string;
73
+ description: string;
74
+ old_value?: unknown;
75
+ new_value?: unknown;
76
+ priority: number;
77
+ }
78
+ export interface ApplyResult {
79
+ intent: ApplyIntent;
80
+ success: boolean;
81
+ error?: string;
82
+ files_created: string[];
83
+ files_modified: string[];
84
+ preview?: string;
85
+ code?: string;
86
+ }
87
+ /** Register a plugin with Sigil */
88
+ export declare function registerPlugin(plugin: ExtractorPlugin): void;
89
+ /** Get all registered plugins */
90
+ export declare function getPlugins(): readonly ExtractorPlugin[];
91
+ /** Get plugins that detect support for a given project */
92
+ export declare function detectPlugins(projectPath: string): Promise<ExtractorPlugin[]>;
93
+ /** Clear all registered plugins (for testing) */
94
+ export declare function clearPlugins(): void;
95
+ export type ProgressPhase = "init" | "detect" | "extract" | "merge" | "serialize" | "cache" | "done";
96
+ export interface ProgressEvent {
97
+ phase: ProgressPhase;
98
+ plugin?: string;
99
+ message: string;
100
+ elapsed_ms?: number;
101
+ }
102
+ export type ProgressCallback = (event: ProgressEvent) => void;
103
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/dist/plugin.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Sigil Plugin System — the extensibility contract.
3
+ *
4
+ * Every language parser implements `ExtractorPlugin`. The core engine
5
+ * discovers registered plugins and orchestrates them.
6
+ *
7
+ * To add Python support:
8
+ * 1. Create @sigil-engine/parser-python
9
+ * 2. Implement ExtractorPlugin
10
+ * 3. Export a default plugin instance
11
+ * 4. Users install it — Sigil discovers it automatically
12
+ */
13
+ // ---------------------------------------------------------------------------
14
+ // Plugin registry
15
+ // ---------------------------------------------------------------------------
16
+ const registry = [];
17
+ /** Register a plugin with Sigil */
18
+ export function registerPlugin(plugin) {
19
+ // Prevent duplicate registration
20
+ const existing = registry.findIndex((p) => p.name === plugin.name);
21
+ if (existing >= 0) {
22
+ registry[existing] = plugin;
23
+ }
24
+ else {
25
+ registry.push(plugin);
26
+ }
27
+ }
28
+ /** Get all registered plugins */
29
+ export function getPlugins() {
30
+ return registry;
31
+ }
32
+ /** Get plugins that detect support for a given project */
33
+ export async function detectPlugins(projectPath) {
34
+ const detected = [];
35
+ for (const plugin of registry) {
36
+ const supports = await plugin.detect(projectPath);
37
+ if (supports) {
38
+ detected.push(plugin);
39
+ }
40
+ }
41
+ return detected;
42
+ }
43
+ /** Clear all registered plugins (for testing) */
44
+ export function clearPlugins() {
45
+ registry.length = 0;
46
+ }
47
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmHH,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,QAAQ,GAAsB,EAAE,CAAC;AAEvC,mCAAmC;AACnC,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,iCAAiC;IACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,QAAQ,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,YAAY;IAC1B,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Apply safety mechanisms — git stash before, validation after, rollback on failure.
3
+ *
4
+ * SECURITY: All git operations use execFileSync (not execSync) to prevent
5
+ * shell injection. Destructive operations require explicit confirmation.
6
+ */
7
+ export interface SafetyCheckpoint {
8
+ hadDirtyFiles: boolean;
9
+ stashCreated: boolean;
10
+ originalHead: string;
11
+ }
12
+ /**
13
+ * Callback for confirming destructive operations.
14
+ * Return true to proceed, false to abort.
15
+ */
16
+ export type ConfirmCallback = (message: string) => boolean | Promise<boolean>;
17
+ export declare function preApplySafety(projectPath: string, confirm?: ConfirmCallback): SafetyCheckpoint;
18
+ export interface ValidationResult {
19
+ typesOk: boolean;
20
+ errors: string[];
21
+ }
22
+ export declare function postApplyValidation(projectPath: string): ValidationResult;
23
+ export declare function rollbackApply(projectPath: string, checkpoint: SafetyCheckpoint, confirm?: ConfirmCallback): Promise<boolean>;
24
+ export declare function getGitStatus(projectPath: string): string;
25
+ //# sourceMappingURL=safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAK9E,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,eAAyB,GACjC,gBAAgB,CA4ClB;AAMD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAsBzE;AAMD,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,gBAAgB,EAC5B,OAAO,GAAE,eAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAiDlB;AAMD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAUxD"}
package/dist/safety.js ADDED
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Apply safety mechanisms — git stash before, validation after, rollback on failure.
3
+ *
4
+ * SECURITY: All git operations use execFileSync (not execSync) to prevent
5
+ * shell injection. Destructive operations require explicit confirmation.
6
+ */
7
+ import { execFileSync } from "child_process";
8
+ import { resolve } from "path";
9
+ /** Default confirmation — always denies (safe default) */
10
+ const denyAll = () => false;
11
+ export function preApplySafety(projectPath, confirm = denyAll) {
12
+ const absPath = resolve(projectPath);
13
+ // Get current HEAD — using execFileSync (no shell)
14
+ let originalHead = "";
15
+ try {
16
+ originalHead = execFileSync("git", ["rev-parse", "HEAD"], {
17
+ cwd: absPath,
18
+ encoding: "utf-8",
19
+ stdio: ["pipe", "pipe", "pipe"],
20
+ }).trim();
21
+ }
22
+ catch {
23
+ // Not a git repo — skip safety
24
+ return { hadDirtyFiles: false, stashCreated: false, originalHead: "" };
25
+ }
26
+ // Check for dirty files
27
+ let gitStatus = "";
28
+ try {
29
+ gitStatus = execFileSync("git", ["status", "--porcelain"], {
30
+ cwd: absPath,
31
+ encoding: "utf-8",
32
+ stdio: ["pipe", "pipe", "pipe"],
33
+ }).trim();
34
+ }
35
+ catch {
36
+ return { hadDirtyFiles: false, stashCreated: false, originalHead };
37
+ }
38
+ const hadDirtyFiles = gitStatus.length > 0;
39
+ if (hadDirtyFiles) {
40
+ try {
41
+ execFileSync("git", ["stash", "push", "-m", "sigil-pre-apply"], {
42
+ cwd: absPath,
43
+ encoding: "utf-8",
44
+ stdio: ["pipe", "pipe", "pipe"],
45
+ });
46
+ return { hadDirtyFiles, stashCreated: true, originalHead };
47
+ }
48
+ catch {
49
+ return { hadDirtyFiles, stashCreated: false, originalHead };
50
+ }
51
+ }
52
+ return { hadDirtyFiles, stashCreated: false, originalHead };
53
+ }
54
+ export function postApplyValidation(projectPath) {
55
+ const absPath = resolve(projectPath);
56
+ try {
57
+ execFileSync("npx", ["tsc", "--noEmit"], {
58
+ cwd: absPath,
59
+ encoding: "utf-8",
60
+ stdio: ["pipe", "pipe", "pipe"],
61
+ timeout: 30000,
62
+ });
63
+ return { typesOk: true, errors: [] };
64
+ }
65
+ catch (err) {
66
+ const output = err.stdout ??
67
+ err.stderr ??
68
+ "";
69
+ const errors = output
70
+ .split("\n")
71
+ .filter((line) => line.includes("error TS"))
72
+ .slice(0, 10);
73
+ return { typesOk: false, errors };
74
+ }
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // Rollback
78
+ // ---------------------------------------------------------------------------
79
+ export async function rollbackApply(projectPath, checkpoint, confirm = denyAll) {
80
+ const absPath = resolve(projectPath);
81
+ // Require confirmation before destructive rollback
82
+ const confirmed = await confirm("Apply produced type errors. Roll back all changes and restore previous state?");
83
+ if (!confirmed) {
84
+ return false;
85
+ }
86
+ // Discard apply changes — execFileSync, no shell
87
+ try {
88
+ execFileSync("git", ["checkout", "."], {
89
+ cwd: absPath,
90
+ encoding: "utf-8",
91
+ stdio: ["pipe", "pipe", "pipe"],
92
+ });
93
+ }
94
+ catch {
95
+ // Could not roll back
96
+ return false;
97
+ }
98
+ // Clean untracked files created by apply
99
+ try {
100
+ execFileSync("git", ["clean", "-fd"], {
101
+ cwd: absPath,
102
+ encoding: "utf-8",
103
+ stdio: ["pipe", "pipe", "pipe"],
104
+ });
105
+ }
106
+ catch {
107
+ // Non-fatal
108
+ }
109
+ // Restore stash if we created one
110
+ if (checkpoint.stashCreated) {
111
+ try {
112
+ execFileSync("git", ["stash", "pop"], {
113
+ cwd: absPath,
114
+ encoding: "utf-8",
115
+ stdio: ["pipe", "pipe", "pipe"],
116
+ });
117
+ }
118
+ catch {
119
+ // Stash pop failed — user must handle manually
120
+ }
121
+ }
122
+ return true;
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // Git commit helper (for post-apply)
126
+ // ---------------------------------------------------------------------------
127
+ export function getGitStatus(projectPath) {
128
+ try {
129
+ return execFileSync("git", ["status", "--porcelain"], {
130
+ cwd: resolve(projectPath),
131
+ encoding: "utf-8",
132
+ stdio: ["pipe", "pipe", "pipe"],
133
+ }).trim();
134
+ }
135
+ catch {
136
+ return "";
137
+ }
138
+ }
139
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"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"}