Skip to content

Commit 5d49b92

Browse files
authored
Merge branch 'master' into sheetalnair/fix-text-outline
2 parents cd321ec + a59280d commit 5d49b92

1,062 files changed

Lines changed: 71899 additions & 33786 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"permissions": {
3+
"deny": [
4+
"Bash(npm install *)"
5+
],
6+
"allow": [
7+
"Bash(rushx build *)",
8+
"Bash(rushx test *)",
9+
"Bash(rushx lint *)",
10+
"Bash(rushx docs *)",
11+
"Bash(rushx extract-api)",
12+
"Bash(rushx clean)",
13+
"Bash(rushx cover)",
14+
"Bash(rush build)",
15+
"Bash(rush install)",
16+
"Bash(rush extract-api)",
17+
"Bash(rush lint)",
18+
"Bash(rush change)",
19+
"Bash(rush clean)",
20+
"Bash(rush cover)",
21+
"Bash(rush test)",
22+
"Bash(rush audit)",
23+
"Bash(npm view *)",
24+
"Bash(pnpm why *)"
25+
]
26+
}
27+
}

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Ensure these file types use the correct OS specific line endings
66
*.bat eol=crlf
77
*.sh eol=lf
8+
*.api.md eol=lf
89
presentation/common/Ruleset.schema.json text eol=lf
910
*.snap eol=lf
1011

.github/agents/cve-audit.agent.md

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ rush install
3535
```
3636

3737
- **Do not create the security branch yet.** The branch name requires a CVE ID, which is only known after the audit in Step 1. Branch creation happens in Execution Flow Step 1b (after the audit).
38-
- For multiple CVEs, use the highest-severity CVE/GHSA ID for the branch name and include others in the commit/PR text. If severity is equal, use the first ID returned by `rush audit --json`.
38+
- For multiple CVEs, use the highest-severity CVE/GHSA ID for the branch name and include others in the commit/PR text. If severity is equal, use the first ID from the audit table output.
3939

4040
### Protected Branch Guard (Required)
4141

@@ -79,14 +79,13 @@ rush change --bulk --message "" --bump-type none -b origin/<starting-branch>
7979
1. Audit — run on the starting branch before creating any branch or making any changes:
8080

8181
```bash
82-
rush audit --level high
83-
rush audit --json > /tmp/cve-audit-results.json
82+
rush audit
8483
```
8584

86-
Parse `/tmp/cve-audit-results.json` to extract CVE/GHSA IDs, severities, advisory URLs, and dependency paths. These values drive all subsequent steps (branch name, commit message, PR body, deferral issues).
85+
**Note:** `rush audit` internally invokes `rush-pnpm audit --audit-level high`. It does **not** accept `--level` or `--json` flags directly. Parse the table output to extract CVE/GHSA IDs, severities, advisory URLs, and dependency paths. Use `rush-pnpm why <package>` to investigate transitive dependency paths when the audit output shows truncated paths.
8786

8887
**1b. Early exit if no High/Critical CVEs found:**
89-
If `rush audit --level high` reports zero High or Critical vulnerabilities — **stop here**. Do not create a branch. Do not run `rush update --full`. Report all-clear to the invoker.
88+
If `rush audit` reports zero High or Critical vulnerabilities — **stop here**. Do not create a branch. Do not run `rush update`. Report all-clear to the invoker.
9089

9190
**1c. Create security branch (now that CVE ID is known):**
9291
```bash
@@ -98,12 +97,21 @@ git rev-parse --verify security/<first-CVE-ID> >/dev/null 2>&1 \
9897

9998
2. Fast-path auto updates — attempt before any manual changes:
10099

100+
```bash
101+
rush update
102+
rush audit
103+
```
104+
105+
Start with `rush update` (without `--full`) — it is faster and less disruptive. Re-run the audit immediately. If High/Critical vulnerabilities are cleared, proceed to Step 4 (verify).
106+
107+
If High/Critical remain, escalate to a full re-resolve:
108+
101109
```bash
102110
rush update --full
103-
rush audit --level high
111+
rush audit
104112
```
105113

