standup-mr 0.1.1 → 0.2.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/mcp/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # MCP server
2
2
 
3
- Exposes one tool, `get_standup_data`, returning the same JSON as `standup fetch`.
3
+ Exposes one tool, `get_standup_data`, for either GitLab or GitHub, returning
4
+ the same JSON as `standup fetch`.
4
5
 
5
6
  ## Install
6
7
 
@@ -10,6 +11,8 @@ npm install standup-mr @modelcontextprotocol/sdk
10
11
 
11
12
  ## Configure
12
13
 
14
+ GitLab:
15
+
13
16
  ```json
14
17
  {
15
18
  "mcpServers": {
@@ -25,9 +28,28 @@ npm install standup-mr @modelcontextprotocol/sdk
25
28
  }
26
29
  ```
27
30
 
28
- `GITLAB_HOST` and `GITLAB_TOKEN` are the supported configuration for MCP use. If
29
- `glab` happens to be installed and authenticated it is used as a fallback, but do
30
- not rely on that inside a container.
31
+ GitHub:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "standup": {
37
+ "command": "node",
38
+ "args": ["/absolute/path/to/standup-mr/dist/mcp/server.js"],
39
+ "env": {
40
+ "GITHUB_HOST": "github.com",
41
+ "GITHUB_TOKEN": "ghp_..."
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ `GITLAB_HOST`/`GITLAB_TOKEN` and `GITHUB_HOST`/`GITHUB_TOKEN` are the supported
49
+ configuration for MCP use — set whichever pair matches the provider you want.
50
+ If `glab` or `gh` happens to be installed and authenticated it is used as a
51
+ fallback, but do not rely on that inside a container.
31
52
 
32
- The tool returns data only. Ask your client to write the note, or use the Claude
33
- Code skill in `skill/`, which carries the note-writing rules.
53
+ The tool returns data only. Ask your client to write the note, or install the
54
+ Claude Code plugin (`/plugin install standup@standup-mr`), which carries the
55
+ note-writing rules.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "standup-mr",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Standup notes from merge request state, not commit logs.",
5
- "keywords": ["standup", "gitlab", "merge-request", "cli", "mcp"],
5
+ "keywords": ["standup", "gitlab", "github", "merge-request", "pull-request", "cli", "mcp"],
6
6
  "license": "MIT",
7
7
  "author": {
8
8
  "name": "İlker Balcılar",
@@ -31,10 +31,11 @@
31
31
  "bin": { "standup": "./dist/cli.js" },
32
32
  "main": "./dist/index.js",
33
33
  "types": "./dist/index.d.ts",
34
- "files": ["dist", "skill", "mcp/README.md", "README.md", "LICENSE"],
34
+ "files": ["dist", "skills", "mcp/README.md", "README.md", "CHANGELOG.md", "LICENSE"],
35
35
  "scripts": {
36
36
  "build": "tsup",
37
37
  "test": "bun test",
38
+ "test:tz": "TZ=Europe/Istanbul bun test ./src/dates/dates.tz.istanbul.cases.ts && TZ=America/Los_Angeles bun test ./src/dates/dates.tz.los-angeles.cases.ts",
38
39
  "typecheck": "tsc --noEmit",
39
40
  "prepublishOnly": "tsup"
40
41
  },
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: standup
3
+ description: >-
4
+ Generates a daily standup note from GitLab merge request or GitHub pull
5
+ request state. Groups the previous working day's activity into themes,
6
+ reports which merge requests are ready to merge or blocked, and diagnoses
7
+ failed pipelines from their job logs. Use for "/standup", "standup note",
8
+ "what did I do yesterday", "what's on my plate today", "daily note".
9
+ ---
10
+
11
+ # Standup Note
12
+
13
+ Goal: put the things worth *saying* in front of the user before their standup.
14
+ Not a commit log — what finished, what is waiting, what is stuck.
15
+
16
+ ## 1. Collect
17
+
18
+ ```bash
19
+ npx standup-mr fetch
20
+ ```
21
+
22
+ Prints one JSON document. The command picks GitLab or GitHub on its own — from
23
+ flags, host, environment, or whichever of `gh`/`glab` is logged in. If the user
24
+ already said which one they mean, pass it explicitly instead of guessing:
25
+
26
+ ```bash
27
+ npx standup-mr fetch --provider github
28
+ npx standup-mr fetch --provider gitlab
29
+ ```
30
+
31
+ Add `--lang tr` for Turkish date labels. Nothing else needs running: the
32
+ command resolves the host and token, works out which day to report on, and
33
+ reads failed job logs itself.
34
+
35
+ If the command exits non-zero, relay its stderr verbatim — do not invent a
36
+ cause. The usual fix is `gh auth login` or `glab auth login`, depending on
37
+ which provider it was trying to reach.
38
+
39
+ ## 2. Shape of the JSON
40
+
41
+ | Field | Contents |
42
+ |---|---|
43
+ | `provider` | `gitlab` or `github` — decides the vocabulary, see below |
44
+ | `previousDays` | Chronologically ascending list of active days since the last report. Each entry: `date`, `label`, `gapDays`, `events` |
45
+ | `todayEvents` | Anything already done today (usually empty) |
46
+ | `myMrs` | Open merge/pull requests with `bucket`: `ready` / `blocked` / `draft` / `stale`, plus `mergeStatus` and `pipelineMissing` |
47
+ | `reviews` | Review requests, with `fresh` and `approvedByMe` |
48
+ | `reviewPendingCount` | Reviews genuinely awaiting action |
49
+ | `blockers` | Failed CI runs with real error lines pulled from the job log |
50
+
51
+ Each entry in `previousDays` carries its own `events` — `action`, `project`,
52
+ `branch`, `commits`, `commitTitle`. **Every active day gets its own section in
53
+ the note; never fold one day into another.** Running on a Monday typically
54
+ means the list holds Friday plus any weekend day that had activity — one entry
55
+ if the weekend was quiet, more if it was not — and each must be written up
56
+ under its own `label`, never merged into a single "yesterday".
57
+
58
+ ## 3. Write the note
59
+
60
+ Three sections: **Previous day · Today · Blockers**. Short, in the language the
61
+ user is speaking, phrased the way they would say it out loud.
62
+
63
+ ### Previous day
64
+
65
+ Write one section per entry in `previousDays`, in order, each headed by its own
66
+ `label`. Never say "yesterday" — after a weekend or a day off it is wrong, and
67
+ the label already carries the right day.
68
+
69
+ **Group by theme within each day; never list events one by one.** A 60-event
70
+ day should collapse to four to six bullets. Group on project + branch + subject:
71
+
72
+ > **Virtual keyboard — two fixes, two releases** (`acme/ui` → main)
73
+ > - keeps scaling on large screens, no longer widens modals → **0.5.13**
74
+ > - mirrors the settled field value, not the in-flight one → **0.5.14**
75
+
76
+ `commitTitle` values are conventional commits; use the scope as the grouping
77
+ hint. Fold merges, branch deletions and tags into the sentence rather than
78
+ giving them their own bullets.
79
+
80
+ When one subject spans several projects in a day — dependency alignment, a CI
81
+ rollout — make it **one bullet** and say how many projects it touched.
82
+
83
+ ### Today
84
+
85
+ - **`ready`** → count them, give project + reference. The bucket name means
86
+ "nothing known is blocking it" — it is **not** a claim that the merge/pull
87
+ request is mergeable. Use `mergeStatus` to say which:
88
+ - `mergeable` → say it plainly, "ready to merge".
89
+ - `unchecked` (GitLab has not evaluated it yet) → say so explicitly, e.g.
90
+ "GitLab hasn't checked mergeability yet" — never round this up to "all
91
+ green".
92
+ - anything else (`conflict`, `need_rebase`, `discussions_not_resolved`,
93
+ GitHub's `dirty`/`blocked`/`behind`, …) → name that specific reason instead
94
+ of the generic bucket label.
95
+ - `null` (the field is `string | null`) → say **nothing** about mergeability.
96
+ The provider did not report it; do not guess a reason and do not round it
97
+ up to "ready to merge".
98
+ - If `pipelineMissing` is true, say **"no pipeline ever ran"** explicitly. Do
99
+ not let it pass as green.
100
+ - **`blocked`** → say which: red pipeline, unresolved comments, or both. On
101
+ GitHub the thing that blocks is a **change request**
102
+ (`CHANGES_REQUESTED`), not an unresolved comment thread — `unresolved` holds
103
+ the count of reviewers who requested changes.
104
+ - **`draft`** → what needs finishing. Collapse drafts that share a branch prefix
105
+ or scope into one line, and flag it when they must merge in order.
106
+ - **`stale`** → a count and the oldest date. No long list.
107
+
108
+ For reviews, use `reviewPendingCount` on **both** providers, not the raw length
109
+ of `reviews`. GitLab keeps you on the reviewer list after you approve, so its
110
+ raw count overstates the work; GitHub drops you from the list once you approve,
111
+ so `approvedByMe` is almost always `false` there — `reviewPendingCount` is the
112
+ field that stays trustworthy either way. List the pending ones with author and
113
+ reference. If the user has both their own merge/pull request and a review in
114
+ the same project, note the conflict risk.
115
+
116
+ ### Vocabulary
117
+
118
+ Match the platform's own words. When `provider` is `github`, say "pull
119
+ request" and reference it as `#123`. When it is `gitlab`, say "merge request"
120
+ and reference it as `!123`. The bucket names (`ready` / `blocked` / `draft` /
121
+ `stale`) stay the same on both sides — only the noun and the reference prefix
122
+ change.
123
+
124
+ ### Blockers
125
+
126
+ If `blockers` is empty, **omit the section entirely.** Never write "no blockers".
127
+
128
+ Otherwise the useful content is the lines in `errors`, not the job name — on
129
+ GitLab those lines come from a failed pipeline job's trace, on GitHub from a
130
+ failed Actions job's log or from a non-Actions check's summary. The rule does
131
+ not change with the provider: what matters is what `errors` says, not which
132
+ job produced it. Collapse several merge/pull requests sharing one root cause
133
+ into a single blocker.
134
+
135
+ > The CI token cannot pull the private packages — `npm ci` gets a 404. Two
136
+ > pipelines are red for the same reason; the third passes because it has no such
137
+ > dependency.
138
+
139
+ A private package registry returning **404 instead of 403** usually means the
140
+ token's scope is wrong, not that the package is missing. Say so when the pattern
141
+ fits.
142
+
143
+ ## Rules
144
+
145
+ - Speak from the data the command returned. If unsure about a merge request,
146
+ verify it rather than guessing.
147
+ - If `todayEvents` is non-empty, do not say "nothing done today" — call out the
148
+ work already started.
149
+ - The note gets read aloud: one breath per bullet, no three-line paragraphs.