flecto 1.0.2 → 2.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.
package/README.md CHANGED
@@ -1,21 +1,56 @@
1
- # Flecto
1
+ <p align="center">
2
+ <img src="docs/assets/flecto-hero.png" alt="Flecto — semantic config watcher" width="920"/>
3
+ </p>
2
4
 
3
- **Flecto watches your config files and tells you exactly what changed — in plain English.**
5
+ <h1 align="center">Flecto</h1>
4
6
 
5
- No more staring at raw line diffs. When your `.env`, `YAML`, `JSON`, or `TOML` file changes, Flecto shows you what actually happened:
7
+ <p align="center">
8
+ <strong>Config changes, in plain English — with risk flags built in.</strong><br/>
9
+ Watch · Diff · Policy · CI · Webhooks
10
+ </p>
6
11
 
7
- ```
8
- [10:42:31] config/prod.yaml 3 changes
9
- ~ database.pool_size: 5 → 20
10
- + feature_flags.dark_mode: true
11
- - deprecated.old_key
12
- ```
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/flecto"><img alt="npm" src="https://img.shields.io/npm/v/flecto?style=flat-square&color=34d399&labelColor=0b1220"/></a>
14
+ <a href="https://github.com/myselfsiddharth/Flecto/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/myselfsiddharth/Flecto/ci.yml?branch=main&style=flat-square&label=CI&labelColor=0b1220"/></a>
15
+ <a href="LICENSE"><img alt="MIT" src="https://img.shields.io/badge/license-MIT-8fa3bf?style=flat-square&labelColor=0b1220"/></a>
16
+ <a href="https://github.com/myselfsiddharth/Flecto/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/myselfsiddharth/Flecto?style=flat-square&color=fbbf24&labelColor=0b1220"/></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://github.com/myselfsiddharth/Flecto/stargazers">⭐ Star this repo</a> if Flecto saves you from a noisy config diff — it helps others find the project.
21
+ </p>
22
+
23
+ <p align="center">
24
+ <img src="docs/assets/flecto-demo.png" alt="Flecto watch demo in the terminal" width="920"/>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <img src="docs/assets/demo-watch.svg" alt="Animated Flecto watch output" width="920"/>
29
+ </p>
13
30
 
14
31
  ---
15
32
 
16
- ## Why Flecto?
33
+ ## Why teams use Flecto
34
+
35
+ Line diffs lie about config. Formatting churn, key reorders, and “small” YAML edits hide the changes that actually matter in production.
36
+
37
+ **Flecto** turns structured config into semantic events:
17
38
 
18
- Standard file watchers tell you *a file changed*. Flecto tells you *what* changed and *why it might matter* — flagging secrets, dangerous toggles, and risky config jumps automatically.
39
+ - What changed (`pool_size: 5 20`)
40
+ - What was added or removed
41
+ - What looks risky (secrets, dangerous toggles, pool jumps)
42
+ - What to do next (CI gate, webhook, shell command)
43
+
44
+ See the [changelog and migration notes](CHANGELOG.md) for release history and
45
+ upcoming v2.1 behavior changes.
46
+
47
+ > Diff tools compare trees. **Flecto watches, scores risk, and alerts.**
48
+
49
+ | Without Flecto | With Flecto |
50
+ |---|---|
51
+ | `+ 40 lines of YAML noise` | `~ database.pool_size: 5 → 20` |
52
+ | Hope someone notices `debug: true` | Policy finding → CI fails |
53
+ | “Something in `.env` changed” | Exact keys + optional secret masking |
19
54
 
20
55
  ---
21
56
 
@@ -25,47 +60,61 @@ Standard file watchers tell you *a file changed*. Flecto tells you *what* change
25
60
  npm install -g flecto
26
61
  ```
27
62
 
28
- After that, `flecto` is available globally from anywhere.
63
+ Requires Node.js 20.19.0 or later.
29
64
 
30
- ---
65
+ ```bash
66
+ flecto --version
67
+ flecto doctor
68
+ ```
31
69
 
32
- ## Quick Start
70
+ ---
33
71
 
34
- Watch any config file:
72
+ ## Quick start
35
73
 
36
74
  ```bash
37
75
  flecto watch config/prod.yaml
38
76
  flecto watch .env
