@datarails-ai/dr-cli 0.0.1-locked → 1.6.71
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 +608 -0
- package/dist/chunk-DWMCBGQH.js +242 -0
- package/dist/cli.js +64468 -0
- package/dist/kb-6UWI7Q32.js +21 -0
- package/dist/scopes-map.json +4412 -0
- package/dist/skills/connector-sandbox/SKILL.md +95 -0
- package/dist/skills/datarails-connect-workato/SKILL.md +140 -0
- package/dist/skills/datarails-connectors-onboard-connector/SKILL.md +813 -0
- package/dist/skills/dr-cli/SKILL.md +659 -0
- package/dist/skills/dr-cli/reference/admin.md +796 -0
- package/dist/skills/dr-cli/reference/budget-builder.md +151 -0
- package/dist/skills/dr-cli/reference/calc-vals.md +73 -0
- package/dist/skills/dr-cli/reference/calcmodels.md +76 -0
- package/dist/skills/dr-cli/reference/cash.md +61 -0
- package/dist/skills/dr-cli/reference/dashboards-widgets.md +85 -0
- package/dist/skills/dr-cli/reference/datamappers.md +150 -0
- package/dist/skills/dr-cli/reference/desk.md +472 -0
- package/dist/skills/dr-cli/reference/filebox-documents.md +373 -0
- package/dist/skills/dr-cli/reference/forecast.md +51 -0
- package/dist/skills/dr-cli/reference/integrations.md +57 -0
- package/dist/skills/dr-cli/reference/lookups.md +168 -0
- package/dist/skills/dr-cli/reference/metrics.md +512 -0
- package/dist/skills/dr-cli/reference/multi-product.md +180 -0
- package/dist/skills/dr-cli/reference/reconciliation-mec.md +76 -0
- package/dist/skills/dr-cli/reference/rh-config.md +84 -0
- package/dist/skills/dr-cli/reference/safety.md +143 -0
- package/dist/skills/dr-cli/reference/spend-control.md +206 -0
- package/dist/skills/dr-cli/reference/templates.md +163 -0
- package/dist/skills/dr-cli/reference/workflows.md +137 -0
- package/dist/skills/dr-error-enrichment/SKILL.md +80 -0
- package/dist/skills/dr-error-enrichment/reference/core.md +257 -0
- package/dist/skills/dr-error-enrichment/reference/groundcover.md +84 -0
- package/dist/skills/dr-error-enrichment/reference/jira-bugs.md +219 -0
- package/dist/skills/dr-error-enrichment/reference/safety-backup.md +122 -0
- package/dist/skills/dr-error-enrichment-author/SKILL.md +219 -0
- package/dist/skills/dr-error-enrichment-improve/SKILL.md +218 -0
- package/dist/skills/dr-error-enrichment-maintain/SKILL.md +237 -0
- package/dist/skills/dr-error-enrichment-reconcile/SKILL.md +167 -0
- package/dist/skills/dr-filebox-api-setup/SKILL.md +170 -0
- package/dist/skills/dr-switch-user/SKILL.md +395 -0
- package/dist/skills/dr-validate/SKILL.md +392 -0
- package/dist/skills/dr-validate/report-template.html +950 -0
- package/dist/skills/fx-conversion-matrix/SKILL.md +763 -0
- package/dist/skills/fx-conversion-matrix/scripts/_args.mjs +52 -0
- package/dist/skills/fx-conversion-matrix/scripts/_xlsx.mjs +241 -0
- package/dist/skills/fx-conversion-matrix/scripts/build-matrix.mjs +366 -0
- package/dist/skills/fx-conversion-matrix/scripts/gen-mappers.mjs +171 -0
- package/dist/skills/fx-conversion-matrix/scripts/rates-to-xlsx.mjs +172 -0
- package/dist/skills/fx-onboard/SKILL.md +325 -0
- package/dist/skills/mec-table-validation/SKILL.md +383 -0
- package/dist/skills/plugins.json +24 -0
- package/dist/skills/validate-workato-migration/SKILL.md +167 -0
- package/dist/skills/validate-workato-migration/reference/gotchas.md +16 -0
- package/dist/skills/validate-workato-migration/reference/staging-orgs.md +26 -0
- package/dist/skills/validate-workato-migration/scripts/compare_files.py +255 -0
- package/dist/zendeskKb-JPSHVOPH.js +243 -0
- package/package.json +56 -9
- package/scripts/postinstall.mjs +91 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Safety and backup — invariants, write gating, import policy
|
|
2
|
+
|
|
3
|
+
Read [the `dr-cli` skill's reference/safety.md](../../dr-cli/reference/safety.md)
|
|
4
|
+
for the underlying confirm-token and prod-gate mechanics. That file lives in the
|
|
5
|
+
`dr-cli` skill, not this one — this skill's safety file is the one you are
|
|
6
|
+
reading.
|
|
7
|
+
|
|
8
|
+
## Three invariants for every server-modifying run
|
|
9
|
+
|
|
10
|
+
**1. Confirm the target server explicitly.** Ask (AskUserQuestion) which server
|
|
11
|
+
to change — never infer it from earlier context in the conversation. Prod keys
|
|
12
|
+
are `US`, `US2`, `UK`, `CA`, `EU`, `DEMO` (DEMO is customer-facing prod, not a
|
|
13
|
+
sandbox). Demonstrate on `DEV` / `TEST-*` first when the user is undecided.
|
|
14
|
+
|
|
15
|
+
**2. Back up every reachable server first.** Before the first write of a
|
|
16
|
+
session, one command — `export` takes the same sweep flags as `list` / `stats`,
|
|
17
|
+
and `--out` is a **directory** when sweeping, one `<SERVER>.csv` per server:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
dr error-enrichments export --all-servers --out ~/dr-enrichment-backups/$(date -u +%Y-%m-%dT%H%M%SZ)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Back up **all** servers, not just the target: a reconcile session usually
|
|
24
|
+
touches more than one, and the diff baseline is worth as much as the restore.
|
|
25
|
+
Use `--servers A,B` to narrow it deliberately, and `--include-test` to pull
|
|
26
|
+
`DEV` / `TEST-*` in as well. `--out` is **required** when sweeping and must name
|
|
27
|
+
a directory — concatenating N servers into one CSV produces N header rows that
|
|
28
|
+
`import` cannot read back, which is the one thing a backup has to survive.
|
|
29
|
+
|
|
30
|
+
**Report which servers actually backed up, before the first write.** The sweep
|
|
31
|
+
writes the files it could and keeps going, printing one stdout line per server —
|
|
32
|
+
`Wrote N rules to <dir>/<SERVER>.csv` for the ones that worked, and a
|
|
33
|
+
`<SERVER> — skipped: …` / `<SERVER> — error: …` line for the ones that did not.
|
|
34
|
+
A server with no stored keychain identity is **skipped** and does **not** make
|
|
35
|
+
the command fail; only a real export failure does. So exit 0 is *not*
|
|
36
|
+
"everything is backed up" — read the per-server lines and tell the user by name
|
|
37
|
+
which servers have a CSV and which do not. A server you are about to write to
|
|
38
|
+
with no backup of its own has no revert path and no diff baseline: fix the login,
|
|
39
|
+
or get an explicit decision to proceed without one, before writing to it.
|
|
40
|
+
|
|
41
|
+
A single server still works the way it always did — `export --server <S> --out
|
|
42
|
+
<file>.csv`, where `--out` is a plain file. Use that only when you have
|
|
43
|
+
deliberately narrowed the scope to one server. Do **not** rebuild the sweep as a
|
|
44
|
+
shell loop: a loop that ends each iteration in `|| echo "skip $S"` turns a failed
|
|
45
|
+
export into one quiet line, and a server with no backup then reads exactly like
|
|
46
|
+
a server with one.
|
|
47
|
+
|
|
48
|
+
**3. Know the revert path before you need it — and prefer the surgical one.**
|
|
49
|
+
The CSV backup carries `id`, so a revert is a per-rule replay:
|
|
50
|
+
|
|
51
|
+
- rule changed → `update <id>` back to the backed-up field values
|
|
52
|
+
- rule you created → `delete <id>`
|
|
53
|
+
- rule you deleted → `create` from the backed-up row (it returns a **new id**)
|
|
54
|
+
|
|
55
|
+
Batch forms make this cheap: one `update --payload-file` with an array of
|
|
56
|
+
`{id, ...original fields}` undoes a whole batch in a single confirmed run.
|
|
57
|
+
Do **not** reach for `import` to undo anything — see the import policy below.
|
|
58
|
+
|
|
59
|
+
## Write gating
|
|
60
|
+
|
|
61
|
+
Every mutation is two-step: run it without `--confirm-token`, relay the printed
|
|
62
|
+
plan to the user, then re-run with the token. Tiers (`src/commands/_prodGateTiers.ts`):
|
|
63
|
+
|
|
64
|
+
- **`create` / `update` — Tier B.** Token only, on every server. Batch forms are
|
|
65
|
+
tiered separately (`error-enrichment-batch|create`, `error-enrichment-batch|update`)
|
|
66
|
+
and are **also Tier B**: a single token covers the whole set.
|
|
67
|
+
- **`delete` / `import` — Tier A.** On a prod server the binary additionally
|
|
68
|
+
demands a challenge word typed by a human in a desktop dialog or TTY; it
|
|
69
|
+
refuses non-zero in a headless shell. Don't invent a chat-side word ritual —
|
|
70
|
+
get the user's "yes", re-run with the token, and let the binary prompt them.
|
|
71
|
+
A batch `delete` (`error-enrichment-batch|delete`) is Tier A too, and **one**
|
|
72
|
+
gate covers the whole set — which is exactly why the plan's per-rule lines have
|
|
73
|
+
to be read rule by rule rather than counted.
|
|
74
|
+
|
|
75
|
+
A batch write binds its token to the targets *and* the field values, so an edited
|
|
76
|
+
payload file invalidates it; a single-target write binds the target only, so an
|
|
77
|
+
edited field flag does **not**. The full rule is in
|
|
78
|
+
[core.md](core.md) under *Confirm-token binding* — read it before you reuse any
|
|
79
|
+
token.
|
|
80
|
+
|
|
81
|
+
## Import policy
|
|
82
|
+
|
|
83
|
+
**Default to `update` / `create` for every fleet change.** Batch `update` (shared
|
|
84
|
+
patch or per-rule array) and batch `create` cover reconcile, approval sweeps, and
|
|
85
|
+
message rewrites — that is what they exist for. `import` is not part of the
|
|
86
|
+
normal loop and must not be selected on your own initiative, however convenient
|
|
87
|
+
the CSV looks.
|
|
88
|
+
|
|
89
|
+
Use `import` **only when the user explicitly asks for it by name** (a genuine
|
|
90
|
+
restore-from-catastrophe). Even then, before running it, state plainly that
|
|
91
|
+
`import` is wipe-and-replace — the server deletes **every** rule on that server
|
|
92
|
+
and bulk-creates from the CSV — and that it therefore:
|
|
93
|
+
|
|
94
|
+
- **resets `hits`, `thumbs_up`, and `thumbs_down` to 0.** The import path ignores
|
|
95
|
+
those columns. That is the feedback history the whole maintenance flow runs on:
|
|
96
|
+
no hits means no `needs_attention` list, no `top_hits`, no thumbs-down ranking,
|
|
97
|
+
and the loss is permanent — nothing recomputes it.
|
|
98
|
+
- **assigns brand-new ids.** The `id` column in the CSV is not honoured, so every
|
|
99
|
+
rule id on that server changes and any id quoted earlier in the conversation,
|
|
100
|
+
in a ticket, or in another server's mapping goes stale.
|
|
101
|
+
- **drops server-only rules** that are not in the CSV.
|
|
102
|
+
|
|
103
|
+
Then get an explicit confirmation of *that* — the analytics loss specifically —
|
|
104
|
+
before running it. If the user's actual goal was "make server B look like server
|
|
105
|
+
A", say so and offer the per-rule route instead.
|
|
106
|
+
|
|
107
|
+
## Batch-write etiquette
|
|
108
|
+
|
|
109
|
+
- **Relay the whole plan.** It names every affected rule — a batch `delete` prints
|
|
110
|
+
one compact line per rule, counters included — and a summarised "12 rules" hides
|
|
111
|
+
the one wrong id. Paste the list.
|
|
112
|
+
- **One server per run.** Keep a fleet change as N separate confirmed runs so each
|
|
113
|
+
server's plan is reviewed against that server's current state.
|
|
114
|
+
- **Re-read the summary table after execution.** The run continues past failures
|
|
115
|
+
and exits non-zero, so the summary — not the exit code, not the plan — is the
|
|
116
|
+
record of what landed and which new ids `create` returned. Retry only the failed
|
|
117
|
+
ids.
|
|
118
|
+
- **Verify after writing** with `dr error-enrichments get <ids...> --server <S>`,
|
|
119
|
+
which takes the same id list you just wrote. With `--json`, remember the shape
|
|
120
|
+
flips: a bare object for one id, an array for two or more, and an id that failed
|
|
121
|
+
to read is missing from the array rather than represented in it — check the exit
|
|
122
|
+
code and the stderr warnings, not just the payload ([core.md](core.md)).
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dr-error-enrichment-author
|
|
3
|
+
description: Author, edit, or delete integration error-enrichment rules — the regex-to-readable-message rules Datarails shows a user when a sync fails. Drafts and server-validates the pattern, gets the customer-facing wording signed off, picks a rank, writes it through the confirm gate, and offers propagation to the other servers. Reviewing and approving existing drafts belongs to dr-error-enrichment-maintain, not here. Use when a specific error needs a rule, or an existing rule needs fixing or removing. Triggers - "add an error enrichment rule", "make this error message readable", "fix the wording of this error", "this error shows no explanation", "why does this integration error show no explanation", "delete an enrichment rule", "test this error regex", "the regex isn't matching".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dr-error-enrichment-author — author, edit, or delete a rule
|
|
7
|
+
|
|
8
|
+
## Read first
|
|
9
|
+
|
|
10
|
+
This flow assumes both shared references and does not repeat them:
|
|
11
|
+
|
|
12
|
+
- [../dr-error-enrichment/reference/core.md](../dr-error-enrichment/reference/core.md)
|
|
13
|
+
— what a rule is, permissions, the full `dr error-enrichments` command surface,
|
|
14
|
+
how matching actually works (`re.match` anchoring, rank order, drafts stealing
|
|
15
|
+
the hit), where to get raw error text off a tenant.
|
|
16
|
+
- [../dr-error-enrichment/reference/safety-backup.md](../dr-error-enrichment/reference/safety-backup.md)
|
|
17
|
+
— confirming the target server, backing up before the first write, the revert
|
|
18
|
+
path, the Tier A/B write gates, and why `import` is never an edit tool.
|
|
19
|
+
|
|
20
|
+
Confirm the target server and take the backup **before** step 8 below, not after:
|
|
21
|
+
`dr error-enrichments export --server <S> --out /tmp/ee-<S>.csv` for the one
|
|
22
|
+
server you are writing to, or
|
|
23
|
+
`dr error-enrichments export --all-servers --out /tmp/ee-backup/` (with a sweep
|
|
24
|
+
`--out` is a directory, one `<SERVER>.csv` per server) when the session is likely
|
|
25
|
+
to spread to the fleet.
|
|
26
|
+
|
|
27
|
+
## Authoring flow
|
|
28
|
+
|
|
29
|
+
1. **Get real samples.** Ask for the raw error text. If the user only names a
|
|
30
|
+
symptom, pull samples from the tenant (`integrations get`,
|
|
31
|
+
`integrations query-status --json`) or mine groundcover — the query mechanics
|
|
32
|
+
and the env-to-server mapping are in
|
|
33
|
+
[../dr-error-enrichment/reference/groundcover.md](../dr-error-enrichment/reference/groundcover.md),
|
|
34
|
+
and `dr-error-enrichment-improve` is the flow built on it. A rule written from
|
|
35
|
+
a paraphrase matches nothing.
|
|
36
|
+
|
|
37
|
+
2. **Check for an existing rule first.** A near-miss rule is usually better
|
|
38
|
+
edited than duplicated:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
dr error-enrichments list --server <S> --integration-type <T> --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Read what the vendor already covers, so the rank you pick next doesn't
|
|
45
|
+
shadow a good rule.
|
|
46
|
+
|
|
47
|
+
3. **Draft the pattern** with a leading `.*` and escaped metacharacters, keeping
|
|
48
|
+
the volatile parts (ids, paths, hostnames, quantities) as `.*` or character
|
|
49
|
+
classes so it generalises past this one sample.
|
|
50
|
+
|
|
51
|
+
4. **Validate it server-side** against the real samples plus at least one error
|
|
52
|
+
that must *not* match:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
dr error-enrichments test-regex --server <S> --pattern '.*INVALID_LOGIN.*' \
|
|
56
|
+
--sample 'Error: INVALID_LOGIN for user x' --sample 'Unrelated timeout'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Iterate until matches and non-matches are both right. `valid: false` means
|
|
60
|
+
the regex itself doesn't compile. `test-regex` runs the same `re.match` plus
|
|
61
|
+
newline-stripping the resolver does — trust it over local regex reasoning,
|
|
62
|
+
and never hand-verify a pattern you could test.
|
|
63
|
+
|
|
64
|
+
5. **Draft the message and steps.** `description` states what went wrong in the
|
|
65
|
+
customer's language — no stack traces, no internal identifiers, no vendor
|
|
66
|
+
error code as the whole message. `resolution_steps` are ordered, concrete
|
|
67
|
+
actions the customer or CSM can actually take. Propose both to the user and
|
|
68
|
+
let them approve the wording; this text ships to customers.
|
|
69
|
+
|
|
70
|
+
6. **Pick a rank.** Rank is priority within the vendor: specific rules above
|
|
71
|
+
general catch-alls, or the general one matches first and hides the better
|
|
72
|
+
message. The server shifts the sibling rows to make room — pass the rank you
|
|
73
|
+
want and never renumber siblings by hand.
|
|
74
|
+
|
|
75
|
+
7. **Set `classification`** (`DataSource` | `Filebox` | `Unclassified`) and
|
|
76
|
+
decide `approved`. Create as a draft (`--approved false`) only when the
|
|
77
|
+
pattern still needs field validation, and say out loud what that costs: a
|
|
78
|
+
draft steals the hit from any lower-ranked approved rule and shows the user
|
|
79
|
+
nothing, so a draft left in place is an active user-facing gap, not a
|
|
80
|
+
harmless staging state.
|
|
81
|
+
|
|
82
|
+
8. **Write it** through the two-step confirm (run without `--confirm-token`,
|
|
83
|
+
relay the plan, re-run with the token), then verify:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
dr error-enrichments get <id> --server <S>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
9. **Propagate.** A rule worth adding on one server is almost always worth
|
|
90
|
+
adding on the others. Offer `dr-error-enrichment-reconcile` rather than
|
|
91
|
+
leaving the fleet inconsistent.
|
|
92
|
+
|
|
93
|
+
## Several rules in one pass
|
|
94
|
+
|
|
95
|
+
The CRUD subcommands take batches. Same gating, same plan-then-token cycle —
|
|
96
|
+
one confirm covers the batch.
|
|
97
|
+
|
|
98
|
+
**Create many.** `--payload-file` accepts either one rule object (as before) or
|
|
99
|
+
an **array** of rule objects:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
cat > /tmp/new-rules.json <<'JSON'
|
|
103
|
+
[
|
|
104
|
+
{"integration_type": "NetSuite", "rank": 3, "re_pattern": ".*INVALID_LOGIN.*",
|
|
105
|
+
"description": "...", "resolution_steps": ["...", "..."], "approved": true},
|
|
106
|
+
{"integration_type": "NetSuite", "rank": 4, "re_pattern": ".*SSS_INVALID_SCRIPT.*",
|
|
107
|
+
"description": "...", "resolution_steps": ["..."], "approved": false}
|
|
108
|
+
]
|
|
109
|
+
JSON
|
|
110
|
+
dr error-enrichments create --payload-file /tmp/new-rules.json --server <S>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**One patch across several rules** — positional ids, field flags applied to
|
|
114
|
+
every id:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
dr error-enrichments update 12 19 24 --approved true --server <S>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
That `--approved true` form is **the last step of the approval protocol, not a
|
|
121
|
+
shortcut past it**. `dr-error-enrichment-maintain` owns approval: it pulls each
|
|
122
|
+
draft, shows it to the user against approved siblings for the same vendor, tests
|
|
123
|
+
the pattern against a real sample, and takes a per-rule confirmation. Only drafts
|
|
124
|
+
that have each been through that cycle may be flipped together here. If the
|
|
125
|
+
request that reached you is "approve rules 12, 19 and 24", the answer is to run
|
|
126
|
+
the maintain protocol first — never to run this line.
|
|
127
|
+
|
|
128
|
+
`--rank` is rejected with several ids: rank is a per-rule priority within a
|
|
129
|
+
vendor and the server shifts siblings on every change, so one shared rank across
|
|
130
|
+
several rules is never what you meant. Change ranks one rule at a time, or give
|
|
131
|
+
each rule its own rank in an array payload.
|
|
132
|
+
|
|
133
|
+
**A different patch per rule** — an **array** of `{id, ...fields}` entries and
|
|
134
|
+
no positional ids:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
cat > /tmp/patches.json <<'JSON'
|
|
138
|
+
[
|
|
139
|
+
{"id": 12, "rank": 2},
|
|
140
|
+
{"id": 19, "description": "...", "resolution_steps": ["..."]}
|
|
141
|
+
]
|
|
142
|
+
JSON
|
|
143
|
+
dr error-enrichments update --payload-file /tmp/patches.json --server <S>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Several deletions under one gate:**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
dr error-enrichments delete 31 32 33 --server <S>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The delete plan prints one compact line per rule — id, integration type, rank,
|
|
153
|
+
pattern, and the hits/thumbs counters — so relay the plan verbatim: that block is
|
|
154
|
+
the user's only view of what is about to be destroyed.
|
|
155
|
+
|
|
156
|
+
Verify a batch afterwards with the same id list:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
dr error-enrichments get 12 19 24 --json --server <S>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`get --json` returns a bare object for one id and an **array** for two or more,
|
|
163
|
+
so parse accordingly.
|
|
164
|
+
|
|
165
|
+
Four things to hold onto with batches:
|
|
166
|
+
|
|
167
|
+
- **A failure does not stop the run.** Each item is sent in turn, per-item
|
|
168
|
+
failures are recorded, and the command prints a summary table naming what
|
|
169
|
+
succeeded (with the new id for each created rule) and what failed, then exits
|
|
170
|
+
non-zero. The table — not the exit code — is what tells you which items
|
|
171
|
+
actually landed; retry only those.
|
|
172
|
+
- **The confirm token binds the field values too.** A batch plan hashes the
|
|
173
|
+
targets *and* the values being written, so editing the payload file or changing
|
|
174
|
+
a field flag between plan and confirm invalidates the token — re-run the plan
|
|
175
|
+
step and relay the new plan. (A single-target write binds only its target, as
|
|
176
|
+
it always has, so the same care applies there by hand.)
|
|
177
|
+
- **Array entries are validated before anything is sent.** A wrong field type or
|
|
178
|
+
a repeated id is rejected up front, and the message names the offending entry
|
|
179
|
+
by its position in the file (`entry 3: …`) — fix that entry and re-plan rather
|
|
180
|
+
than retrying with the old token.
|
|
181
|
+
- **A bulk create into one `integration_type` shifts that vendor's ranks.** Each
|
|
182
|
+
insert makes room for itself, so ranks you assumed while drafting may not be
|
|
183
|
+
the ranks you end up with. Re-run
|
|
184
|
+
`dr error-enrichments list --server <S> --integration-type <T> --json`
|
|
185
|
+
afterwards and check the order is what you intended.
|
|
186
|
+
|
|
187
|
+
Batch writes are still one server per run — there is no cross-server write.
|
|
188
|
+
|
|
189
|
+
## Deleting a rule
|
|
190
|
+
|
|
191
|
+
Show the user the rule's `hits`, `thumbs_up`, and `thumbs_down` from the plan
|
|
192
|
+
step before confirming. A rule with meaningful hits is usually better re-pointed
|
|
193
|
+
with `update` (new pattern, better wording) than deleted, because deleting it
|
|
194
|
+
drops its feedback history with it — and that history is what
|
|
195
|
+
`dr-error-enrichment-maintain` ranks its work from. Delete is Tier A: on a prod
|
|
196
|
+
server the binary itself prompts a human for a challenge word, so get the user's
|
|
197
|
+
"yes", re-run with the token, and let the binary do the asking.
|
|
198
|
+
|
|
199
|
+
## Pitfalls
|
|
200
|
+
|
|
201
|
+
| Mistake | Fix |
|
|
202
|
+
|---|---|
|
|
203
|
+
| Pattern without a leading `.*` | `re.match` anchors at the start — write `.*NEEDLE.*` |
|
|
204
|
+
| Writing a pattern expecting `\n` | Newlines are stripped before matching; the error is one long line |
|
|
205
|
+
| Hand-verifying a regex you could test | `test-regex` runs the server's own matcher — use it, with a non-matching sample too |
|
|
206
|
+
| Pattern fitted to one sample | Generalise ids, paths, hostnames, quantities to `.*` or a character class |
|
|
207
|
+
| Adding a rule that duplicates a near-miss | `list --integration-type <T>` first; edit the existing rule instead |
|
|
208
|
+
| A general rule ranked above a specific one | The general one matches first and hides the better message — rank specific first |
|
|
209
|
+
| Renumbering siblings by hand after a rank change | The server shifts them; pass the rank you want and leave the rest alone |
|
|
210
|
+
| Leaving a draft in place "for now" | It steals the hit and shows nothing — approve it, fix it, or lower its rank |
|
|
211
|
+
| Vendor codes or stack traces in `description` | Customer-facing text — plain language, wording approved by the user |
|
|
212
|
+
| Expecting `--resolution-step` with no value to clear the steps | PATCH-omit semantics — clear with `--payload-file` and `{"resolution_steps": []}` |
|
|
213
|
+
| Reading only the exit code of a batch | It is non-zero if *any* item failed — read the summary table for what landed |
|
|
214
|
+
| Flipping `--approved true` over a list of drafts here | Approval is `dr-error-enrichment-maintain`'s protocol — one rule at a time, then batch the confirmed set |
|
|
215
|
+
| Re-using a batch token after editing the payload file | The batch token binds the values too; edit means re-plan |
|
|
216
|
+
| `--rank` with several positional ids | Rejected — ranks are per rule; use one id at a time or an array payload |
|
|
217
|
+
| Assuming drafted ranks survive a bulk create | Each insert shifts siblings; re-`list` the vendor afterwards |
|
|
218
|
+
| Deleting a rule with real hits | Re-point it with `update`; deleting discards the feedback history |
|
|
219
|
+
| Writing on one server and stopping | Offer `dr-error-enrichment-reconcile` — per-server drift is the problem this tooling exists to fix |
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dr-error-enrichment-improve
|
|
3
|
+
description: Continuous improvement for integration error enrichment - mine groundcover for sync errors that no rule matches yet, rank them by volume, triage out the ones caused by our own bugs, and turn the rest into proposed rules. Use when the user wants to know what the rule table is missing rather than to edit a rule they already have in mind. Triggers - "which errors have no rule", "find unmatched integration errors", "suggest new enrichment rules", "what should we add to the error enrichment rules", "mine groundcover for integration errors", "what are we not explaining to customers", "is this error a bug or a missing rule".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dr-error-enrichment-improve — find the errors nothing matches
|
|
7
|
+
|
|
8
|
+
This is the outward-looking pass of the error-enrichment family: every other flow
|
|
9
|
+
starts from a rule that exists, this one starts from the errors that have none.
|
|
10
|
+
You are not fixing a rule the user named — you are finding the errors that reach
|
|
11
|
+
customers with **no explanation at all**, ranking them by how much traffic they
|
|
12
|
+
represent, sorting out which of them are our own bugs, and proposing rules for
|
|
13
|
+
what is left.
|
|
14
|
+
|
|
15
|
+
That sort is not a formality. A rule is a message to a customer about something
|
|
16
|
+
they can act on; written over a defect of ours it tells them to fix what they
|
|
17
|
+
cannot, and it makes the defect stop looking like one. **Some candidates should
|
|
18
|
+
become bugs, not rules** — and a run that ends in three bug reports and no rules
|
|
19
|
+
did its job.
|
|
20
|
+
|
|
21
|
+
Authoring the chosen rules is `dr-error-enrichment-author`. Approving drafts and
|
|
22
|
+
fixing disliked rules is `dr-error-enrichment-maintain`.
|
|
23
|
+
|
|
24
|
+
## Read first
|
|
25
|
+
|
|
26
|
+
- [../dr-error-enrichment/reference/groundcover.md](../dr-error-enrichment/reference/groundcover.md)
|
|
27
|
+
— the gcQL query mechanics, the env-to-server mapping, and the hash-not-text
|
|
28
|
+
caveat. This flow is mostly that file; do not compose queries from memory.
|
|
29
|
+
- [../dr-error-enrichment/reference/core.md](../dr-error-enrichment/reference/core.md)
|
|
30
|
+
— matching semantics. A proposal that ignores `re.match` anchoring is dead on
|
|
31
|
+
arrival, and a proposed rank that sits under an existing catch-all never fires.
|
|
32
|
+
- [../dr-error-enrichment/reference/jira-bugs.md](../dr-error-enrichment/reference/jira-bugs.md)
|
|
33
|
+
— the bug sweep in step 6: the `System area` field and its exact option value,
|
|
34
|
+
the JQL that actually returns rows, how to tell our defect from the customer's
|
|
35
|
+
condition, and how to file the bug if one is missing.
|
|
36
|
+
- [../dr-error-enrichment/reference/safety-backup.md](../dr-error-enrichment/reference/safety-backup.md)
|
|
37
|
+
— before any of the proposals become writes. The backup is one command:
|
|
38
|
+
`dr error-enrichments export --all-servers --out /tmp/ee-backup/` (with a
|
|
39
|
+
sweep, `--out` is a directory and each server lands as its own
|
|
40
|
+
`<SERVER>.csv`).
|
|
41
|
+
|
|
42
|
+
## The loop
|
|
43
|
+
|
|
44
|
+
**1. Pick the region and the window, and prove they line up.** Ask which server
|
|
45
|
+
the user intends to improve, then map it to the groundcover env before querying —
|
|
46
|
+
`UK` is `prod-uk*`, `CA` is `prod-canada-central`, `DEMO` is `prod-demo`, and
|
|
47
|
+
`US`/`US2` are ambiguous across the three US envs and `EU` is not mapped at
|
|
48
|
+
all, so resolve those explicitly (see the reference). Mining one region's logs to justify a rule you then write to
|
|
49
|
+
another is the failure mode this step exists to prevent. Start with a tight
|
|
50
|
+
window and widen only after it returns rows.
|
|
51
|
+
|
|
52
|
+
**2. Find the unmatched-resolve marker lines.** The monolith logs every resolve
|
|
53
|
+
that matched nothing with `[ErrorEnrichment] No matching rule`. Query on the bare
|
|
54
|
+
keyword — a leading wildcard can't use the full-text index and times out on a
|
|
55
|
+
busy env:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
ErrorEnrichment | stats count()
|
|
59
|
+
ErrorEnrichment | fields _time, content | limit 20
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**3. Group by vendor to find the worst connector.** The marker's fields are
|
|
63
|
+
printf-formatted inside the message text, not indexed attributes, so extract them
|
|
64
|
+
first or you get one silent empty group:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
ErrorEnrichment | extract_regexp "vendor_name=(?P<vendor>[^ ]+)" from content
|
|
68
|
+
| stats by (vendor) count() as unmatched | sort by (unmatched desc) | limit 20
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**4. Group by error hash to rank distinct offenders.** Identical
|
|
72
|
+
`err_sha256_prefix` values are the same normalised error, so this counts *distinct*
|
|
73
|
+
unmatched errors rather than volume of one noisy tenant. The top rows are the
|
|
74
|
+
highest-value *candidates* — a lot of traffic each, still to be cleared by
|
|
75
|
+
step 6:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
ErrorEnrichment | extract_regexp "err_sha256_prefix=(?P<sig>[0-9a-f]+)" from content
|
|
79
|
+
| stats by (sig) count() as hits | sort by (hits desc) | limit 50
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**5. Recover the raw text for each candidate.** The marker carries only a hash and
|
|
83
|
+
a length **by design** — vendor errors can embed customer paths and tokens, so the
|
|
84
|
+
text is deliberately kept out of the log. Get it from the tenant instead
|
|
85
|
+
(`integrations get <id>`, or `integrations query-status --json` for the `query_id`
|
|
86
|
+
the marker names) or from the vendor sync error logs around the same timestamp and
|
|
87
|
+
`datasource_id`. Without real text you cannot write a pattern, only guess at one.
|
|
88
|
+
|
|
89
|
+
**6. Triage each candidate against the integration bugs before it becomes a
|
|
90
|
+
proposal.** Read
|
|
91
|
+
[jira-bugs.md](../dr-error-enrichment/reference/jira-bugs.md) for the exact
|
|
92
|
+
queries; the shape of the step is:
|
|
93
|
+
|
|
94
|
+
- Sweep the open integration bugs **and** the ones fixed in the last ~60 days —
|
|
95
|
+
`cf[10717] = "Integration"` in project `DR` (the option is singular
|
|
96
|
+
`Integration`; a wrong value returns zero rows and no error). A signature whose
|
|
97
|
+
volume stops the week a fix shipped needs nothing at all.
|
|
98
|
+
- The `System area` field is optional on the create screen and often empty, so
|
|
99
|
+
follow with a free-text `text ~ "<stable phrase>"` pass with no area filter
|
|
100
|
+
before calling a signature unticketed.
|
|
101
|
+
- Then classify each candidate: **customer- or vendor-side** → propose a rule;
|
|
102
|
+
**our defect with a ticket** → no rule, report the signature against the bug
|
|
103
|
+
key, because your volume figure is priority evidence that bug does not have
|
|
104
|
+
yet; **our defect with no ticket** → no rule, flag it and offer to open one;
|
|
105
|
+
**unclear** → no rule, say what would settle it.
|
|
106
|
+
- Classify on **whose code raised it**, not on what the error looks like.
|
|
107
|
+
Tracebacks, `NoneType`, un-enriched exception bodies, 5xx and timeouts all
|
|
108
|
+
reach us from vendors and from the customer's own machine too — they are clues
|
|
109
|
+
that raise the question. Settle it with the log source, the host, and whose
|
|
110
|
+
endpoint answered; if those don't converge the verdict is **unclear**, which is
|
|
111
|
+
still not a rule.
|
|
112
|
+
- Opening the bug is outward-facing: show the summary and body first and wait for
|
|
113
|
+
a yes, group related signatures into one ticket, and set `customfield_10717`
|
|
114
|
+
(`{"id": "20748"}`) or the next sweep cannot see it.
|
|
115
|
+
- **Redact the error text in the draft you show, before anything is filed** —
|
|
116
|
+
credentials and connection strings, usernames, hosts/DSNs/paths, customer and
|
|
117
|
+
account identifiers, and any row-level financial values. Keep the exception
|
|
118
|
+
class, message template, module, vendor error code and the
|
|
119
|
+
`err_sha256_prefix`; that is what the fix needs. The checklist is in
|
|
120
|
+
[jira-bugs.md](../dr-error-enrichment/reference/jira-bugs.md) — nothing
|
|
121
|
+
sanitises this for you.
|
|
122
|
+
|
|
123
|
+
If the Atlassian tools are not available in the session, **say so and mark the
|
|
124
|
+
proposals un-triaged** — a skipped sweep produces a list that looks exactly like
|
|
125
|
+
a triaged one.
|
|
126
|
+
|
|
127
|
+
**7. Sanity-check that nothing already covers it.** A "missing" rule is often an
|
|
128
|
+
existing rule that is too narrow, or one that is a draft and therefore invisible:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
dr error-enrichments list --server <S> --integration-type <T> --json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Check the vendor's existing ranks at the same time — a proposal has to sit above
|
|
135
|
+
whatever catch-all would otherwise swallow it.
|
|
136
|
+
|
|
137
|
+
**8. Draft one proposal per surviving candidate.** Each proposal states: the
|
|
138
|
+
vendor (`integration_type`), the proposed pattern, the proposed `description` and
|
|
139
|
+
`resolution_steps` in customer language, the samples it was built from, and the
|
|
140
|
+
estimated volume it would cover (the `hits` count from step 4). Volume is what
|
|
141
|
+
makes the list rankable — without it the user is choosing blind.
|
|
142
|
+
|
|
143
|
+
## Handing the results off
|
|
144
|
+
|
|
145
|
+
A run has **two** outputs, and the second one is not a footnote. Report them as
|
|
146
|
+
separate lists:
|
|
147
|
+
|
|
148
|
+
1. **Ranked rule proposals** — the candidates that are genuinely the customer's
|
|
149
|
+
or the vendor's to fix.
|
|
150
|
+
2. **Defects** — the candidates held back in step 6, each with its volume and
|
|
151
|
+
either the bug key it belongs to or an offer to file one. Say plainly that
|
|
152
|
+
these deliberately get no rule and why.
|
|
153
|
+
|
|
154
|
+
Present the proposals and let the user choose which to write. Do not write the
|
|
155
|
+
whole list because it is on the list.
|
|
156
|
+
|
|
157
|
+
- Route the chosen ones to `dr-error-enrichment-author` for the per-rule
|
|
158
|
+
treatment, **or** write them together as a batch:
|
|
159
|
+
`dr error-enrichments create --payload-file proposals.json --server <S>` with an
|
|
160
|
+
array of rule objects. Batch writes are sequential and a per-item failure does
|
|
161
|
+
not stop the run — read the summary table afterwards to see which ids landed.
|
|
162
|
+
Every entry is type-validated before anything is sent, and the error names the
|
|
163
|
+
offending entry by its position in the file (`entry 3: …`), so fix that entry
|
|
164
|
+
and re-plan. Re-planning is
|
|
165
|
+
required anyway: the batch confirm token binds the field values as well as the
|
|
166
|
+
targets, so a payload edited after the plan was relayed will not redeem.
|
|
167
|
+
- **Validate every pattern with `test-regex` before it goes into the payload
|
|
168
|
+
file**, against the real samples *and* at least one error that must not match.
|
|
169
|
+
A batch create does not validate patterns for you.
|
|
170
|
+
- Create as drafts (`approved: false`) when a pattern still needs field
|
|
171
|
+
validation. Say out loud what that costs: a draft steals the hit and shows the
|
|
172
|
+
user nothing, so it is strictly worse than no rule until it is approved. A draft
|
|
173
|
+
is a commitment to come back — book the follow-up through
|
|
174
|
+
`dr-error-enrichment-maintain`.
|
|
175
|
+
|
|
176
|
+
## Prove the pipeline before reporting zero
|
|
177
|
+
|
|
178
|
+
An empty gcQL result is indistinguishable from a wrong env, a too-narrow window,
|
|
179
|
+
or a misspelled field — none of those error, they all return nothing. Run a query
|
|
180
|
+
you *expect* to return rows (`ErrorEnrichment | stats count()`) and confirm the
|
|
181
|
+
env resolves before telling the user there are no unmatched errors. "We're fully
|
|
182
|
+
covered" is a much more expensive thing to say wrongly than "I couldn't reach the
|
|
183
|
+
logs".
|
|
184
|
+
|
|
185
|
+
The bug sweep fails the same silent way: a wrong `System area` option value
|
|
186
|
+
returns zero rows without erroring, so "no known bug" and "bad JQL" look
|
|
187
|
+
identical. Prove that query returns rows too before you let a candidate through
|
|
188
|
+
as nobody's fault but the customer's.
|
|
189
|
+
|
|
190
|
+
## Customer data
|
|
191
|
+
|
|
192
|
+
Raw vendor error text is customer data. Use it to build the rule; keep it out of
|
|
193
|
+
chat summaries beyond what the rule actually needs; put sanitised text in
|
|
194
|
+
`examples`. The hash-only marker exists for this reason — don't undo it by pasting
|
|
195
|
+
whole error bodies into the conversation, or into a Jira ticket, which is a wider
|
|
196
|
+
audience still.
|
|
197
|
+
|
|
198
|
+
## Pitfalls
|
|
199
|
+
|
|
200
|
+
| Mistake | Fix |
|
|
201
|
+
|---|---|
|
|
202
|
+
| `stats by (vendor_name)` on the marker line | Those are text inside `content`, not fields — `extract_regexp` first, or you get one empty group |
|
|
203
|
+
| `content:*ErrorEnrichment*` | Leading wildcard can't use the index; query the bare keyword `ErrorEnrichment` |
|
|
204
|
+
| Treating an empty result as "no unmatched errors" | Verify env, window, and field names with a query you expect to return rows |
|
|
205
|
+
| Mining `prod-uk` and writing the rule to `US` | Resolve the env-to-server mapping first; volume evidence is per region |
|
|
206
|
+
| Expecting raw error text from the marker | It is hash + length only; pull the text from the tenant or the vendor sync logs |
|
|
207
|
+
| Ranking candidates by raw line count | Group by `err_sha256_prefix` — one noisy tenant is not the same as a widespread error |
|
|
208
|
+
| Proposing a rule for an error our own code raised | Triage against the integration bugs first — a rule over a defect blames the customer and buries the bug |
|
|
209
|
+
| Skipping the bug sweep because the errors "look like vendor errors" | Tracebacks and 5xx from our services hide in vendor-shaped noise; the sweep is two queries |
|
|
210
|
+
| Sweeping only *open* bugs | A fix shipped last week disqualifies the rule too — include `resolved >= -60d` |
|
|
211
|
+
| Trusting `cf[10717]` alone, or writing `"Integrations"` | The field is optional and often empty, and the option is singular `Integration` — add a `text ~` pass, and remember a bad option value returns zero rows without erroring |
|
|
212
|
+
| Filing a bug per signature, or filing one unasked | Group related signatures, show the ticket first, and set `System area` so the next sweep sees it |
|
|
213
|
+
| Presenting proposals when the Jira sweep could not run | Say they are un-triaged — the list looks the same either way |
|
|
214
|
+
| Proposing a pattern with no leading `.*` | `re.match` anchors at the start; it will match nothing in production |
|
|
215
|
+
| Writing the whole proposal list unasked | Present ranked, let the user pick — each rule is user-facing text |
|
|
216
|
+
| Batch-creating patterns straight from the proposal | `test-regex` every one first; `create` does not validate matching behaviour |
|
|
217
|
+
| Editing `proposals.json` after relaying the plan | The batch token binds the values too — re-run the plan step and relay it again |
|
|
218
|
+
| Leaving new drafts behind | A draft steals the hit and shows nothing — hand it to `dr-error-enrichment-maintain` |
|