@sitar_fiercer4c/skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +75 -0
- package/bin/install.js +45 -0
- package/package.json +29 -0
- package/skills/architecture-walkthrough/SKILL.md +223 -0
- package/skills/architecture-walkthrough/references/sections.md +29 -0
- package/skills/architecture-walkthrough/scripts/check_structure.py +200 -0
- package/skills/autotest-webapp-ui/SKILL.md +58 -0
- package/skills/backend-code-review/SKILL.md +386 -0
- package/skills/backend-code-review/references/report-format.md +333 -0
- package/skills/backend-code-review/scripts/list_routes.py +269 -0
- package/skills/backend-code-review/scripts/sweep.py +550 -0
- package/skills/backend-code-review/scripts/verify_citations.py +201 -0
- package/skills/be-brief/SKILL.md +18 -0
- package/skills/clarke-list-excel/SKILL.md +51 -0
- package/skills/clarke-list-excel/references/output-schema.md +125 -0
- package/skills/clarke-list-excel/scripts/clarke_common.py +251 -0
- package/skills/clarke-list-excel/scripts/clarke_extract.py +487 -0
- package/skills/clarke-list-excel/scripts/load_clarke.py +322 -0
- package/skills/clarke-list-excel/scripts/run_all.py +63 -0
- package/skills/datalab-api/SKILL.md +163 -0
- package/skills/datalab-api/references/parameters-and-payload.md +121 -0
- package/skills/datalab-api/references/table-selection.md +35 -0
- package/skills/datalab-api/scripts/datalab_tables.py +365 -0
- package/skills/find-test-seam/SKILL.md +41 -0
- package/skills/frontend-code-review/SKILL.md +247 -0
- package/skills/frontend-code-review-2/SKILL.md +192 -0
- package/skills/frontend-code-review-2/scripts/fetch_pr_comments.py +65 -0
- package/skills/frontend-code-review-2/scripts/render_report.py +139 -0
- package/skills/murtaza-breif/SKILL.md +143 -0
- package/skills/murtaza-breif/scripts/save_brief.py +128 -0
- package/skills/pdf-to-json/SKILL.md +42 -0
- package/skills/pdf-to-json/references/output-schema.md +168 -0
- package/skills/pdf-to-json/scripts/extract_figures.py +319 -0
- package/skills/pdf-to-json/scripts/load_mongo.py +287 -0
- package/skills/pdf-to-json/scripts/pdf_extract.py +1313 -0
- package/skills/record-api-traffic/SKILL.md +434 -0
- package/skills/record-api-traffic/references/reading-recordings.md +224 -0
- package/skills/record-api-traffic/scripts/check-schema.mjs +184 -0
- package/skills/record-api-traffic/scripts/dump-quotation.mjs +67 -0
- package/skills/record-api-traffic/scripts/dump-source-excel.mjs +75 -0
- package/skills/record-api-traffic/scripts/lib/repo.mjs +109 -0
- package/skills/record-api-traffic/scripts/preflight.py +528 -0
- package/skills/record-api-traffic/scripts/record-api-traffic.py +720 -0
- package/skills/refac-wrt-business-goal/SKILL.md +305 -0
- package/skills/refac-wrt-business-goal/references/critic.md +170 -0
- package/skills/system-resource-triage/SKILL.md +180 -0
- package/skills/system-resource-triage/scripts/reap.sh +116 -0
- package/skills/system-resource-triage/scripts/triage.sh +111 -0
- package/skills/using-git-worktrees/SKILL.md +167 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright (c) 2026 thenextepisode-stealth. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software is proprietary and confidential. Unauthorized copying,
|
|
4
|
+
distribution, or use of this software, in whole or in part, is prohibited
|
|
5
|
+
without prior written permission from the copyright holder.
|
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# skills
|
|
2
|
+
|
|
3
|
+
Agent skills for Claude Code, distributed as the private npm package `@sitar_fiercer4c/skills`.
|
|
4
|
+
|
|
5
|
+
Installing the package copies every skill into the `.claude/skills` directory of the project where `npm install` is run.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
You need an npm account that has been added as a collaborator on this private package.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm login # or add a read-only token to .npmrc (see below)
|
|
13
|
+
npm install -D @sitar_fiercer4c/skills
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The skills land in `./.claude/skills/<skill-name>/`.
|
|
17
|
+
|
|
18
|
+
For CI, add this to the project's `.npmrc` and set `NPM_TOKEN` to a read-only token:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### If install scripts are disabled
|
|
25
|
+
|
|
26
|
+
With `--ignore-scripts`, pnpm, or bun, the postinstall copy may not run. Copy the skills manually from the project root:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npx @sitar_fiercer4c/skills
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Update
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm install -D @sitar_fiercer4c/skills@latest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Skills shipped by this package are replaced whenever npm installs a new copy of the package (a fresh `node_modules` or a new version), so local edits to them are overwritten. Other skills in `.claude/skills` are left alone.
|
|
39
|
+
|
|
40
|
+
npm skips the copy when the installed version is unchanged. To restore the skills in that case, run `npx @sitar_fiercer4c/skills`.
|
|
41
|
+
|
|
42
|
+
## Uninstall
|
|
43
|
+
|
|
44
|
+
`npm uninstall` does not remove the copied skills. Delete their folders from `.claude/skills` manually.
|
|
45
|
+
|
|
46
|
+
## Skills
|
|
47
|
+
|
|
48
|
+
- architecture-walkthrough
|
|
49
|
+
- autotest-webapp-ui
|
|
50
|
+
- backend-code-review
|
|
51
|
+
- be-brief
|
|
52
|
+
- clarke-list-excel
|
|
53
|
+
- datalab-api
|
|
54
|
+
- find-test-seam
|
|
55
|
+
- frontend-code-review
|
|
56
|
+
- frontend-code-review-2
|
|
57
|
+
- murtaza-breif
|
|
58
|
+
- pdf-to-json
|
|
59
|
+
- record-api-traffic
|
|
60
|
+
- refac-wrt-business-goal
|
|
61
|
+
- system-resource-triage
|
|
62
|
+
- using-git-worktrees
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
Each skill lives in `skills/<name>/` with a `SKILL.md`. `evals/` folders are kept in the repo but excluded from the published package.
|
|
67
|
+
|
|
68
|
+
To publish, load the token from `.env.local` and run:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
set -a && . ./.env.local && set +a
|
|
72
|
+
npm version patch
|
|
73
|
+
npm publish
|
|
74
|
+
git push --follow-tags
|
|
75
|
+
```
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Copies the bundled skills into <project>/.claude/skills.
|
|
5
|
+
// Runs as a postinstall hook, or manually via `npx @sitar_fiercer4c/skills`.
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const pkgRoot = path.resolve(__dirname, '..');
|
|
11
|
+
const srcDir = path.join(pkgRoot, 'skills');
|
|
12
|
+
const isPostinstall = process.env.npm_lifecycle_event === 'postinstall';
|
|
13
|
+
|
|
14
|
+
// INIT_CWD is the directory npm was invoked from, i.e. the consumer project.
|
|
15
|
+
const projectRoot = path.resolve(process.env.INIT_CWD || process.cwd());
|
|
16
|
+
|
|
17
|
+
function main() {
|
|
18
|
+
// Skip when installing dependencies inside this repo, or for global installs.
|
|
19
|
+
if (isPostinstall && (projectRoot === pkgRoot || process.env.npm_config_global === 'true')) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const destDir = path.join(projectRoot, '.claude', 'skills');
|
|
24
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
25
|
+
|
|
26
|
+
const installed = [];
|
|
27
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
28
|
+
if (!entry.isDirectory()) continue;
|
|
29
|
+
const dest = path.join(destDir, entry.name);
|
|
30
|
+
// Replace only skills this package ships; other skills in the folder are untouched.
|
|
31
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
32
|
+
fs.cpSync(path.join(srcDir, entry.name), dest, { recursive: true });
|
|
33
|
+
installed.push(entry.name);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log(`skills: installed ${installed.length} skills into ${destDir}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
main();
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(`skills: failed to install skills: ${err.message}`);
|
|
43
|
+
// Never break the consumer's `npm install`; the manual npx command can be rerun.
|
|
44
|
+
process.exitCode = isPostinstall ? 0 : 1;
|
|
45
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sitar_fiercer4c/skills",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Claude Code agent skills, installed into the project's .claude/skills directory",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/thenextepisode-stealth/skills.git"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"skills": "bin/install.js"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"postinstall": "node bin/install.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/",
|
|
18
|
+
"skills/",
|
|
19
|
+
"!skills/*/evals/**",
|
|
20
|
+
"!skills/*/datalab_raw/**",
|
|
21
|
+
"!**/__pycache__/**"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "restricted"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architecture-walkthrough
|
|
3
|
+
description: Build up Backend/ARCHITECTURE.md for the murtaza-hotel-project backend one section at a time, tracing real code and walking each section through in chat before writing it. Use this skill whenever the user wants to understand, document, trace, or explain any part of that backend — asks about a workflow (login, Outlook OAuth, inbox, attachment preview, extraction pipeline, quotation editing, Excel/PDF export), asks to fill in or continue ARCHITECTURE.md, asks "how does X work" about that repo, or asks what files run for a given feature. Also use it when adding a new section to that doc, revising one already written, or refreshing sections after the backend code has changed.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Architecture walkthrough
|
|
7
|
+
|
|
8
|
+
## What this builds
|
|
9
|
+
|
|
10
|
+
`/home/dev/workspaces/murtaza-workspaces/murtaza-hotel-project/Backend/ARCHITECTURE.md` — a
|
|
11
|
+
workflow-organised map of that backend, written for someone learning the codebase.
|
|
12
|
+
|
|
13
|
+
The doc is organised by workflow, not by layer. Each **H2 is a business workflow** (what the user is
|
|
14
|
+
trying to do); each **H3 under it is a technical workflow** that implements part of it. It was
|
|
15
|
+
created deliberately empty — introduction plus headings — and is filled in one H3 at a time.
|
|
16
|
+
|
|
17
|
+
Read `references/sections.md` for the current section list, the file inventory for each, and the
|
|
18
|
+
findings already verified against source.
|
|
19
|
+
|
|
20
|
+
## The protocol
|
|
21
|
+
|
|
22
|
+
This is the part that matters most. The doc is how the reader learns the codebase, so **the chat
|
|
23
|
+
pass is the review and the file is the record.** Writing first inverts that: prose the reader never
|
|
24
|
+
validated accumulates in the doc, and they lose the chance to say "explain that better" or "that
|
|
25
|
+
level is wrong for me" before it sets.
|
|
26
|
+
|
|
27
|
+
For each section:
|
|
28
|
+
|
|
29
|
+
1. **Trace the real code.** Open every file in the section's inventory and follow the actual call
|
|
30
|
+
chain. See "Tracing" below — this is where the section's accuracy is won or lost.
|
|
31
|
+
2. **Draft the section in chat**, complete and in the template format below. Not a summary of what
|
|
32
|
+
you'll write — the section itself.
|
|
33
|
+
3. **Stop and wait.** Do not touch ARCHITECTURE.md. The user reads it and responds.
|
|
34
|
+
4. **Revise in chat** until they approve. Their questions during this pass are where the section's
|
|
35
|
+
Notes come from — see "What goes in Notes".
|
|
36
|
+
5. **Then write it** to the doc, as approved.
|
|
37
|
+
|
|
38
|
+
If the user pre-authorises writing ("just write it", "draft and add 3.5 straight in"), skip the gate
|
|
39
|
+
— but still trace before drafting. The gate is about their review, not about being cautious.
|
|
40
|
+
|
|
41
|
+
Take one section per pass. Section 3.4, the extraction pipeline, is large enough that it is worth
|
|
42
|
+
splitting across several passes and saying so before starting.
|
|
43
|
+
|
|
44
|
+
## Updating a section after the code changes
|
|
45
|
+
|
|
46
|
+
A written section is a claim about code that may have moved on since. When the user says the code
|
|
47
|
+
changed and the doc needs to catch up, do not re-derive the section from scratch and do not trust
|
|
48
|
+
what it currently says.
|
|
49
|
+
|
|
50
|
+
Work one section at a time, through the same gate as writing a new one:
|
|
51
|
+
|
|
52
|
+
1. **Read the section as it stands**, then re-trace its inventory files in the current source.
|
|
53
|
+
2. **Work out what actually differs** — citations that no longer land on the code they name, claims
|
|
54
|
+
about the flow that no longer hold, and code the section never mentioned.
|
|
55
|
+
3. **Draft the revised section in chat**, complete and in the template format, and say plainly what
|
|
56
|
+
changed and what you are leaving alone.
|
|
57
|
+
4. **Stop and wait**, revise until approved, then write it.
|
|
58
|
+
|
|
59
|
+
Keep the gate here rather than rewriting straight in. A section that has been through the user's
|
|
60
|
+
review carries their decisions about depth and emphasis, and a silent rewrite discards them where
|
|
61
|
+
the reader has no way to notice. Showing the diff in chat is also what tells them whether the change
|
|
62
|
+
is a line number or a change in how the system works.
|
|
63
|
+
|
|
64
|
+
If the trace turns up code with no home in the doc — a new service, a step no section covers —
|
|
65
|
+
propose where it belongs rather than filing it silently or leaving it out.
|
|
66
|
+
|
|
67
|
+
## Tracing
|
|
68
|
+
|
|
69
|
+
Every claim in a section must come from source you opened. Three things in this repo will mislead
|
|
70
|
+
you if you trust them:
|
|
71
|
+
|
|
72
|
+
- **Doc comments in the code.** Most comments in `email.controller.js` and `email.service.js` say
|
|
73
|
+
the routes are `/api/email/...`. They are wrong — `app.js:92` mounts that router at `/api`, so
|
|
74
|
+
the real path is `/api/inbox`. A whole section was drafted incorrectly from these comments before
|
|
75
|
+
anyone opened `app.js`.
|
|
76
|
+
- **The repo's other docs.** `README.md`, `QUOTATION.md`, `ATTACHMENT_TO_EXCEL_FLOW.md` and
|
|
77
|
+
`CODE_REVIEW.md` all predate the 2026-08-30 extraction refactors. They describe Datalab as an
|
|
78
|
+
optional step after OfficeCLI; it now runs in parallel with bounding-box merging.
|
|
79
|
+
- **A subagent's summary.** Subagents are useful for locating files and listing importers. They read
|
|
80
|
+
excerpts, so their narrative of a flow is a lead to verify, not a source to quote.
|
|
81
|
+
|
|
82
|
+
Cite `file.js:LINE` for every function you name, and confirm the line still holds what you say it
|
|
83
|
+
does before writing it down.
|
|
84
|
+
|
|
85
|
+
## The section template
|
|
86
|
+
|
|
87
|
+
Read sections 3.1–3.3 in ARCHITECTURE.md before drafting. **They are the format specification** — if
|
|
88
|
+
they and this skill ever disagree on shape or voice, the doc wins, because it reflects the most
|
|
89
|
+
recent round of the user's feedback.
|
|
90
|
+
|
|
91
|
+
Their Notes blocks are the one thing not to copy the scale of. Those notes accumulated over several
|
|
92
|
+
rounds of the reader asking questions, so a written section holds more of them than any draft of it
|
|
93
|
+
did. Match their voice, not their length.
|
|
94
|
+
|
|
95
|
+
````markdown
|
|
96
|
+
### 3.N Section name
|
|
97
|
+
|
|
98
|
+
**What this does for the business workflow:** 15–30 words, plain English, from the operator's point
|
|
99
|
+
of view. What they are trying to accomplish, and what this step contributes.
|
|
100
|
+
|
|
101
|
+
`METHOD /path` — or, when a section covers more than one endpoint, a sentence naming each.
|
|
102
|
+
|
|
103
|
+
**Input:** what arrives — auth state, URL params, query flags, body.
|
|
104
|
+
|
|
105
|
+
**Output:** what goes back, plus side effects (documents written, jobs started).
|
|
106
|
+
|
|
107
|
+
**Files:** the files whose code actually runs, comma-separated, backticked.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
[ASCII diagram]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Notes** (optional)
|
|
114
|
+
|
|
115
|
+
Unnumbered paragraphs, one idea each. See "What goes in Notes" — often absent on a first draft.
|
|
116
|
+
````
|
|
117
|
+
|
|
118
|
+
**Do not add a Steps block by default.** The diagram, plus whatever notes the diagram cannot hold,
|
|
119
|
+
is the finished shape. The diagram already carries the sequence, so prose that walks the same stages
|
|
120
|
+
again is the same information twice and buries the notes that are actually load-bearing.
|
|
121
|
+
|
|
122
|
+
Add **Steps** only when the reader asks for more — "explain each step a little more", "I can't
|
|
123
|
+
follow the diagram here". Then write one bold imperative title per stage, numbered to match the
|
|
124
|
+
diagram's `(1)…(N)`, two to four sentences each:
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
**Steps**
|
|
128
|
+
|
|
129
|
+
**(1) Imperative title.** Two to four sentences expanding that stage of the diagram.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Section 3.3 in the doc carries Steps because the reader asked for them there. Do not read that as
|
|
133
|
+
the default.
|
|
134
|
+
|
|
135
|
+
## What goes in Notes
|
|
136
|
+
|
|
137
|
+
Every note costs the reader a detour away from the diagram, so a note has to earn its place, and
|
|
138
|
+
there are only two ways it can.
|
|
139
|
+
|
|
140
|
+
**One: the fact has no shape in a flow.** The diagram is where every fact goes first — as a node, a
|
|
141
|
+
label beside a node, a branch condition, an error exit, an annotation stacked to the right. Before
|
|
142
|
+
keeping a note, try to draw it; if it fits in the diagram, move it there and cut the note. What is
|
|
143
|
+
left over is the material with no arrow: an inconsistency between two files, a reason stated in a
|
|
144
|
+
code comment, a constraint that lives outside the call chain the diagram traces.
|
|
145
|
+
|
|
146
|
+
**Two: the reader asked.** When they read the draft and ask "what does `.lean()` do here?" or "why
|
|
147
|
+
two round trips?", that question is the section telling you what it is missing. Answer in chat, then
|
|
148
|
+
fold the answer into Notes when you write the section, in the doc's own voice — not "you asked
|
|
149
|
+
about X", just the explanation.
|
|
150
|
+
|
|
151
|
+
The second source is why a first draft's Notes should be thin. Two or three notes is a normal draft;
|
|
152
|
+
none at all is a legitimate draft and the block can be left out entirely. Resist explaining the Node
|
|
153
|
+
and JS idioms up front, even though the reader is weak there and a diagram cannot hold them: you
|
|
154
|
+
cannot tell which ones they already know, and a draft that answers eight guessed questions buries
|
|
155
|
+
the one or two notes that are actually load-bearing. The questions they do ask are better evidence
|
|
156
|
+
than your guess at them, and the review gate exists to collect them.
|
|
157
|
+
|
|
158
|
+
When you revise a written section after the code changes, treat the notes already in it as answers
|
|
159
|
+
the reader once asked for. Keep them unless the code they describe is gone.
|
|
160
|
+
|
|
161
|
+
## Diagram conventions
|
|
162
|
+
|
|
163
|
+
The diagram carries the flow; the prose carries what a diagram cannot express. Follow the diagrams
|
|
164
|
+
already in the doc:
|
|
165
|
+
|
|
166
|
+
- Flow runs downward with `│` and `▼`, starting at ` client`.
|
|
167
|
+
- A node is `path/file.js:LINE` and, where useful, the function name beside it.
|
|
168
|
+
- External calls go right with `──►`, with the URL and its query parameters stacked to the right.
|
|
169
|
+
- Error exits go on the same line as their cause: `none → 400 "Outlook is not connected"`.
|
|
170
|
+
- Branches use `├─` and `└─`, with the condition first and the outcome after `──►`.
|
|
171
|
+
- A box `┌─┐` expands a sub-sequence inlined at that point.
|
|
172
|
+
- Numbered stages `(1)`, `(2)` label branch points inside the diagram. They stand on their own; they
|
|
173
|
+
do not oblige you to write a Steps block, but they supply its numbering if one is asked for later.
|
|
174
|
+
- One diagram per endpoint. A section covering two endpoints gets two diagrams.
|
|
175
|
+
|
|
176
|
+
## Writing style
|
|
177
|
+
|
|
178
|
+
**Do not editorialize.** Explain what the code does; do not offer a verdict on it. Phrasings like
|
|
179
|
+
"the interesting bit", "this looks wasteful", "one thing to not mix up" were called out and removed.
|
|
180
|
+
|
|
181
|
+
When the code has a reason, attribute it to the comment that states it rather than presenting it as
|
|
182
|
+
your own reading:
|
|
183
|
+
|
|
184
|
+
> The comment at `email.service.js:416` gives the reason: locating the attachment inside a message
|
|
185
|
+
> fetched with this user's own token confirms it belongs to them.
|
|
186
|
+
|
|
187
|
+
State anomalies as facts and let the reader draw the conclusion:
|
|
188
|
+
|
|
189
|
+
> `getInbox` inlines the load-refresh-retry sequence that `withGraph()` (line 321) exists to hold.
|
|
190
|
+
|
|
191
|
+
not "this is duplicated code that should be refactored."
|
|
192
|
+
|
|
193
|
+
**Pitch to the reader.** They are strong in Python, SQL, Linux, relational and NoSQL databases,
|
|
194
|
+
system design, data flow and ETL pipelines; weak in JavaScript, Node, npm and anything frontend.
|
|
195
|
+
|
|
196
|
+
So when an explanation is called for — they asked, or you are writing Steps — the Node and JS idioms
|
|
197
|
+
are what to spend it on: a promise deliberately not awaited, Mongoose `select: false`, a callback
|
|
198
|
+
passed to a wrapper function, ESM default-export objects. Never spend it on database indexes, atomic
|
|
199
|
+
updates, HTTP status codes or what a pipeline stage is; they know those better than you do.
|
|
200
|
+
|
|
201
|
+
This tells you which explanations are worth writing, not that a draft should pre-empt them — see
|
|
202
|
+
"What goes in Notes".
|
|
203
|
+
|
|
204
|
+
Prefer short paragraphs over long ones, and concrete nouns over abstractions. Ordinary sentences,
|
|
205
|
+
not bullet fragments, in Steps and Notes.
|
|
206
|
+
|
|
207
|
+
## Before presenting
|
|
208
|
+
|
|
209
|
+
Run the structure check on your draft:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
python3 scripts/check_structure.py <path-to-ARCHITECTURE.md> # all sections
|
|
213
|
+
python3 scripts/check_structure.py <path-to-ARCHITECTURE.md> --section 3.5
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
It verifies the template is complete — description present and 15–35 words, Input/Output/Files,
|
|
217
|
+
at least one diagram and `file:line` citations, with no banned editorializing phrases. Notes and
|
|
218
|
+
Steps are both optional: a missing Notes block is reported as a warning rather than a failure, and a
|
|
219
|
+
missing Steps block is not reported at all. If Steps are present their numbering must match the
|
|
220
|
+
diagram. The check is shape only; accuracy is on you.
|
|
221
|
+
|
|
222
|
+
Empty headings are reported as `empty` and are not failures — the doc is meant to be filled in
|
|
223
|
+
gradually.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Sections, file inventories, and verified findings
|
|
2
|
+
|
|
3
|
+
Paths below are relative to
|
|
4
|
+
`/home/dev/workspaces/murtaza-workspaces/murtaza-hotel-project/Backend/src/`.
|
|
5
|
+
|
|
6
|
+
## Doc state
|
|
7
|
+
|
|
8
|
+
| Section | Title | Status |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| 1.1 | Registration | written |
|
|
11
|
+
| 1.2 | Login | written |
|
|
12
|
+
| 1.3 | Password reset | written |
|
|
13
|
+
| 1.4 | Session validation | written |
|
|
14
|
+
| 2.1 | Starting the connection | written |
|
|
15
|
+
| 2.2 | OAuth callback and token storage | written |
|
|
16
|
+
| 2.3 | Silent token refresh | written |
|
|
17
|
+
| 2.4 | Connection status and disconnect | written |
|
|
18
|
+
| 3.1 | Browsing the inbox | written |
|
|
19
|
+
| 3.2 | Previewing an attachment | written |
|
|
20
|
+
| 3.3 | Triggering extraction | written |
|
|
21
|
+
| 3.4 | The extraction pipeline | written — spine plus 3.4.1–3.4.5 |
|
|
22
|
+
| 3.5 | Reading a quotation | written |
|
|
23
|
+
| 3.6 | Editing a quotation | written |
|
|
24
|
+
| 3.7 | Exporting to Excel | written |
|
|
25
|
+
| 3.8 | Exporting to PDF | written |
|
|
26
|
+
| 3.9 | Sending the quotation by email | written |
|
|
27
|
+
| — | Known issues (H2 at the end of the doc) | written |
|
|
28
|
+
|
|
29
|
+
Re-derive this table from the doc rather than trusting it; sections get filled in between uses.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Check that ARCHITECTURE.md sections follow the walkthrough template.
|
|
3
|
+
|
|
4
|
+
Shape only — it cannot tell you whether a section is accurate. Empty headings are
|
|
5
|
+
reported as `empty` and never fail, because the doc is filled in gradually. Notes and
|
|
6
|
+
Steps are both optional; a missing Notes block is a warning, not a failure.
|
|
7
|
+
|
|
8
|
+
python3 check_structure.py path/to/ARCHITECTURE.md
|
|
9
|
+
python3 check_structure.py path/to/ARCHITECTURE.md --section 3.5
|
|
10
|
+
python3 check_structure.py path/to/ARCHITECTURE.md --json
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
DESC_LABEL = "**What this does for the business workflow:**"
|
|
19
|
+
DESC_MIN, DESC_MAX = 15, 35
|
|
20
|
+
|
|
21
|
+
ENDPOINT_RE = re.compile(r"`(GET|POST|PUT|PATCH|DELETE)\s+/")
|
|
22
|
+
CITATION_RE = re.compile(r"[\w./-]+\.(?:js|mjs|json):\d+")
|
|
23
|
+
STAGE_RE = re.compile(r"\((\d+)\)")
|
|
24
|
+
STEP_RE = re.compile(r"^\*\*\((\d+)\)")
|
|
25
|
+
FENCE_RE = re.compile(r"^```")
|
|
26
|
+
|
|
27
|
+
# Phrasings the reader has asked to keep out: verdicts on the code rather than
|
|
28
|
+
# descriptions of it.
|
|
29
|
+
BANNED = [
|
|
30
|
+
"interesting bit",
|
|
31
|
+
"the interesting",
|
|
32
|
+
"looks wasteful",
|
|
33
|
+
"seems wasteful",
|
|
34
|
+
"not mix up",
|
|
35
|
+
"should be refactored",
|
|
36
|
+
"code smell",
|
|
37
|
+
"in my opinion",
|
|
38
|
+
"i think",
|
|
39
|
+
"arguably",
|
|
40
|
+
"unfortunately",
|
|
41
|
+
"sadly",
|
|
42
|
+
"cleverly",
|
|
43
|
+
"elegantly",
|
|
44
|
+
"surprisingly",
|
|
45
|
+
"oddly enough",
|
|
46
|
+
"the good news",
|
|
47
|
+
"the bad news",
|
|
48
|
+
"worth noting that",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def split_sections(text):
|
|
53
|
+
"""Yield (number, title, body_lines) for every H3 heading."""
|
|
54
|
+
lines = text.splitlines()
|
|
55
|
+
starts = [
|
|
56
|
+
(i, m.group(1), m.group(2).strip())
|
|
57
|
+
for i, line in enumerate(lines)
|
|
58
|
+
if (m := re.match(r"^###\s+([\d.]+)\s+(.*)$", line))
|
|
59
|
+
]
|
|
60
|
+
for pos, (idx, number, title) in enumerate(starts):
|
|
61
|
+
end = len(lines)
|
|
62
|
+
for j in range(idx + 1, len(lines)):
|
|
63
|
+
if lines[j].startswith("### ") or lines[j].startswith("## "):
|
|
64
|
+
end = j
|
|
65
|
+
break
|
|
66
|
+
if pos + 1 < len(starts):
|
|
67
|
+
end = min(end, starts[pos + 1][0])
|
|
68
|
+
yield number, title, lines[idx + 1 : end]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def fenced_blocks(body):
|
|
72
|
+
blocks, current, inside = [], [], False
|
|
73
|
+
for line in body:
|
|
74
|
+
if FENCE_RE.match(line):
|
|
75
|
+
if inside:
|
|
76
|
+
blocks.append(current)
|
|
77
|
+
current, inside = [], False
|
|
78
|
+
else:
|
|
79
|
+
inside = True
|
|
80
|
+
continue
|
|
81
|
+
if inside:
|
|
82
|
+
current.append(line)
|
|
83
|
+
return blocks
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def description_words(body):
|
|
87
|
+
for i, line in enumerate(body):
|
|
88
|
+
if line.strip().startswith(DESC_LABEL):
|
|
89
|
+
para = [line.strip()[len(DESC_LABEL) :]]
|
|
90
|
+
for nxt in body[i + 1 :]:
|
|
91
|
+
if not nxt.strip():
|
|
92
|
+
break
|
|
93
|
+
para.append(nxt)
|
|
94
|
+
return len(re.findall(r"[A-Za-z0-9][\w'`./:-]*", " ".join(para)))
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def check(number, title, body):
|
|
99
|
+
text = "\n".join(body)
|
|
100
|
+
prose = "\n".join(
|
|
101
|
+
line for line in body if not line.startswith("```")
|
|
102
|
+
) # banned-phrase scan includes diagrams; harmless
|
|
103
|
+
|
|
104
|
+
if not text.strip():
|
|
105
|
+
return {"section": number, "title": title, "status": "empty", "checks": []}
|
|
106
|
+
|
|
107
|
+
blocks = fenced_blocks(body)
|
|
108
|
+
words = description_words(body)
|
|
109
|
+
stages = sorted({int(n) for b in blocks for n in STAGE_RE.findall("\n".join(b))})
|
|
110
|
+
steps = sorted(int(m.group(1)) for line in body if (m := STEP_RE.match(line)))
|
|
111
|
+
lowered = prose.lower()
|
|
112
|
+
hits = [p for p in BANNED if p in lowered]
|
|
113
|
+
|
|
114
|
+
checks = [
|
|
115
|
+
("business description present", "required", words is not None,
|
|
116
|
+
"add the `**What this does for the business workflow:**` line"),
|
|
117
|
+
(f"description is {DESC_MIN}-{DESC_MAX} words", "required",
|
|
118
|
+
words is not None and DESC_MIN <= words <= DESC_MAX,
|
|
119
|
+
f"description is {words} words"),
|
|
120
|
+
("endpoint named", "required", bool(ENDPOINT_RE.search(text)),
|
|
121
|
+
"name the route as `METHOD /path`"),
|
|
122
|
+
("Input stated", "required", "**Input:**" in text, "add an `**Input:**` line"),
|
|
123
|
+
("Output stated", "required", "**Output:**" in text, "add an `**Output:**` line"),
|
|
124
|
+
("Files listed", "required", "**Files:**" in text, "add a `**Files:**` line"),
|
|
125
|
+
("diagram present", "required", len(blocks) > 0, "add the ASCII flow diagram"),
|
|
126
|
+
("file:line citations", "required", bool(CITATION_RE.search(text)),
|
|
127
|
+
"cite file.js:LINE for the functions named"),
|
|
128
|
+
# Advisory, not required: Notes carry only what the diagram cannot and what the reader
|
|
129
|
+
# asked about, so a section with neither has nothing to say here. Failing the check would
|
|
130
|
+
# buy a filler paragraph.
|
|
131
|
+
("Notes section", "advisory", "**Notes**" in text,
|
|
132
|
+
"no `**Notes**` block — fine if nothing qualified"),
|
|
133
|
+
("no editorializing", "required", not hits,
|
|
134
|
+
f"banned phrasing: {', '.join(hits)}" if hits else ""),
|
|
135
|
+
# A Steps block is optional — the diagram plus Notes is the finished shape, and Steps are
|
|
136
|
+
# added only when the reader asks for more. So absence is fine; a mismatch is not.
|
|
137
|
+
("Steps, if present, match the diagram numbering", "required",
|
|
138
|
+
(not steps) or (steps == stages),
|
|
139
|
+
f"diagram stages {stages} vs Steps {steps}"),
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
results = [
|
|
143
|
+
{"name": name, "level": level, "passed": bool(ok), "detail": detail if not ok else ""}
|
|
144
|
+
for name, level, ok, detail in checks
|
|
145
|
+
]
|
|
146
|
+
failed = any(r["level"] == "required" and not r["passed"] for r in results)
|
|
147
|
+
return {
|
|
148
|
+
"section": number,
|
|
149
|
+
"title": title,
|
|
150
|
+
"status": "fail" if failed else "pass",
|
|
151
|
+
"checks": results,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def main():
|
|
156
|
+
ap = argparse.ArgumentParser()
|
|
157
|
+
ap.add_argument("path")
|
|
158
|
+
ap.add_argument("--section", help="check one section, e.g. 3.5")
|
|
159
|
+
ap.add_argument("--json", action="store_true")
|
|
160
|
+
args = ap.parse_args()
|
|
161
|
+
|
|
162
|
+
with open(args.path, encoding="utf-8") as fh:
|
|
163
|
+
text = fh.read()
|
|
164
|
+
|
|
165
|
+
results = [
|
|
166
|
+
check(num, title, body)
|
|
167
|
+
for num, title, body in split_sections(text)
|
|
168
|
+
if not args.section or num == args.section
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
if not results:
|
|
172
|
+
print(f"no section matched {args.section!r}", file=sys.stderr)
|
|
173
|
+
return 2
|
|
174
|
+
|
|
175
|
+
if args.json:
|
|
176
|
+
print(json.dumps(results, indent=2))
|
|
177
|
+
else:
|
|
178
|
+
for r in results:
|
|
179
|
+
if r["status"] == "empty":
|
|
180
|
+
print(f" ~ {r['section']} {r['title']} (empty)")
|
|
181
|
+
continue
|
|
182
|
+
mark = "OK " if r["status"] == "pass" else "FAIL"
|
|
183
|
+
print(f"{mark:>4} {r['section']} {r['title']}")
|
|
184
|
+
for c in r["checks"]:
|
|
185
|
+
if c["passed"]:
|
|
186
|
+
continue
|
|
187
|
+
tag = "fail" if c["level"] == "required" else "warn"
|
|
188
|
+
detail = f" — {c['detail']}" if c["detail"] else ""
|
|
189
|
+
print(f" [{tag}] {c['name']}{detail}")
|
|
190
|
+
|
|
191
|
+
written = [r for r in results if r["status"] != "empty"]
|
|
192
|
+
bad = [r for r in written if r["status"] == "fail"]
|
|
193
|
+
print(f"\n{len(written) - len(bad)}/{len(written)} written sections pass "
|
|
194
|
+
f"({len(results) - len(written)} still empty)")
|
|
195
|
+
|
|
196
|
+
return 1 if any(r["status"] == "fail" for r in results) else 0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
sys.exit(main())
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: autotest-webapp-ui
|
|
3
|
+
description: Automatically test webapp by controlling a chrome browser via CDP
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Permissions
|
|
7
|
+
You have permission to:
|
|
8
|
+
- start servers in a shell
|
|
9
|
+
|
|
10
|
+
# Steps
|
|
11
|
+
|
|
12
|
+
## Inform user
|
|
13
|
+
- open inspect panel since CDP doesnt have tooling for it
|
|
14
|
+
|
|
15
|
+
## Start servers
|
|
16
|
+
- Start frontend & backend server
|
|
17
|
+
|
|
18
|
+
## Inputs from user
|
|
19
|
+
- CDP port - The port on which CDP listens for instructions to control chrome on another machine
|
|
20
|
+
- screenshot frequency (default: last page) - as specified by user.
|
|
21
|
+
- screenshot save path (default: skills/autotest-webapp-ui/autotest-webapp-ui-workspace/<YYYYMMDD-HHMMSS>/<path-n>) - save every run in a timestamped folder where each screenshot name is of format <screenshot-index>-<screenshot-slug> (eg: 01-login_page, 02-email_page)
|
|
22
|
+
- save commands issued to CDP (default: no) - The raw commands sent to CDP to control chrome
|
|
23
|
+
- save the logs from any of the Inspect panel subtabs (default: no): Logs from panels specified by user (Console, Network, Sources, Application, etc)
|
|
24
|
+
|
|
25
|
+
## Preflight checks
|
|
26
|
+
- Check Chrome control over CDP is working by opening google.com and closing it later
|
|
27
|
+
|
|
28
|
+
## Traverse happy paths
|
|
29
|
+
|
|
30
|
+
### Path-1
|
|
31
|
+
- login with email `admin@gmail.com`, password `admin@123`
|
|
32
|
+
- open emails
|
|
33
|
+
- then click on the latest email
|
|
34
|
+
- click on preview, wait for the preview to load
|
|
35
|
+
- close the preview
|
|
36
|
+
- click view quotation, wait for the next page to load
|
|
37
|
+
- scroll the full page and come back to the top
|
|
38
|
+
|
|
39
|
+
## Output
|
|
40
|
+
- Create a .md file in the screenshot directory with following sections
|
|
41
|
+
- Path-n bullet points: copy paste these from above
|
|
42
|
+
- Path-n user flow diagram: Mermaid flowchart. Eg:
|
|
43
|
+
```mermaid
|
|
44
|
+
graph LR
|
|
45
|
+
A(Start) -->B["<img src='<screenhot-01-path>' width='100' hegiht='100'/>"] -->C["<img src='<screenhot-02-path>' width='100' hegiht='100'/>"] -->D(End)
|
|
46
|
+
```
|
|
47
|
+
- Share screenshot path
|
|
48
|
+
- Share paths for other inputs user said yes to
|
|
49
|
+
|
|
50
|
+
## Ask user
|
|
51
|
+
- what path they want to try next
|
|
52
|
+
|
|
53
|
+
## Cleanup
|
|
54
|
+
- Stop frontend & backend server
|
|
55
|
+
|
|
56
|
+
# Constraints & alternatives
|
|
57
|
+
- Do not write intermediate scripts to execute steps. Drive with one-shot commands
|
|
58
|
+
- Do not make any changes to CDP port (eg: killing it, stopping it)
|