@deployanyway/excuse-js 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/MIGRATION.md +6 -0
- package/README.md +25 -2
- package/dist/index.cjs +123 -13
- package/index.d.cts +2 -0
- package/index.d.ts +2 -0
- package/package.json +1 -1
- package/src/cli.js +28 -11
- package/src/excuses.js +100 -1
- package/src/index.js +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
132 original workplace-safe excuses: twelve distinct phrases in each of eleven categories. Seeded batches avoid repeats until all twelve phrases in the category have been used; larger batches cycle. Reports pair the joke with an honest next step. The jokes are for humor, not hiding incidents or misleading teammates.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
|
|
9
|
+
|
|
3
10
|
## 0.3.0 — 2026-10-08
|
|
4
11
|
|
|
5
12
|
- Useful structured API/CLI additions described in README.
|
|
@@ -22,3 +29,4 @@
|
|
|
22
29
|
- 33 original workplace-safe excuses across 11 categories.
|
|
23
30
|
- Library API, stateless seeded selection, and CLI with category listing.
|
|
24
31
|
- Tests, linting, formatting, and CI on Node 22/24.
|
|
32
|
+
```
|
package/MIGRATION.md
CHANGED
|
@@ -3,3 +3,9 @@
|
|
|
3
3
|
Node 22.13+ is required. Existing core APIs remain available; TypeScript declarations and CommonJS exports are new. The CLI now lives in src/cli.js behind the same executable path. Input/stdout behavior for new options is documented in README.
|
|
4
4
|
|
|
5
5
|
Install 0.3.0 with npm. Seeds and exact humorous wording are version-specific. Do not treat jokes or heuristic scores as production evidence.
|
|
6
|
+
|
|
7
|
+
## 0.3.0 to 0.4.0
|
|
8
|
+
|
|
9
|
+
132 original phrases across eleven categories; twelve unique items before batch cycling; independent listExcuses catalogs and CLI --catalog; specific conflict-resolution next step.
|
|
10
|
+
|
|
11
|
+
Seeded selections are version-specific and may differ after catalog expansion. Pin the version for exact reproducibility. Existing user messages and API entry points remain supported.
|
package/README.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
# excuse-js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## A meeting-sized library (0.4.0)
|
|
4
|
+
|
|
5
|
+
132 original workplace-safe excuses: twelve distinct phrases in each of eleven categories. Seeded batches avoid repeats until all twelve phrases in the category have been used; larger batches cycle. Reports pair the joke with an honest next step. The jokes are for humor, not hiding incidents or misleading teammates.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npx @deployanyway/excuse-js testing --count 12 --seed demo
|
|
9
|
+
npx @deployanyway/excuse-js production --report --seed demo
|
|
10
|
+
npx @deployanyway/excuse-js network --catalog --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import {
|
|
15
|
+
listExcuses,
|
|
16
|
+
excuseBatch,
|
|
17
|
+
excuseReport,
|
|
18
|
+
} from "@deployanyway/excuse-js";
|
|
19
|
+
console.log(listExcuses("testing"));
|
|
20
|
+
console.log(excuseBatch("demo", { count: 5, seed: "rehearsal" }));
|
|
21
|
+
console.log(excuseReport("production", { seed: "incident" }));
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`listExcuses(category?)` returns a fresh copy of the category catalog without consuming randomness. CLI `--catalog` accepts a category and optional `--json`, not seed, count or report. Catalog expansion changes which phrase a seed chooses compared with 0.3.0; pin the version for exact reproducibility.
|
|
25
|
+
|
|
26
|
+
> **Version 0.4.0:** install from npm with Node 22.13+ or Node 24. See MIGRATION.md for changes from 0.2.0.
|
|
4
27
|
|
|
5
28
|
[](https://www.npmjs.com/package/@deployanyway/excuse-js)
|
|
6
29
|
[](https://github.com/DeployAnyway/excuse-js/actions/workflows/ci.yml)
|
|
@@ -63,7 +86,7 @@ catalog changes between versions; this is not a cryptographic generator.
|
|
|
63
86
|
## Categories
|
|
64
87
|
|
|
65
88
|
deployment, build, production, bug, api, database, deadline, testing, network,
|
|
66
|
-
merge-conflict, demo. Each
|
|
89
|
+
merge-conflict, demo. Each has twelve original, workplace-safe phrases.
|
|
67
90
|
|
|
68
91
|
Custom runtime categories are deferred. Contributors can extend the data file
|
|
69
92
|
without changing the selection logic.
|
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
categories: () => categories,
|
|
24
24
|
excuse: () => excuse,
|
|
25
25
|
excuseBatch: () => excuseBatch,
|
|
26
|
-
excuseReport: () => excuseReport
|
|
26
|
+
excuseReport: () => excuseReport,
|
|
27
|
+
listExcuses: () => listExcuses
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(index_exports);
|
|
29
30
|
|
|
@@ -32,62 +33,162 @@ var phrases = {
|
|
|
32
33
|
deployment: [
|
|
33
34
|
"The deployment passed rehearsal and requested a stunt double for production.",
|
|
34
35
|
"The release arrived on time. Its dependencies are still finding parking.",
|
|
35
|
-
"The deployment is waiting for the server to finish its dramatic entrance."
|
|
36
|
+
"The deployment is waiting for the server to finish its dramatic entrance.",
|
|
37
|
+
"The release notes say smooth landing. The landing gear has requested clarification.",
|
|
38
|
+
"The deploy button has confidence. The health check has follow-up questions.",
|
|
39
|
+
"The release is technically live and emotionally still in staging.",
|
|
40
|
+
"Our rollback plan has achieved the rare status of being read before the incident.",
|
|
41
|
+
"The canary found a problem and would like its consulting fee in seeds.",
|
|
42
|
+
"The release was ready until production introduced itself.",
|
|
43
|
+
"We shipped the fix. The monitoring dashboard is deciding whether to clap.",
|
|
44
|
+
"The deployment arrived wearing a parachute. This is considered progress.",
|
|
45
|
+
"The server accepted the release but declined to endorse its lifestyle."
|
|
36
46
|
],
|
|
37
47
|
build: [
|
|
38
48
|
"The compiler found a typo and promoted it to a company-wide announcement.",
|
|
39
49
|
"The build is assembling a committee to discuss the missing semicolon.",
|
|
40
|
-
"The artifacts are ready; the build is negotiating custody."
|
|
50
|
+
"The artifacts are ready; the build is negotiating custody.",
|
|
51
|
+
"The compiler is proofreading a novel we thought was a configuration file.",
|
|
52
|
+
"The build cache remembers a different version of reality.",
|
|
53
|
+
"The bundle got smaller after we removed the feature that made it work.",
|
|
54
|
+
"The build system asked for a dependency and received a family reunion.",
|
|
55
|
+
"One warning invited its friends and now the terminal needs chairs.",
|
|
56
|
+
"The clean build is clean because it contains no artifacts yet.",
|
|
57
|
+
"The compiler rejected the argument that it worked yesterday.",
|
|
58
|
+
"Our build pipeline is a conveyor belt with trust issues.",
|
|
59
|
+
"The source maps know where the problem is. They are being dramatic about it."
|
|
41
60
|
],
|
|
42
61
|
production: [
|
|
43
62
|
"Production interpreted the happy path as an optional scenic route.",
|
|
44
63
|
"The server is performing an unscheduled demonstration of our recovery plan.",
|
|
45
|
-
"Production has requested that our assumptions submit identification."
|
|
64
|
+
"Production has requested that our assumptions submit identification.",
|
|
65
|
+
"Production has discovered an edge case shaped exactly like our largest customer.",
|
|
66
|
+
"The incident is stable. Our coffee consumption is scaling horizontally.",
|
|
67
|
+
"The dashboards are green because the broken metric stopped reporting.",
|
|
68
|
+
"Production read the happy-path test and chose creative freedom.",
|
|
69
|
+
"The service is healthy in the same way a husky is quiet before stealing a sock.",
|
|
70
|
+
"We have narrowed the cause to the part of the system currently existing.",
|
|
71
|
+
"The fallback works. It has been promoted to the main plan without a ceremony.",
|
|
72
|
+
"The alert arrived before the customer email. We are counting that as a win.",
|
|
73
|
+
"Our recovery estimate is being reviewed by the concept of time."
|
|
46
74
|
],
|
|
47
75
|
bug: [
|
|
48
76
|
"The edge case moved to the center and brought furniture.",
|
|
49
77
|
"That variable has been exploring career opportunities outside its scope.",
|
|
50
|
-
"The bug declined to reproduce until the screen-sharing session began."
|
|
78
|
+
"The bug declined to reproduce until the screen-sharing session began.",
|
|
79
|
+
"The bug is intermittent, which is engineer for witness protection.",
|
|
80
|
+
"The reproduction is minimal. The emotional damage is not.",
|
|
81
|
+
"The issue disappeared while screen sharing and returned to clock in afterward.",
|
|
82
|
+
"The edge case has built a small apartment in the main path.",
|
|
83
|
+
"We found the bug. It was wearing a feature flag as a disguise.",
|
|
84
|
+
"The fix is one line. The explanation requires a whiteboard and snacks.",
|
|
85
|
+
"The bug survived three refactors and now qualifies for seniority.",
|
|
86
|
+
"The stack trace has provided directions to a place we never wanted to visit.",
|
|
87
|
+
"The defect is resolved in the branch where optimism is enabled."
|
|
51
88
|
],
|
|
52
89
|
api: [
|
|
53
90
|
"The API sent a response, but it used the envelope for the payload.",
|
|
54
91
|
"The endpoint is observing a moment of silence for our timeout setting.",
|
|
55
|
-
"The contract was clear. The response preferred interpretive dance."
|
|
92
|
+
"The contract was clear. The response preferred interpretive dance.",
|
|
93
|
+
"The endpoint returned success with the confidence of an empty response body.",
|
|
94
|
+
"The API contract and implementation are currently seeing other people.",
|
|
95
|
+
"The request timed out while the server composed a thoughtful silence.",
|
|
96
|
+
"The response schema evolved during the meeting about freezing the schema.",
|
|
97
|
+
"The retry succeeded in creating the same problem twice.",
|
|
98
|
+
"The status code is correct. The payload is expressing itself artistically.",
|
|
99
|
+
"The endpoint is idempotent on days when nobody asks it twice.",
|
|
100
|
+
"The client sent a request. The server returned a character development arc.",
|
|
101
|
+
"The integration test has discovered that both sides mean something different by optional."
|
|
56
102
|
],
|
|
57
103
|
database: [
|
|
58
104
|
"The database is taking a full-table stroll to consider our question.",
|
|
59
105
|
"The query asked for one row and accidentally invited the whole neighborhood.",
|
|
60
|
-
"The migration packed the columns but forgot the forwarding address."
|
|
106
|
+
"The migration packed the columns but forgot the forwarding address.",
|
|
107
|
+
"The query planner chose the scenic route through every row.",
|
|
108
|
+
"The migration passed locally on a database containing exactly our confidence.",
|
|
109
|
+
"The index exists. The query would prefer to meet all the data personally.",
|
|
110
|
+
"The connection pool is full of connections discussing their retirement.",
|
|
111
|
+
"The transaction is waiting on a lock that is waiting on a conversation.",
|
|
112
|
+
"The backup completed. We are now attempting the bold sequel: restore.",
|
|
113
|
+
"The schema is flexible because we forgot where it was documented.",
|
|
114
|
+
"The slow query has enough history to apply for heritage status.",
|
|
115
|
+
"The data is consistent about disagreeing with the application."
|
|
61
116
|
],
|
|
62
117
|
deadline: [
|
|
63
118
|
"The estimate included coding time, but the calendar added plot twists.",
|
|
64
119
|
"The deadline arrived before the requirements finished introducing themselves.",
|
|
65
|
-
"The last ten percent has applied for its own project manager."
|
|
120
|
+
"The last ten percent has applied for its own project manager.",
|
|
121
|
+
"The estimate included development, testing and a completely fictional Tuesday.",
|
|
122
|
+
"The smallest deliverable grew after someone used the word just.",
|
|
123
|
+
"The timeline assumed dependencies would arrive with their shoes on.",
|
|
124
|
+
"We can deliver quickly if the definition of delivered stops moving.",
|
|
125
|
+
"The calendar is immutable. The scope is doing parkour.",
|
|
126
|
+
"The critical path has stopped to attend a planning meeting.",
|
|
127
|
+
"The deadline is realistic in the timezone where requirements never change.",
|
|
128
|
+
"We reduced the scope. It is now only moderately larger than the week.",
|
|
129
|
+
"The schedule has a buffer. Unfortunately it is written in pencil."
|
|
66
130
|
],
|
|
67
131
|
testing: [
|
|
68
132
|
"The test fixture has developed stronger opinions than the specification.",
|
|
69
133
|
"The flaky test only accepts results delivered under a full cache.",
|
|
70
|
-
"The assertion expected certainty; the asynchronous task offered suspense."
|
|
134
|
+
"The assertion expected certainty; the asynchronous task offered suspense.",
|
|
135
|
+
"The test passed because the assertion was exceptionally supportive.",
|
|
136
|
+
"The fixture describes a world with fewer users and better manners.",
|
|
137
|
+
"The flaky test is conducting a long-term study of team patience.",
|
|
138
|
+
"Coverage went up after we tested the part that says hello.",
|
|
139
|
+
"The integration test has introduced the units to each other. They are arguing.",
|
|
140
|
+
"The mock is perfect at simulating the service we wish we had.",
|
|
141
|
+
"The regression test passed and immediately asked why it was not here earlier.",
|
|
142
|
+
"The test suite is green. The skipped tests are enjoying a quiet holiday.",
|
|
143
|
+
"The failing test has a point and an unfortunate way of making it."
|
|
71
144
|
],
|
|
72
145
|
network: [
|
|
73
146
|
"The packets took a detour to admire the routing table.",
|
|
74
147
|
"DNS is still deciding which address feels most like home.",
|
|
75
|
-
"The connection is buffering its explanation for the delay."
|
|
148
|
+
"The connection is buffering its explanation for the delay.",
|
|
149
|
+
"DNS is resolving everything except the team's uncertainty.",
|
|
150
|
+
"The packet took a detour through a router with strong opinions.",
|
|
151
|
+
"The connection is stable between the moments when it is not.",
|
|
152
|
+
"The firewall followed the rules. The configuration forgot to read them.",
|
|
153
|
+
"The timeout was selected by someone who believed all servers live next door.",
|
|
154
|
+
"The service is reachable from everywhere except the place that needs it.",
|
|
155
|
+
"The proxy is helping by changing the question before it arrives.",
|
|
156
|
+
"The request is in transit and has started a travel blog.",
|
|
157
|
+
"The network is technically up. The route is considering its options."
|
|
76
158
|
],
|
|
77
159
|
"merge-conflict": [
|
|
78
160
|
"Both branches brought a solution and neither brought a seating chart.",
|
|
79
161
|
"Git discovered that two correct answers wanted the same line.",
|
|
80
|
-
"The branches agree on the goal and disagree on every comma."
|
|
162
|
+
"The branches agree on the goal and disagree on every comma.",
|
|
163
|
+
"Both branches improved the same line in incompatible directions.",
|
|
164
|
+
"The conflict is resolved. The naming debate is still open.",
|
|
165
|
+
"Git found two versions of the truth and asked us to facilitate.",
|
|
166
|
+
"The rebase succeeded after we explained time travel to the tests.",
|
|
167
|
+
"The diff is small if you exclude the file everybody reformatted.",
|
|
168
|
+
"The merge was automatic until the humans got involved.",
|
|
169
|
+
"The branch is current with main and several unresolved feelings.",
|
|
170
|
+
"We chose both changes. The compiler would like us to choose again.",
|
|
171
|
+
"The conflict marker survived review by pretending to be punctuation."
|
|
81
172
|
],
|
|
82
173
|
demo: [
|
|
83
174
|
"The demo saw an audience and switched from software to performance art.",
|
|
84
175
|
"The prototype is saving its best behavior for the recording we forgot to start.",
|
|
85
|
-
"The live demo has added a surprise question to the presentation."
|
|
176
|
+
"The live demo has added a surprise question to the presentation.",
|
|
177
|
+
"The demo works best when the audience is a test fixture.",
|
|
178
|
+
"The projector has detected confidence and activated its troubleshooting mode.",
|
|
179
|
+
"The live demo is a distributed system consisting of nerves and Wi-Fi.",
|
|
180
|
+
"The happy path worked until someone clicked the interesting button.",
|
|
181
|
+
"The offline fallback is now the star of the presentation.",
|
|
182
|
+
"The demo data is realistic enough to have missing fields.",
|
|
183
|
+
"The browser refreshed and introduced us to the unsaved version.",
|
|
184
|
+
"The feature worked backstage. It is negotiating public appearances.",
|
|
185
|
+
"The rehearsal was flawless. The room has different opinions about networking."
|
|
86
186
|
]
|
|
87
187
|
};
|
|
88
188
|
|
|
89
189
|
// src/index.js
|
|
90
190
|
var nextSteps = {
|
|
191
|
+
"merge-conflict": "Understand both changes, resolve the conflict deliberately, then run tests for the combined behavior. Git does not accept a coin toss.",
|
|
91
192
|
deployment: "Check the release diff and rollback plan before delivering this line.",
|
|
92
193
|
testing: "Reproduce the failure and add a regression test. The punchline is optional.",
|
|
93
194
|
build: "Read the first build error, verify dependencies, then rebuild. The compiler does not accept applause.",
|
|
@@ -152,10 +253,19 @@ function excuseBatch(category = "deployment", options = {}) {
|
|
|
152
253
|
(_, i) => pool[(start + i) % pool.length]
|
|
153
254
|
);
|
|
154
255
|
}
|
|
256
|
+
function listExcuses(category = "deployment") {
|
|
257
|
+
if (typeof category !== "string" || !category.trim())
|
|
258
|
+
throw new TypeError("Category must be a nonempty string.");
|
|
259
|
+
const key = category.trim().toLowerCase();
|
|
260
|
+
if (!Object.hasOwn(phrases, key))
|
|
261
|
+
throw new RangeError("Unknown category: " + category);
|
|
262
|
+
return [...phrases[key]];
|
|
263
|
+
}
|
|
155
264
|
// Annotate the CommonJS export names for ESM import in node:
|
|
156
265
|
0 && (module.exports = {
|
|
157
266
|
categories,
|
|
158
267
|
excuse,
|
|
159
268
|
excuseBatch,
|
|
160
|
-
excuseReport
|
|
269
|
+
excuseReport,
|
|
270
|
+
listExcuses
|
|
161
271
|
});
|
package/index.d.cts
CHANGED
package/index.d.ts
CHANGED
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { parseArgs } from "node:util";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { URL } from "node:url";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
excuse,
|
|
6
|
+
categories,
|
|
7
|
+
excuseBatch,
|
|
8
|
+
excuseReport,
|
|
9
|
+
listExcuses,
|
|
10
|
+
} from "./index.js";
|
|
5
11
|
|
|
6
12
|
try {
|
|
7
13
|
const { values, positionals } = parseArgs({
|
|
@@ -14,11 +20,12 @@ try {
|
|
|
14
20
|
count: { type: "string" },
|
|
15
21
|
json: { type: "boolean" },
|
|
16
22
|
report: { type: "boolean" },
|
|
23
|
+
catalog: { type: "boolean" },
|
|
17
24
|
},
|
|
18
25
|
});
|
|
19
26
|
if (values.help) {
|
|
20
27
|
console.log(
|
|
21
|
-
"Usage: excuse-js [category] [--seed text] [--count 3] [--json]\n\nDefault category: deployment. --report pairs the joke with an honest next step.\n\nOptions:\n --seed text Repeatable selection (always a string seed)\n --count 1..20 Prepare a batch for the meeting\n --json Structured string or batch\n --list List categories\n -h, --help Show help\n -v, --version Show version\n\nExample: excuse-js deployment --seed demo\nExit codes: 0 success; 2 invalid arguments.",
|
|
28
|
+
"Usage: excuse-js [category] [--seed text] [--count 3] [--json]\n\nDefault category: deployment. --report pairs the joke with an honest next step.\n\nOptions:\n --seed text Repeatable selection (always a string seed)\n --count 1..20 Prepare a batch for the meeting\n --json Structured string or batch\n --catalog Show every phrase in a category\n --list List categories\n -h, --help Show help\n -v, --version Show version\n\nExample: excuse-js deployment --seed demo\nExit codes: 0 success; 2 invalid arguments.",
|
|
22
29
|
);
|
|
23
30
|
} else if (values.version) {
|
|
24
31
|
console.log(
|
|
@@ -32,7 +39,8 @@ try {
|
|
|
32
39
|
values.seed !== undefined ||
|
|
33
40
|
values.count !== undefined ||
|
|
34
41
|
values.json ||
|
|
35
|
-
values.report
|
|
42
|
+
values.report ||
|
|
43
|
+
values.catalog
|
|
36
44
|
)
|
|
37
45
|
throw new TypeError("--list does not accept a category or seed.");
|
|
38
46
|
console.log(categories().join("\n"));
|
|
@@ -43,14 +51,23 @@ try {
|
|
|
43
51
|
throw new TypeError("count must be an integer.");
|
|
44
52
|
if (values.report && values.count !== undefined)
|
|
45
53
|
throw new TypeError("--report cannot be combined with --count.");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
if (
|
|
55
|
+
values.catalog &&
|
|
56
|
+
(values.seed !== undefined || values.count !== undefined || values.report)
|
|
57
|
+
)
|
|
58
|
+
throw new TypeError(
|
|
59
|
+
"--catalog cannot be combined with seed, count or report.",
|
|
60
|
+
);
|
|
61
|
+
const result = values.catalog
|
|
62
|
+
? listExcuses(positionals[0])
|
|
63
|
+
: values.report
|
|
64
|
+
? excuseReport(positionals[0], { seed: values.seed })
|
|
65
|
+
: values.count === undefined
|
|
66
|
+
? excuse(positionals[0], { seed: values.seed })
|
|
67
|
+
: excuseBatch(positionals[0], {
|
|
68
|
+
seed: values.seed,
|
|
69
|
+
count: Number(values.count),
|
|
70
|
+
});
|
|
54
71
|
console.log(
|
|
55
72
|
values.json
|
|
56
73
|
? JSON.stringify(result)
|
package/src/excuses.js
CHANGED
|
@@ -1,58 +1,157 @@
|
|
|
1
|
-
// Original, workplace-safe phrases.
|
|
1
|
+
// Original, workplace-safe phrases. Each category has twelve distinct excuses.
|
|
2
2
|
export const phrases = {
|
|
3
3
|
deployment: [
|
|
4
4
|
"The deployment passed rehearsal and requested a stunt double for production.",
|
|
5
5
|
"The release arrived on time. Its dependencies are still finding parking.",
|
|
6
6
|
"The deployment is waiting for the server to finish its dramatic entrance.",
|
|
7
|
+
"The release notes say smooth landing. The landing gear has requested clarification.",
|
|
8
|
+
"The deploy button has confidence. The health check has follow-up questions.",
|
|
9
|
+
"The release is technically live and emotionally still in staging.",
|
|
10
|
+
"Our rollback plan has achieved the rare status of being read before the incident.",
|
|
11
|
+
"The canary found a problem and would like its consulting fee in seeds.",
|
|
12
|
+
"The release was ready until production introduced itself.",
|
|
13
|
+
"We shipped the fix. The monitoring dashboard is deciding whether to clap.",
|
|
14
|
+
"The deployment arrived wearing a parachute. This is considered progress.",
|
|
15
|
+
"The server accepted the release but declined to endorse its lifestyle.",
|
|
7
16
|
],
|
|
8
17
|
build: [
|
|
9
18
|
"The compiler found a typo and promoted it to a company-wide announcement.",
|
|
10
19
|
"The build is assembling a committee to discuss the missing semicolon.",
|
|
11
20
|
"The artifacts are ready; the build is negotiating custody.",
|
|
21
|
+
"The compiler is proofreading a novel we thought was a configuration file.",
|
|
22
|
+
"The build cache remembers a different version of reality.",
|
|
23
|
+
"The bundle got smaller after we removed the feature that made it work.",
|
|
24
|
+
"The build system asked for a dependency and received a family reunion.",
|
|
25
|
+
"One warning invited its friends and now the terminal needs chairs.",
|
|
26
|
+
"The clean build is clean because it contains no artifacts yet.",
|
|
27
|
+
"The compiler rejected the argument that it worked yesterday.",
|
|
28
|
+
"Our build pipeline is a conveyor belt with trust issues.",
|
|
29
|
+
"The source maps know where the problem is. They are being dramatic about it.",
|
|
12
30
|
],
|
|
13
31
|
production: [
|
|
14
32
|
"Production interpreted the happy path as an optional scenic route.",
|
|
15
33
|
"The server is performing an unscheduled demonstration of our recovery plan.",
|
|
16
34
|
"Production has requested that our assumptions submit identification.",
|
|
35
|
+
"Production has discovered an edge case shaped exactly like our largest customer.",
|
|
36
|
+
"The incident is stable. Our coffee consumption is scaling horizontally.",
|
|
37
|
+
"The dashboards are green because the broken metric stopped reporting.",
|
|
38
|
+
"Production read the happy-path test and chose creative freedom.",
|
|
39
|
+
"The service is healthy in the same way a husky is quiet before stealing a sock.",
|
|
40
|
+
"We have narrowed the cause to the part of the system currently existing.",
|
|
41
|
+
"The fallback works. It has been promoted to the main plan without a ceremony.",
|
|
42
|
+
"The alert arrived before the customer email. We are counting that as a win.",
|
|
43
|
+
"Our recovery estimate is being reviewed by the concept of time.",
|
|
17
44
|
],
|
|
18
45
|
bug: [
|
|
19
46
|
"The edge case moved to the center and brought furniture.",
|
|
20
47
|
"That variable has been exploring career opportunities outside its scope.",
|
|
21
48
|
"The bug declined to reproduce until the screen-sharing session began.",
|
|
49
|
+
"The bug is intermittent, which is engineer for witness protection.",
|
|
50
|
+
"The reproduction is minimal. The emotional damage is not.",
|
|
51
|
+
"The issue disappeared while screen sharing and returned to clock in afterward.",
|
|
52
|
+
"The edge case has built a small apartment in the main path.",
|
|
53
|
+
"We found the bug. It was wearing a feature flag as a disguise.",
|
|
54
|
+
"The fix is one line. The explanation requires a whiteboard and snacks.",
|
|
55
|
+
"The bug survived three refactors and now qualifies for seniority.",
|
|
56
|
+
"The stack trace has provided directions to a place we never wanted to visit.",
|
|
57
|
+
"The defect is resolved in the branch where optimism is enabled.",
|
|
22
58
|
],
|
|
23
59
|
api: [
|
|
24
60
|
"The API sent a response, but it used the envelope for the payload.",
|
|
25
61
|
"The endpoint is observing a moment of silence for our timeout setting.",
|
|
26
62
|
"The contract was clear. The response preferred interpretive dance.",
|
|
63
|
+
"The endpoint returned success with the confidence of an empty response body.",
|
|
64
|
+
"The API contract and implementation are currently seeing other people.",
|
|
65
|
+
"The request timed out while the server composed a thoughtful silence.",
|
|
66
|
+
"The response schema evolved during the meeting about freezing the schema.",
|
|
67
|
+
"The retry succeeded in creating the same problem twice.",
|
|
68
|
+
"The status code is correct. The payload is expressing itself artistically.",
|
|
69
|
+
"The endpoint is idempotent on days when nobody asks it twice.",
|
|
70
|
+
"The client sent a request. The server returned a character development arc.",
|
|
71
|
+
"The integration test has discovered that both sides mean something different by optional.",
|
|
27
72
|
],
|
|
28
73
|
database: [
|
|
29
74
|
"The database is taking a full-table stroll to consider our question.",
|
|
30
75
|
"The query asked for one row and accidentally invited the whole neighborhood.",
|
|
31
76
|
"The migration packed the columns but forgot the forwarding address.",
|
|
77
|
+
"The query planner chose the scenic route through every row.",
|
|
78
|
+
"The migration passed locally on a database containing exactly our confidence.",
|
|
79
|
+
"The index exists. The query would prefer to meet all the data personally.",
|
|
80
|
+
"The connection pool is full of connections discussing their retirement.",
|
|
81
|
+
"The transaction is waiting on a lock that is waiting on a conversation.",
|
|
82
|
+
"The backup completed. We are now attempting the bold sequel: restore.",
|
|
83
|
+
"The schema is flexible because we forgot where it was documented.",
|
|
84
|
+
"The slow query has enough history to apply for heritage status.",
|
|
85
|
+
"The data is consistent about disagreeing with the application.",
|
|
32
86
|
],
|
|
33
87
|
deadline: [
|
|
34
88
|
"The estimate included coding time, but the calendar added plot twists.",
|
|
35
89
|
"The deadline arrived before the requirements finished introducing themselves.",
|
|
36
90
|
"The last ten percent has applied for its own project manager.",
|
|
91
|
+
"The estimate included development, testing and a completely fictional Tuesday.",
|
|
92
|
+
"The smallest deliverable grew after someone used the word just.",
|
|
93
|
+
"The timeline assumed dependencies would arrive with their shoes on.",
|
|
94
|
+
"We can deliver quickly if the definition of delivered stops moving.",
|
|
95
|
+
"The calendar is immutable. The scope is doing parkour.",
|
|
96
|
+
"The critical path has stopped to attend a planning meeting.",
|
|
97
|
+
"The deadline is realistic in the timezone where requirements never change.",
|
|
98
|
+
"We reduced the scope. It is now only moderately larger than the week.",
|
|
99
|
+
"The schedule has a buffer. Unfortunately it is written in pencil.",
|
|
37
100
|
],
|
|
38
101
|
testing: [
|
|
39
102
|
"The test fixture has developed stronger opinions than the specification.",
|
|
40
103
|
"The flaky test only accepts results delivered under a full cache.",
|
|
41
104
|
"The assertion expected certainty; the asynchronous task offered suspense.",
|
|
105
|
+
"The test passed because the assertion was exceptionally supportive.",
|
|
106
|
+
"The fixture describes a world with fewer users and better manners.",
|
|
107
|
+
"The flaky test is conducting a long-term study of team patience.",
|
|
108
|
+
"Coverage went up after we tested the part that says hello.",
|
|
109
|
+
"The integration test has introduced the units to each other. They are arguing.",
|
|
110
|
+
"The mock is perfect at simulating the service we wish we had.",
|
|
111
|
+
"The regression test passed and immediately asked why it was not here earlier.",
|
|
112
|
+
"The test suite is green. The skipped tests are enjoying a quiet holiday.",
|
|
113
|
+
"The failing test has a point and an unfortunate way of making it.",
|
|
42
114
|
],
|
|
43
115
|
network: [
|
|
44
116
|
"The packets took a detour to admire the routing table.",
|
|
45
117
|
"DNS is still deciding which address feels most like home.",
|
|
46
118
|
"The connection is buffering its explanation for the delay.",
|
|
119
|
+
"DNS is resolving everything except the team's uncertainty.",
|
|
120
|
+
"The packet took a detour through a router with strong opinions.",
|
|
121
|
+
"The connection is stable between the moments when it is not.",
|
|
122
|
+
"The firewall followed the rules. The configuration forgot to read them.",
|
|
123
|
+
"The timeout was selected by someone who believed all servers live next door.",
|
|
124
|
+
"The service is reachable from everywhere except the place that needs it.",
|
|
125
|
+
"The proxy is helping by changing the question before it arrives.",
|
|
126
|
+
"The request is in transit and has started a travel blog.",
|
|
127
|
+
"The network is technically up. The route is considering its options.",
|
|
47
128
|
],
|
|
48
129
|
"merge-conflict": [
|
|
49
130
|
"Both branches brought a solution and neither brought a seating chart.",
|
|
50
131
|
"Git discovered that two correct answers wanted the same line.",
|
|
51
132
|
"The branches agree on the goal and disagree on every comma.",
|
|
133
|
+
"Both branches improved the same line in incompatible directions.",
|
|
134
|
+
"The conflict is resolved. The naming debate is still open.",
|
|
135
|
+
"Git found two versions of the truth and asked us to facilitate.",
|
|
136
|
+
"The rebase succeeded after we explained time travel to the tests.",
|
|
137
|
+
"The diff is small if you exclude the file everybody reformatted.",
|
|
138
|
+
"The merge was automatic until the humans got involved.",
|
|
139
|
+
"The branch is current with main and several unresolved feelings.",
|
|
140
|
+
"We chose both changes. The compiler would like us to choose again.",
|
|
141
|
+
"The conflict marker survived review by pretending to be punctuation.",
|
|
52
142
|
],
|
|
53
143
|
demo: [
|
|
54
144
|
"The demo saw an audience and switched from software to performance art.",
|
|
55
145
|
"The prototype is saving its best behavior for the recording we forgot to start.",
|
|
56
146
|
"The live demo has added a surprise question to the presentation.",
|
|
147
|
+
"The demo works best when the audience is a test fixture.",
|
|
148
|
+
"The projector has detected confidence and activated its troubleshooting mode.",
|
|
149
|
+
"The live demo is a distributed system consisting of nerves and Wi-Fi.",
|
|
150
|
+
"The happy path worked until someone clicked the interesting button.",
|
|
151
|
+
"The offline fallback is now the star of the presentation.",
|
|
152
|
+
"The demo data is realistic enough to have missing fields.",
|
|
153
|
+
"The browser refreshed and introduced us to the unsaved version.",
|
|
154
|
+
"The feature worked backstage. It is negotiating public appearances.",
|
|
155
|
+
"The rehearsal was flawless. The room has different opinions about networking.",
|
|
57
156
|
],
|
|
58
157
|
};
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { phrases } from "./excuses.js";
|
|
2
2
|
const nextSteps = {
|
|
3
|
+
"merge-conflict":
|
|
4
|
+
"Understand both changes, resolve the conflict deliberately, then run tests for the combined behavior. Git does not accept a coin toss.",
|
|
3
5
|
deployment:
|
|
4
6
|
"Check the release diff and rollback plan before delivering this line.",
|
|
5
7
|
testing:
|
|
@@ -90,3 +92,13 @@ export function excuseBatch(category = "deployment", options = {}) {
|
|
|
90
92
|
(_, i) => pool[(start + i) % pool.length],
|
|
91
93
|
);
|
|
92
94
|
}
|
|
95
|
+
|
|
96
|
+
/** Read a category without consuming randomness; the returned catalog is independent. */
|
|
97
|
+
export function listExcuses(category = "deployment") {
|
|
98
|
+
if (typeof category !== "string" || !category.trim())
|
|
99
|
+
throw new TypeError("Category must be a nonempty string.");
|
|
100
|
+
const key = category.trim().toLowerCase();
|
|
101
|
+
if (!Object.hasOwn(phrases, key))
|
|
102
|
+
throw new RangeError("Unknown category: " + category);
|
|
103
|
+
return [...phrases[key]];
|
|
104
|
+
}
|