39
77
  flecto watch settings.json
40
78
  flecto watch pyproject.toml
79
+ flecto watch app.ini
41
80
  ```
42
81
 
43
- That's it. Flecto starts watching and prints a clear summary every time something changes.
82
+ Thats it Flecto prints a clear summary on every meaningful change.
44
83
 
45
84
  ---
46
85
 
47
- ## Common Use Cases
86
+ ## Features at a glance
48
87
 
49
- ### Watch multiple files at once
88
+ - **Semantic diffs** for JSON, YAML, TOML, INI, and dotenv (`.env`, `.env.*`, `*.env`)
89
+ - **Live watch** with optional command + webhook delivery
90
+ - **Policy packs** (`default`, `strict-prod`, `compose`, `node-runtime`) + custom `policies/*.json` + local ESM plugins
91
+ - **CI mode** with JSON / NDJSON / GitHub annotations and fail rules
92
+ - **Snapshots & diffs** for deploy scripts and pre-commit hooks
93
+ - **Profiles** via `--profile` or `FLECTO_PROFILE`
94
+ - **Default array identity** (`id` / `name`, or `--array-id-key`) and secret masking
95
+
96
+ ---
97
+
98
+ ## Common use cases
99
+
100
+ ### Watch multiple files
50
101
 
51
102
  ```bash
52
103
  flecto watch "config/**/*.yaml" ".env"
53
104
  ```
54
105
 
55
- ### See detailed before/after values
106
+ ### Verbose before/after
56
107
 
57
108
  ```bash
58
109
  flecto watch config/prod.yaml --mode verbose
59
110
  ```
60
111
 
61
- ### Ignore noisy keys (like timestamps)
112
+ ### Ignore noisy keys
62
113
 
63
114
  ```bash
64
115
  flecto watch config/prod.yaml --ignore "updated_at,meta.timestamp"
65
116
  ```
66
117
 
67
- You can ignore exact keys, entire subtrees, wildcards, or keys anywhere in the file:
68
-
69
118
  | Pattern | What it ignores |
70
119
  |---|---|
71
120
  | `meta.timestamp` | That exact key |
@@ -73,21 +122,15 @@ You can ignore exact keys, entire subtrees, wildcards, or keys anywhere in the f
73
122
  | `servers[*].meta.timestamp` | That key inside any array item |
74
123
  | `**.updated_at` | Any key named `updated_at`, anywhere |
75
124
 
76
- ### Run a command when something changes
125
+ ### Run a command on change
77
126
 
78
127
  ```bash
79
128
  flecto watch .env --command "docker-compose restart app"
80
129
  ```
81
130
 
82
- Flecto passes the changes as JSON to your command via the `FLECTO_CHANGES` environment variable.
131
+ Changes are passed as JSON via `FLECTO_CHANGES` (large payloads may use `FLECTO_CHANGES_FILE`).
83
132
 
84
- ### Send changes to a webhook
85
-
86
- ```bash
87
- flecto watch config/prod.yaml --webhook https://hooks.example.com/notify
88
- ```
89
-
90
- Add auth headers if needed:
133
+ ### Webhooks
91
134
 
92
135
  ```bash
93
136
  flecto watch config/prod.yaml \
@@ -95,22 +138,145 @@ flecto watch config/prod.yaml \
95
138
  --webhook-header "Authorization: Bearer TOKEN"
96
139
  ```
97
140
 
98
- Each webhook payload includes a full event envelope:
141
+ Envelope shape (`schema_version: "2.0"`):
99
142
 
100
143
  ```json
101
144
  {
102
- "schema_version": "1.1",
145
+ "schema_version": "2.0",
103
146
  "event_id": "uuid",
104
147
  "event_type": "changes",
105
148
  "emitted_at": "2026-04-14T10:42:31.000Z",
106
149
  "file": "/absolute/path/to/config/prod.yaml",
107
150
  "changes": [
108
151
  { "type": "changed", "path": "database.pool_size", "before": 5, "after": 20 }
152
+ ],
153
+ "policies": [
154
+ {
155
+ "id": "pool-size-jump",
156
+ "severity": "warn",
157
+ "path": "database.pool_size",
158
+ "message": "Pool size increased from 5 to 20 (>=2x).",
159
+ "pack": "default"
160
+ }
109
161
  ]
110
162
  }