106-
Re-run the audit immediately after `rush update --full`. If High/Critical vulnerabilities are cleared, proceed to Step 4 (verify) — no further manual changes are needed.
114+
If still not cleared after `--full`, proceed to Step 3 for manual remediation.
107115

108116
3. If High/Critical remain after step 2, remediate using the fix strategy defined in the `cve-remediation` skill:
109117

@@ -117,7 +125,12 @@ rush audit --level high
117125

118126
```bash
119127
rush update
120-
rush audit --level high
128+
rush audit
129+
```
130+
131+
After audit confirms High/Critical are resolved, run build and test validation. If the invoker prefers to validate separately (e.g., in CI), commit after audit verification and note pending validation steps in the report.
132+
133+
```bash
121134
rush build
122135
rush test
123136
```
@@ -229,7 +242,7 @@ If not requested: stop after commit and final report (no push, no PR).
229242
## Done Criteria
230243

231244
- Critical/High vulnerabilities reduced or explicitly documented with rationale.
232-
- `rush audit --level high` rerun and reported.
245+
- `rush audit` rerun and reported.
233246
- `rush build` and `rush test` pass (or no new failures with clear disclosure).
234247
- `rush change` handled non-interactively (`--verify`; blank entry via `--bulk --message "" --bump-type none` only when required).
235248
- API impact checked with `rush extract-api` when relevant.

.github/agents/electron-version-bump.agent.md

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ grep -r '"electron":' --include='package.json' -l .
115115

116116
Compare the results with the list above and include any additional files found.
117117

118-
### Step 3: Review and apply breaking changes
118+
### Step 3: Review breaking changes and get approval
119+
120+
**This step requires explicit invoker approval before proceeding to file modifications.**
119121

120122
Fetch the Electron breaking changes documentation. Use the raw URL to avoid GitHub rate limiting:
121123

@@ -144,10 +146,7 @@ grep -r "require(\"electron\")" --include='*.ts' --include='*.js' -l .
144146
For each breaking change listed in the Electron docs for the new major version:
145147

146148
1. **Identify** whether the breaking change affects any API used in this codebase.
147-
2. **If affected**, apply the necessary code fix:
148-
- Search the codebase for all usages of the affected API.
149-
- Update the code to use the new API or pattern as prescribed by the Electron breaking changes doc.
150-
- Ensure backward compatibility with the minimum supported Electron version (currently ^35.0.0) — use feature detection or version checks when the old API is removed and a polyfill is needed.
149+
2. **If affected**, describe the required code fix and which files need modification.
151150
3. **If not affected**, note it and move on.
152151

153152
**Common breaking change categories to watch for:**
@@ -159,6 +158,24 @@ For each breaking change listed in the Electron docs for the new major version:
159158
- New required permissions or security policy changes
160159
- Deprecated APIs that are now removed
161160

161+
#### Present findings and wait for approval
162+
163+
After completing the analysis, present a summary table to the invoker:
164+
165+
| Breaking change | Affected? | Proposed fix |
166+
| --- | --- | --- |
167+
| (change description) | Yes / No | (fix description or "N/A") |
168+
169+
**STOP here and wait for the invoker's explicit go-ahead before making any file changes.** If the invoker requests modifications to the proposed approach, incorporate their feedback before proceeding.
170+
171+
#### Apply breaking change fixes (after approval)
172+
173+
Once approved, for each affected breaking change:
174+
175+
- Search the codebase for all usages of the affected API.
176+
- Update the code to use the new API or pattern as prescribed by the Electron breaking changes doc.
177+
- Ensure backward compatibility with the minimum supported Electron version documented in docs/learning/SupportedPlatforms.md — use feature detection or version checks when the old API is removed and a polyfill is needed.
178+
162179
If a breaking change requires a non-trivial migration (e.g., architectural changes), document the issue in the report. If triggered from a GitHub issue, add a comment to the issue describing the blocker and wait for guidance. Otherwise, ask the invoker before proceeding with the fix.
163180