111
163
  ```
112
164
 
113
- ### Use both command and webhook together
165
+ JSON Schema: [`schemas/flecto-envelope-2.0.json`](schemas/flecto-envelope-2.0.json).
166
+
167
+ ### Policy packs and profiles
168
+
169
+ ```bash
170
+ flecto ci config/prod.yaml --profile prod --snapshot-ref HEAD~1
171
+ ```
172
+
173
+ ```json
174
+ {
175
+ "defaults": {
176
+ "policies": ["default"],
177
+ "maskSecrets": false
178
+ },
179
+ "profiles": {
180
+ "prod": {
181
+ "policies": ["default", "strict-prod"],
182
+ "severityRemap": { "pool-size-jump": "error" },
183
+ "maskSecrets": true
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ Profile selection: `--profile` > `FLECTO_PROFILE` > defaults.
190
+ Custom packs: `policies/<id>.json`. Plugins: local ESM exporting `evaluate(changes, ctx)`.
191
+
192
+ #### Declarative rule predicates
193
+
194
+ Rules combine their top-level predicates with AND. In addition to `when`, regex
195
+ `match.path`, `afterEquals`, and `numericJump`, packs can use:
196
+
197
+ - `beforeEquals`, `afterIn`, and `beforeIn` for exact values or allowed value lists.
198
+ - `beforeTruthy: true` and `afterTruthy: true` to require a truthy before/after value.
199
+ - `afterMatches` to require a string after value that matches a regular expression.
200
+ - `numericDelta: { "min": 10 }` to match an absolute numeric change of at least 10.
201
+ - `match.pathEquals` and `match.pathPrefix` for exact or prefix path matching without regex.
202
+ - `allOf` and `anyOf` arrays of simple match clauses. Every `allOf` clause and at least
203
+ one `anyOf` clause must match. Clauses support the same value, truthiness, numeric, and
204
+ `match` predicates, but cannot nest composition.
205
+
206
+ ```json
207
+ {
208
+ "id": "risky-feature-enable",
209
+ "severity": "error",
210
+ "allOf": [
211
+ { "match": { "pathPrefix": "features." } },
212
+ { "afterTruthy": true }
213
+ ],
214
+ "anyOf": [
215
+ { "afterEquals": true },
216
+ { "afterIn": ["unsafe", "disabled"] }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ Pack loading fails closed for unknown rule or `match` fields, invalid regexes, and invalid
222
+ predicate shapes, so misspelled predicates cannot silently disable a rule.
223
+
224
+ Use `severityRemap` in defaults or a profile to change pack rule severities without forking a pack:
225
+
226
+ ```json
227
+ {
228
+ "profiles": {
229
+ "dev": {
230
+ "severityRemap": { "pool-size-jump": "off" }
231
+ },
232
+ "prod": {
233
+ "severityRemap": { "pool-size-jump": "error" }
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ Each key is a rule id and each value must be `info`, `warn`, `error`, or `off`. The remap applies after all configured built-in and local packs load, before findings and CI `--fail-on` checks. When multiple packs provide the same rule id, the remap applies to every matching pack rule. Plugin findings are unchanged. Unknown rule ids print a warning instead of being ignored silently.
240
+
241
+ Authoring guides: [policy packs](docs/policy-packs.md) · [plugins](docs/plugins.md) · [plugin cookbook](docs/plugin-cookbook.md).
242
+
243
+ ### Discover policy packs
244
+
245
+ ```bash
246
+ flecto policies list
247
+ flecto policies list --json
248
+ ```
249
+
250
+ The command lists every bundled and local pack that resolves from the current
251
+ working directory, including its source path and rule count. For a given pack
252
+ id, Flecto resolves local files before bundled packs in this order:
253
+ `policies/<id>.json`, `policies/<id>.yaml`, `policies/<id>.yml`, then the
254
+ built-in pack. A local pack with the same id overrides its built-in counterpart.
255
+
256
+ ### Array identity matching
257
+
258
+ ```bash
259
+ flecto watch config/services.yaml
260
+ ```
261
+
262
+ Arrays of objects automatically match by a shared, unique `id` key, falling back
263
+ to `name` when `id` is unavailable. This avoids false changes when named items
264
+ are reordered. Use a custom identity field when needed:
265
+
266
+ ```bash
267
+ flecto watch config/services.yaml --array-id-key serviceKey
268
+ ```
269
+
270
+ To restore index-based diffs for every array, pass `--no-array-id`:
271
+
272
+ ```bash
273
+ flecto watch config/services.yaml --no-array-id
274
+ ```
275
+
276
+ In `.flectorc`, set `"arrayId": false` in `defaults` or a profile for the same
277
+ escape hatch.
278
+
279
+ ### Command + webhook together
114
280
 
115
281
  ```bash
116
282
  flecto watch .env \
@@ -129,37 +295,26 @@ flecto watch config/prod.yaml \
129
295
 
130
296
  | Flag | Options | What it does |
131
297
  |---|---|---|
132
- | `--delivery-mode` | `best-effort` (default), `at-least-once` | Whether to persist and retry failed webhook events |
133
- | `--on-alert-failure` | `warn`, `exit`, `retry` | What happens if a command or webhook fails |
298
+ | `--delivery-mode` | `best-effort` (default), `at-least-once` | Persist and retry failed webhook events |
299
+ | `--on-alert-failure` | `warn`, `exit`, `retry` | Behavior when command/webhook fails |
134
300
 
135
301
  ---
136
302
 
137
- ## Snapshots & Diffs
138
-
139
- Save a baseline snapshot of your file:
303
+ ## Snapshots & diffs
140
304
 
141
305
  ```bash
142
306
  flecto watch config/prod.yaml --snapshot
143
- # Saved to .flecto-snapshots/<id>.json
144
- ```
145
-
146
- Then compare the current file against it anytime:
147
-
148
- ```bash
149
307
  flecto watch config/prod.yaml --diff
308
+ flecto history config/prod.yaml --limit 10
150
309
  ```
151
310
 
152
- Exit codes:
153
- - `0` — no changes (file is clean)
154
- - `1` — changes detected
311
+ Exit codes: `0` clean · `1` changes detected.
155
312
 
156
- This is useful in deployment scripts and pre-commit hooks.
313
+ `flecto history` stays local: it lists recent snapshots from `.flecto-snapshots/` with their timestamps and semantic change counts from the previous snapshot. Counts use the same ignore paths, array identity, and order settings as `flecto watch --diff` (CLI flags or `.flectorc`). Omit files to view all saved snapshot history.
157
314
 
158
315
  ---
159
316
 
160
- ## CI Mode
161
-
162
- Catch risky config changes before they ship:
317
+ ## CI mode
163
318
 
164
319
  ```bash
165
320
  flecto ci "config/**/*.yaml" \
@@ -168,49 +323,84 @@ flecto ci "config/**/*.yaml" \
168
323
  --fail-on "changed,policy,error"
169
324
  ```
170
325
 
171
- **Output formats:** `json`, `ndjson`, `github-annotations`
326
+ **Formats:** `json`, `ndjson`, `github-annotations`
327
+ **Fail triggers:** `changed`, `added`, `removed`, `policy`, `error`, `warn`
328
+ Unresolved `--snapshot-ref` fails closed (no silent empty baseline).
329
+ If every target is missing or unsupported, `flecto ci` and `flecto watch --snapshot` exit non-zero (pass `--allow-empty` to opt out).
330
+
331
+ ### GitHub Action
172
332
 
173
- **Fail triggers:** `changed`, `added`, `removed`, `policy`, `error`, `warn`
333
+ Use the [Flecto CI Action](.github/actions/flecto-ci/action.yml) to run `flecto ci` in a workflow with GitHub annotations enabled by default. A complete local-action workflow is available at [`examples/github-action/flecto-ci.yml`](examples/github-action/flecto-ci.yml).
334
+
335
+ ```yaml
336
+ permissions:
337
+ contents: read
338
+
339
+ steps:
340
+ - uses: actions/checkout@v7
341
+ with:
342
+ fetch-depth: 2
343
+ - uses: myselfsiddharth/Flecto/.github/actions/flecto-ci@main
344
+ with:
345
+ targets: config/**/*.{yaml,yml,json,toml,ini}
346
+ snapshot-ref: HEAD~1
347
+ ```
348
+
349
+ `contents: read` is required by `actions/checkout`. The Action emits workflow-command annotations and needs no write permissions. Keep `fetch-depth: 2` (or use `fetch-depth: 0`) when using the default `HEAD~1` baseline.
350
+
351
+ | Input | Default | Description |
352
+ |---|---|---|
353
+ | `targets` | `config/**/*.{yaml,yml,json,toml,ini}` | Whitespace-separated paths or glob patterns to check |
354
+ | `fail-on` | `policy,error` | Comma-separated events that fail the job |
355
+ | `policies` | _(empty)_ | Comma-separated policy pack IDs; omit to use `.flectorc` / Flecto defaults |
356
+ | `profile` | _(empty)_ | Optional `.flectorc` profile |
357
+ | `format` | `github-annotations` | Flecto output format |
358
+ | `snapshot-ref` | `HEAD~1` | Git ref or snapshot file used as the baseline |
359
+ | `node-version` | `20` | Node.js version used to run Flecto |
360
+
361
+ The Action runs `npx --yes flecto@2 ci`: the major version is pinned so compatible Flecto updates are received. For fully reproducible builds, pin the Action reference to a commit SHA and replace `@2` in a forked Action with an exact published Flecto version.
174
362
 
175
363
  ---
176
364
 
177
- ## Built-in Policy Checks
365
+ ## Built-in policy checks
178
366
 
179
- Flecto automatically flags changes that look risky:
367
+ Built-in pack ids:
180
368
 
181
- - 🔑 **Secrets touched** keys named `secret`, `token`, `password`, `api_key`, etc.
182
- - ⚠️ **Dangerous toggles** `debug: true`, `disable_tls`, `skip_tls_verify`, `allow_insecure`
183
- - 📈 **Large pool size jumps** `pool_size` doubled or more
369
+ - `default`secrets, dangerous toggles, and pool-size jumps.
370
+ - `strict-prod` stricter severities and matching for production use.
371
+ - `compose` privileged services, host networking, Docker socket mounts, and sensitive host-directory bind mounts.
372
+ - `node-runtime` — removed Node.js engine requirements, TLS verification bypasses, and enabled Node debugging or inspector options.
184
373
 
185
- Policy violations can fail your CI pipeline with `--fail-on policy`.
374
+ Fail CI with `--fail-on policy`.
186
375
 
187
376
  ---
188
377
 
189
- ## Tuning for Network Drives or Odd Editors
378
+ ## Migrating from envelope 1.1
190
379
 
191
- Some editors write files via a temp file swap, which can confuse standard watchers. Enable polling mode:
380
+ - `schema_version` is now `"2.0"`
381
+ - Type name is `FlectoEnvelope` (docs/types)
382
+ - New `policies` array on change envelopes
383
+ - Webhook headers unchanged (`X-Flecto-*`)
384
+
385
+ ---
386
+
387
+ ## Tuning for network drives / odd editors
192
388
 
193
389
  ```bash
194
390
  flecto watch config/prod.yaml --polling --interval 500
195
391
  ```
196
392
 
197
- Default polling interval is `100ms`. Polling is off by default.
393
+ Polling is off by default (interval default `100ms` when enabled).
198
394
 
199
395
  ---
200
396
 
201
- ## Config File (.flectorc)
202
-
203
- Set your defaults once so you don't have to repeat flags every time.
204
-
205
- Generate a starter config:
397
+ ## Config file (`.flectorc`)
206
398
 
207
399
  ```bash
208
400
  flecto init
209
401
  ```
210
402
 
211
- Flecto looks for `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
212
-
213
- Example:
403
+ Looks for `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
214
404
 
215
405
  ```json
216
406
  {
@@ -219,35 +409,35 @@ Example:
219
409
  "interval": 100,
220
410
  "ignore": ["**.updated_at"],
221
411
  "deliveryMode": "best-effort",
222
- "onAlertFailure": "warn"
412
+ "onAlertFailure": "warn",
413
+ "policies": ["default"],
414
+ "arrayId": true
223
415
  },
224
416
  "profiles": {
225
417
  "dev": { "mode": "verbose" },
226
- "ci": { "failOn": "policy,error" }
418
+ "ci": { "failOn": "policy,error" },
419
+ "prod": {
420
+ "policies": ["default", "strict-prod"],
421
+ "severityRemap": { "pool-size-jump": "error" },
422
+ "maskSecrets": true
423
+ }
227
424
  },
228
- "files": ["config/**/*.yaml", ".env"],
425
+ "files": ["config/**/*.{yaml,yml,json,toml,ini}", ".env", ".env.*", "*.env"],
229
426
  "exclude": ["**/node_modules/**"]
230
427
  }
231
428
  ```
232
429
 
233
- Use a named profile:
234
-
235
430
  ```bash
236
431
  flecto watch --profile dev
237
432
  flecto ci --profile ci
238
- ```
239
-
240
- CLI flags always override profile/default values.
241
-
242
- Verify your setup:
243
-
244
- ```bash
245
433
  flecto doctor
246
434
  ```
247
435
 
436
+ CLI flags override profile/default values.
437
+
248
438
  ---
249
439
 
250
- ## Output Format Reference
440
+ ## Output format reference
251
441
 
252
442
  ### Compact (default)
253
443
 
@@ -265,47 +455,45 @@ flecto doctor
265
455
  ~ path
266
456
  before: old_value
267
457
  after: new_value
268
- + path: value
269
- (key added)
270
458
  ```
271
459
 
272
460
  ---
273
461
 
274
- ## Error Handling
275
-
276
- Flecto is designed to keep running even when things go wrong:
462
+ ## Error handling
277
463
 
278
464
  | Situation | Behavior |
279
465
  |---|---|
280
- | File not found | Error message + exit 1 |
281
- | Unsupported file format | Lists supported extensions + exit 1 |
282
- | File has a parse error | Warning shown, last valid state kept, watching continues |
283
- | Command fails | Warning shown, watcher continues |
284
- | Webhook fails | Warning shown, watcher continues |
285
- | Ctrl+C | Clean shutdown message |
466
+ | File not found | Error + exit 1 |
467
+ | Unsupported format | Lists supported extensions + exit 1 |
468
+ | Parse error while watching | Warning, last valid state kept |
469
+ | Command / webhook fails | Warning (unless `--on-alert-failure exit`) |
470
+ | Ctrl+C | Clean shutdown |
286
471
 
287
472
  ---
288
473
 
289
- ## Running Tests
474
+ ## How it works
290
475
 
291
- ```bash
292
- npm test
293
- # or directly:
294
- node --test test/*.test.js
295
- ```
476
+ 1. **Parser** — format by extension / dotenv naming → structured values
477
+ 2. **Watcher** — [chokidar](https://github.com/paulmillr/chokidar) + debounce
478
+ 3. **Differ** — semantic tree diff (objects, arrays, ignore rules, automatic array ids)
479
+ 4. **Policy engine** — packs + plugins → severity findings
480
+ 5. **Envelope** — versioned automation payload (`2.0`)
481
+ 6. **Alerter** — command and/or webhook with retry modes
482
+
483
+ ---
484
+
485
+ ## Contributing
486
+
487
+ Flecto is open source. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, PR rules, and review expectations.
488
+ Please read the [Code of Conduct](CODE_OF_CONDUCT.md) and [Security policy](SECURITY.md).
296
489
 
297
- Tests cover the differ, watcher behavior, webhook delivery, policy logic, and CI command behavior.
490
+ Roadmap lives in [GitHub milestones](https://github.com/myselfsiddharth/Flecto/milestones).
298
491
 
299
492
  ---
300
493
 
301
- ## How It Works
494
+ ## Star the project
302
495
 
303
- 1. **Parser** detects the file format by extension and parses it into structured JS values.
304
- 2. **Watcher** — uses [chokidar](https://github.com/paulmillr/chokidar) with debouncing so rapid saves don't flood you with events.
305
- 3. **Differ** — computes a semantic diff (not a line diff), supporting objects, arrays, scalars, and ignore rules.
306
- 4. **Policy engine** — inspects the changes for patterns that look risky and adds severity findings.
307
- 5. **Envelope** — wraps each batch of changes in a versioned event schema ready for automation.
308
- 6. **Alerter** — delivers events via command execution and/or webhook, with configurable retry logic.
496
+ If Flecto helps your team catch a risky config change **[star the repo](https://github.com/myselfsiddharth/Flecto)** so more people can find it.
309
497
 
310
498
  ---
311
499