164181
### Step 3.5: Update `@itwin/electron-authorization` if needed
@@ -290,10 +307,13 @@ gh pr create \
290307
--head electron-<NEW_MAJOR> \
291308
--title "Add support for Electron <NEW_MAJOR>" \
292309
--body "$(cat <<'EOF'
293-
Adds support for Electron <NEW_MAJOR>.
294-
295310
### Breaking changes review
296-
<Include the breaking changes assessment here — list each change with "affected" / "not affected" status>
311+
312+
<Include the breaking changes assessment table from Step 3 here>
313+
314+
### Notes
315+
316+
<Include any relevant notes, e.g. unmet peer dependencies>
297317
298318
See [Electron <NEW_MAJOR> release blog](https://www.electronjs.org/blog/electron-<NEW_MAJOR>-0) for details.
299319
EOF

.github/copilot-instructions.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ API changes require:
8888

8989
All published packages use **lockstep versioning** (`prerelease-monorepo-lockStep` policy). Versions are automatically synchronized across packages - do NOT manually edit internal dependency versions in `package.json`.
9090

91+
When generating a changelog non-interactively with `rush change`, always use bump type `"none"` in the generated change file. In this lockstep monorepo, version bumps are coordinated separately and changelog entries should not choose per-package bump types like `"patch"` or `"minor"`.
92+
9193
## Testing
9294

9395
### Mocha vs Vitest
@@ -183,6 +185,13 @@ Valid formats recognized by the ESLint rule:
183185

184186
**Critical**: Always run `rush extract-api` and `rush change` before pushing - CI will fail otherwise.
185187

188+
### Draft PR Descriptions
189+
190+
When creating or updating a draft PR, always include a `## Validation` section in the PR description. Summarize any targeted verification steps you performed beyond what CI checks cover, and note any known pre-existing failures or warnings:
191+
192+
- `Targeted verification:`
193+
- `Known baseline issues:`
194+
186195
## Build Tools
187196

188197
TypeScript compilation outputs dual format: CJS in `lib/cjs/`, ESM in `lib/esm/`.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"version": 1,
3+
"hooks": {
4+
"preToolUse": [
5+
{
6+
"type": "command",
7+
"bash": "node .github/hooks/scripts/itwinjs-core-pre-tool-use.mjs",
8+
"cwd": ".",
9+
"timeoutSec": 30
10+
}
11+
],
12+
"postToolUse": [
13+
{
14+
"type": "command",
15+
"bash": "node .github/hooks/scripts/itwinjs-core-post-tool-use.mjs",
16+
"cwd": ".",
17+
"timeoutSec": 10
18+
}
19+
]
20+
}
21+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
export async function readHookInput() {
2+
const chunks = [];
3+
for await (const chunk of process.stdin) {
4+
chunks.push(chunk);
5+
}
6+
7+
const input = Buffer.concat(chunks).toString("utf8").trim();
8+
if (!input) {
9+
return {};
10+
}
11+
12+
try {
13+
return JSON.parse(input);
14+
} catch {
15+
return {};
16+
}
17+
}
18+
19+
export function parseToolArgs(toolArgs) {
20+
if (!toolArgs) {
21+
return {};
22+
}
23+
24+
if (typeof toolArgs === "object") {
25+
return toolArgs;
26+
}
27+
28+
if (typeof toolArgs === "string") {
29+
try {
30+
return JSON.parse(toolArgs);
31+
} catch {
32+
return { raw: toolArgs };
33+
}
34+
}
35+
36+
return {};
37+
}
38+
39+
export function getBashCommand(input) {
40+
const args = parseToolArgs(input.toolArgs);
41+
return typeof args.command === "string" ? args.command : "";
42+
}
43+
44+
export function isGitCommitCommand(command) {
45+
return /\bgit\s+(?:-[^\s]+\s+)*commit\b/.test(command);
46+
}
47+
48+
export function getChangedPathText(input) {
49+
const args = parseToolArgs(input.toolArgs);
50+
const directPath = args.file_path ?? args.path ?? "";
51+
const summary = getPathSummary(args);
52+
53+
try {
54+
const summaryText = Object.keys(summary).length > 0 ? JSON.stringify(summary) : "";
55+
return summaryText ? `${directPath}\n${summaryText}` : `${directPath}\n`;
56+
} catch {
57+
return `${directPath}\n`;
58+
}
59+
}
60+
61+
export function getChangedPaths(input) {
62+
const args = parseToolArgs(input.toolArgs);
63+
const paths = [];
64+
for (const value of [args.file_path, args.path, args.old_path, args.new_path, args.paths, args.files]) {
65+
if (typeof value === "string" && value.length > 0) {
66+
paths.push(value);
67+
} else if (Array.isArray(value)) {
68+
paths.push(...value.filter((entry) => typeof entry === "string" && entry.length > 0));
69+
}
70+
}
71+
72+
return paths;
73+
}
74+
75+
export function isPackageJsonPath(path) {
76+
return String(path).split(/[\\/]/).pop() === "package.json";
77+
}
78+
79+
export function isWriteLikeTool(toolName) {
80+
return /^(edit|create|write|apply_patch)$/i.test(String(toolName ?? ""));
81+
}
82+
83+
export function compactJson(value) {
84+
return `${JSON.stringify(value)}\n`;
85+
}
86+
87+
function getPathSummary(args) {
88+
const summary = {};
89+
for (const key of ["file_path", "path", "old_path", "new_path", "paths", "files"]) {
90+
const value = args?.[key];
91+
if (typeof value === "string" && value.length > 0) {
92+
summary[key] = value;
93+
} else if (Array.isArray(value)) {
94+
const paths = value.filter((entry) => typeof entry === "string" && entry.length > 0);
95+
if (paths.length > 0) {
96+
summary[key] = paths;
97+
}
98+
}
99+
}
100+
101+
return summary;
102+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {
2+
getBashCommand,
3+
getChangedPaths,
4+
getChangedPathText,
5+
isGitCommitCommand,
6+
isPackageJsonPath,
7+
isWriteLikeTool,
8+
readHookInput,
9+
} from "./itwinjs-core-hook-utils.mjs";
10+
11+
const input = await readHookInput();
12+
const messages = [];
13+
const isWriteLike = isWriteLikeTool(input.toolName);
14+
15+
if (isWriteLike) {
16+
const changedPaths = getChangedPaths(input);
17+
18+
if (changedPaths.some(isPackageJsonPath)) {
19+
messages.push("[itwinjs] package.json changed - run rush update to sync pnpm-lock.yaml before committing.");
20+
}
21+
22+
if (changedPaths.some((path) => path.includes("tsconfig")) || /tsconfig/i.test(getChangedPathText(input))) {
23+
messages.push(
24+
"[itwinjs] tsconfig changed - clean and rebuild to avoid stale lib/ artifacts: from the affected package directory run rushx clean && rushx build, or from the repo root use rush clean && rush build.",
25+
);
26+
}
27+
}
28+
29+
if (String(input.toolName ?? "").toLowerCase() === "bash") {
30+
const command = getBashCommand(input);
31+
if (isGitCommitCommand(command)) {
32+
messages.push(
33+
"[itwinjs] Commit checklist: (1) any .ts files staged? -> rush lint from the repo root, or rushx lint from the affected package; (2) any @public/@beta symbol or TSDoc comment changed? -> rush extract-api + commit .api.md; (3) package.json dep changed? -> rush update committed; (4) changed a package with dependents? -> run downstream tests.",
34+
);
35+
}
36+
}
37+
38+
if (messages.length > 0) {
39+
process.stderr.write(`${messages.join("\n")}\n`);
40+
}

0 commit comments

Comments
 (0)