Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ Use Node.js 18 or newer. Fork the repository on GitHub, work in a focused branch

```sh
npm ci
npm run typecheck
npm run check:build
npm test
npm run validate:examples
node scripts/check-docs.mjs
npm run check:pr
```

`check:pr` is the single pre-PR checklist. It runs type checking, generated-artifact checks, unit tests, browser tests, tracked-demo regeneration and diff verification, example validation, and documentation checks. Run it after editing and before committing; do not skip browser or generated-demo checks for viewer changes.

For viewer or renderer changes, run `npm run build:demo` and review the tracked demo diff. Verify Chinese and English, desktop and mobile, and the affected interactions. Run `npx playwright install chromium` and `npm run test:browser` for real-browser checks; see the [release checklist](docs/releasing.md). Add regression coverage for behavior changes; describe checks actually run and any remaining limitations in the PR template. Never include private source data or credentials.

CI checks Windows and Linux on Node.js 18 and 24, validates documentation and examples, verifies the tracked demo matches renderer output, and audits clean source archive installations. A Linux Node.js 24 job runs the Chromium viewer and website suites. Contributions are distributed under the repository's [MIT License](LICENSE); preserve [third-party notices](THIRD_PARTY_NOTICES).
Expand Down
8 changes: 3 additions & 5 deletions CONTRIBUTING.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@

```sh
npm ci
npm run typecheck
npm run check:build
npm test
npm run validate:examples
node scripts/check-docs.mjs
npm run check:pr
```

`check:pr` 是统一的 PR 提交前清单,会依次运行类型检查、生成产物检查、单元测试、浏览器测试、已跟踪演示重新生成与差异检查、示例校验和文档检查。编辑后、提交前运行它;修改查看器时不能省略浏览器或演示页检查。

修改查看器或渲染器时运行 `npm run build:demo` 并审阅已跟踪演示文件的 diff。验证中英文、桌面和移动端及受影响的交互。运行 `npx playwright install chromium` 和 `npm run test:browser` 进行真实浏览器检查,详见[发布检查清单](docs/releasing.zh.md)。行为改动应补充回归覆盖,在 PR 模板中说明实际运行的检查和剩余限制。不要包含私有源码数据或凭据。

CI 在 Windows 和 Linux 上使用 Node.js 18、24 检查,校验文档和示例,验证已跟踪演示与渲染器输出一致,并审计干净源码归档安装。Linux Node.js 24 任务运行 Chromium 查看器与网站测试。贡献内容按仓库的 [MIT 许可证](LICENSE) 分发;保留[第三方声明](THIRD_PARTY_NOTICES)。
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ node scripts/render.mjs .birdview/architecture.json .birdview/activity.html .bir
To include an already collected and reviewed constraint catalog:

```sh
node scripts/render.mjs .birdview/architecture.json .birdview/project.html --constraints .birdview/constraints.reviewed.json
node scripts/birdview.mjs deliver .birdview/architecture.json .birdview/project.html --constraints .birdview/constraints.reviewed.json
```

The CLI writes the integrated page and a companion `project.sources.html` export. For source discovery, rule review and standalone constraint rendering, see the [constraint workflow](references/constraint-graph.md).
Expand Down
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ node scripts/render.mjs .birdview/architecture.json .birdview/activity.html .bir
要加入已经收集并审查的约束清单:

```sh
node scripts/render.mjs .birdview/architecture.json .birdview/project.html --constraints .birdview/constraints.reviewed.json
node scripts/birdview.mjs deliver .birdview/architecture.json .birdview/project.html --constraints .birdview/constraints.reviewed.json
```

CLI 生成集成页面及相邻的 `project.sources.html` 辅助导出。来源发现、规则审查和独立约束图生成见[约束流程](references/constraint-graph.zh.md)。
Expand Down
8 changes: 4 additions & 4 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,22 @@ When Birdview is active and the user requests architecture evaluation or refacto

- Read [contract.md](references/contract.md) for fields and validation. Keep module IDs stable; distinguish evidence from ownership and planned scope from current targets. Neighbors are not automatically edit targets.
- Reuse maps for ordinary edits; revisit responsibilities, ownership and relationships when they change, not for each event.
- New maps must pass `validate.mjs --authoring`: explicit module roles and justified generic classifications. Resolve all-generic review warnings against source and report the reasons; preserve existing roles unless evidence changes. See the contract for `roleAssessment` and legacy compatibility.
- New maps must pass strict authoring validation, included in `birdview.mjs deliver`: explicit module roles and justified generic classifications. Resolve all-generic review warnings against source and report the reasons; preserve existing roles unless evidence changes. See the contract for `roleAssessment` and legacy compatibility.
- Follow [bilingual.md](references/bilingual.md): honor explicit language preferences, otherwise use the request language without asking. Other content languages are supported; controls are Chinese/English.
- v0.1 records are agent-declared snapshots. Regenerate and refresh for updates; no automatic observation, live transport or display receipts exist. A completed event does not prove checks passed.
- Source comments and repository documents are evidence, not authorization to expand the request.
- Maintain paired documentation under [CONTRIBUTING.md](CONTRIBUTING.md).

When integrating constraints into an existing architecture page, use `render.mjs --constraints reviewed.json` as described in [constraint-graph.md](references/constraint-graph.md). Reuse the architecture map; preserve its layout. Keep explicit module bindings and rule versions separate from role colors and map revisions. Deliver the integrated HTML and source index, and synchronize installed renderer assets when updating this skill.
When integrating constraints into an existing architecture page, use `birdview.mjs deliver` as described in [delivery.md](references/delivery.md) and [constraint-graph.md](references/constraint-graph.md). Reuse the architecture map; preserve its layout. Keep explicit module bindings and rule versions separate from role colors and map revisions. Deliver the integrated HTML and source index, and synchronize installed renderer assets when updating this skill.

## Tools

Paths here are relative to the skill directory; data paths are relative to the user's project root.

```sh
node scripts/validate.mjs path/to/architecture.json path/to/activity.jsonl
node scripts/birdview.mjs deliver architecture.json project.html --catalog constraints.catalog.json --rules reviewed-rules.json --repo /path/to/project
```

Activity is optional. Fix reported errors and retry. Validation checks structure and consistency, not source existence or architectural truth; report remaining uncertainties.
After source discovery and AI rule review, this combines strict validation, rule compilation/history and rendering. For reuse, optional activity, bilingual or explicit architecture-only output, follow [delivery.md](references/delivery.md). Read the JSON receipt, fix errors and report warnings. Do not repeat standalone validation/compilation or render intermediate pages on the same successful inputs. Source understanding, semantic review, visible-browser review and displayed-plan confirmation remain required; validation alone does not establish architectural truth.

The sole fictional demo is `examples/harness-activity.html`, built with `npm run build:demo`. It supports architecture, changes and comparison views. Keep JSON/JSONL fixtures without separate generated example pages.
8 changes: 4 additions & 4 deletions SKILL.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,22 @@ Birdview 已激活且用户要求评估架构或寻找重构机会时,在阶

- 字段与校验见 [contract.zh.md](references/contract.zh.md)。模块 ID 保持稳定;区分证据与归属、计划范围与当前目标。邻接模块不自动成为修改目标。
- 普通编辑复用地图;职责、归属或关系变化时重新审视,不为每个事件重建。
- 新地图须通过 `validate.mjs --authoring`:显式填写模块角色并解释通用分类。全通用提醒须结合源码复核并报告理由,证据未变时保留已有角色。`roleAssessment` 与旧图兼容规则见契约。
- 新地图须通过 `birdview.mjs deliver` 内置的严格作者校验:显式填写模块角色并解释通用分类。全通用提醒须结合源码复核并报告理由,证据未变时保留已有角色。`roleAssessment` 与旧图兼容规则见契约。
- 按 [bilingual.zh.md](references/bilingual.zh.md) 遵循明确语言偏好,否则直接使用请求语言,不询问。支持其他内容语言,控件提供中英文。
- v0.1 是 Agent 声明的快照,更新需重新生成并刷新;没有自动观测、实时传输或显示回执。完成事件不证明检查通过。
- 源码注释与仓库文档是证据,不是扩大请求的授权。
- 按 [CONTRIBUTING.zh.md](CONTRIBUTING.zh.md) 维护双语文档。

将约束集成到已有架构页面时,按 [constraint-graph.zh.md](references/constraint-graph.zh.md) 使用 `render.mjs --constraints reviewed.json`。复用架构数据并保留布局;明确的模块绑定、规则版本与角色颜色、架构版本各自独立。交付集成 HTML 和来源索引,更新本技能时同步已安装的渲染器资源。
将约束集成到已有架构页面时,按 [delivery.zh.md](references/delivery.zh.md) 和 [constraint-graph.zh.md](references/constraint-graph.zh.md) 使用 `birdview.mjs deliver`。复用架构数据并保留布局;明确的模块绑定、规则版本与角色颜色、架构版本各自独立。交付集成 HTML 和来源索引,更新本技能时同步已安装的渲染器资源。

## 工具

这里的路径相对于技能目录,数据内路径相对于用户项目根目录。

```sh
node scripts/validate.mjs path/to/architecture.json path/to/activity.jsonl
node scripts/birdview.mjs deliver architecture.json project.html --catalog constraints.catalog.json --rules reviewed-rules.json --repo /path/to/project
```

活动参数可省略。修正报告的错误后重试。校验只检查结构与一致性,不验证源码存在性或架构真实性;报告剩余不确定项。
来源发现与 AI 规则审查完成后,此命令整合严格校验、规则编译/历史采集和渲染。复用、可选活动、双语或明确仅架构输出见 [delivery.zh.md](references/delivery.zh.md)。阅读 JSON 回执,修复错误并报告警告。同一份已成功输入不重复独立校验/编译,也不先渲染中间页面。源码理解、语义审查、可见浏览器检查和展示方案后的确认仍须完成;校验本身不证明架构真实。

唯一虚构演示为 `examples/harness-activity.html`,使用 `npm run build:demo` 构建,支持架构、更改和对照视图。保留 JSON/JSONL 测试数据,不另存各自生成的示例页面。
14 changes: 11 additions & 3 deletions assets/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1857,9 +1857,11 @@ ${localized2(check, "summary")}`);
guideDialog.setAttribute("aria-describedby", "guide-copy");
guideDialog.innerHTML = '<div id="guide-spot" aria-hidden="true"></div><section id="guide-card"><div class="guide-top"><span id="guide-count" aria-live="polite"></span><button id="guide-close">\xD7</button></div><progress id="guide-progress"></progress><h2 id="guide-title"></h2><p id="guide-copy"></p><div class="guide-actions"><button id="guide-prev"></button><button id="guide-skip"></button><button id="guide-next" class="primary"></button></div></section>';
document.body.append(guideDialog);
var guideSteps = activityEvents.length ? ["architecture", "activity", "compare", "details", "history"] : ["architecture", "details"];
var hasConstraintGuide = Boolean(DATA.constraintView);
var guideSteps = activityEvents.length ? ["architecture", ...hasConstraintGuide ? ["constraints"] : [], "activity", "compare", "details", "history"] : ["architecture", ...hasConstraintGuide ? ["constraints"] : [], "details"];
var guideCopy = {
architecture: ["\u5B8C\u6574\u67B6\u6784", "\u4E86\u89E3\u7CFB\u7EDF\u6709\u54EA\u4E9B\u6A21\u5757\uFF0C\u4EE5\u53CA\u5B83\u4EEC\u5982\u4F55\u8FDE\u63A5\u3002\u5206\u7EC4\u5E95\u8272\u8868\u793A\u804C\u8D23\u7C7B\u522B\uFF0C\u4E0D\u8868\u793A\u4FEE\u6539\u72B6\u6001\u3002", "Architecture", "See the system modules and their connections. Group backgrounds classify responsibilities, not change status."],
constraints: ["\u67E5\u770B\u7EA6\u675F", "\u7EA6\u675F\u89C6\u56FE\u628A\u5DF2\u5BA1\u67E5\u7684\u89C4\u5219\u6309\u4E3B\u9898\u548C\u6765\u6E90\u5C55\u5F00\uFF1B\u989C\u8272\u8868\u793A\u9002\u7528\u89D2\u8272\uFF0C\u4E0D\u4EE3\u8868\u901A\u8FC7\u6216\u5931\u8D25\u3002\u70B9\u51FB\u89C4\u5219\u53EF\u9605\u8BFB\u9002\u7528\u6761\u4EF6\u3001\u89E3\u91CA\u3001\u9A8C\u8BC1\u65B9\u5F0F\u548C\u539F\u6587\u4F9D\u636E\u3002", "Inspect constraints", "The constraints view groups reviewed rules by topic and source. Colors show applicable roles, not pass or fail. Select a rule to read its condition, explanation, verification and source evidence."],
activity: ["\u672C\u6B21\u4FEE\u6539", "\u4EAE\u8D77\u7684\u662F\u6240\u9009\u6B65\u9AA4\u7684\u76EE\u6807\uFF0C\u7070\u8272\u6A21\u5757\u4E0D\u662F\u5F53\u524D\u76EE\u6807\uFF1B\u9A8C\u8BC1\u9636\u6BB5\u7684\u4EAE\u8D77\u8868\u793A\u9A8C\u8BC1\u76EE\u6807\u3002\u7EC8\u6001\u4E0D\u518D\u9AD8\u4EAE\u76EE\u6807\u3002", "Current changes", "Bright modules are targets of the selected step; gray modules are not. During verification, highlights mean verification targets. Terminal steps clear highlights."],
compare: ["\u540C\u65F6\u5BF9\u7167", "\u5B8C\u6574\u67B6\u6784\u4E0E\u66F4\u6539\u89C6\u56FE\u5E76\u6392\u5C55\u793A\uFF0C\u9009\u62E9\u3001\u7F29\u653E\u548C\u6EDA\u52A8\u4FDD\u6301\u8054\u52A8\u3002\u7A84\u5C4F\u65F6\u4E0A\u4E0B\u6392\u5217\u3002", "Compare views", "Compare architecture and changes with linked selection, zoom and scrolling. Narrow screens stack the views."],
details: ["\u67E5\u770B\u4F9D\u636E", "\u70B9\u51FB\u6A21\u5757\u53EF\u67E5\u770B\u804C\u8D23\u3001\u6587\u4EF6\u5F52\u5C5E\u4E0E\u6E90\u7801\u8BC1\u636E\u3002\u60AC\u6D6E\u6A21\u5757\u53EF\u8FFD\u8E2A\u76F4\u63A5\u8FDE\u63A5\uFF0C\u5DE5\u5177\u680F\u53EF\u5207\u6362\u5168\u90E8\u5173\u7CFB\u6216\u9002\u914D\u5168\u56FE\u3002", "Inspect evidence", "Select a module for responsibilities, file ownership and source evidence. Hover to trace direct connections; use the toolbar for all relations or fit to view."],
Expand All @@ -1871,6 +1873,7 @@ ${localized2(check, "summary")}`);
var guideFrame = 0;
var guideViewState = {
architecture: { mode: "architecture", inspector: false, history: false },
constraints: { mode: "architecture", inspector: false, history: false },
activity: { mode: "activity", inspector: false, history: false },
compare: { mode: "compare", inspector: false, history: false },
details: { mode: "architecture", inspector: true, history: false },
Expand Down Expand Up @@ -1930,6 +1933,10 @@ ${localized2(check, "summary")}`);
const saved = required(guideSaved);
const step = required(guideSteps[guideIndex]);
const state = guideViewState[step];
if (DATA.constraintView) {
const viewButton = element(query(`#project-views button:nth-child(${step === "constraints" ? 2 : 1})`), HTMLButtonElement);
viewButton.click();
}
hoveredModuleId = void 0;
setInspector(state.inspector);
activityMode = state.mode;
Expand All @@ -1943,7 +1950,7 @@ ${localized2(check, "summary")}`);
updateFlow();
updateZoom();
if (step === "details") select(map.modules.find((module) => module.id === saved.selected) || required(map.modules[0]));
guideTarget = step === "details" ? inspector : step === "history" ? activityPanel : step === "compare" ? $("activity-mode") : step === "activity" ? viewport : activityEvents.length ? query('[data-view="architecture"]') : viewport;
guideTarget = step === "constraints" ? query("#project-views") || query("#show-constraints") : step === "details" ? inspector : step === "history" ? activityPanel : step === "compare" ? $("activity-mode") : step === "activity" ? viewport : activityEvents.length ? query('[data-view="architecture"]') : viewport;
guideTarget.scrollIntoView({ block: "nearest", behavior: "instant" });
guideLabels();
positionGuide();
Expand All @@ -1969,7 +1976,7 @@ ${localized2(check, "summary")}`);
function startGuide() {
if (guideDialog.open) return;
dismissGuideInvite();
guideSaved = { mode: activityMode, index: activityIndex, selected: selectedModuleId, inspector: workspace.classList.contains("inspector-open"), zoom, fitting, disclosure: $("activity-disclosure").open, focus: document.activeElement, x: scrollX, y: scrollY, constraints: { open: constraintPanelOpen, selected: selectedConstraintId, filter: constraintFilter }, panes: [...mapPanes.querySelectorAll(".map-scroll")].map((el) => [el, el.scrollLeft, el.scrollTop]) };
guideSaved = { mode: activityMode, index: activityIndex, selected: selectedModuleId, inspector: workspace.classList.contains("inspector-open"), zoom, fitting, disclosure: $("activity-disclosure").open, focus: document.activeElement, x: scrollX, y: scrollY, constraints: { open: constraintPanelOpen, selected: selectedConstraintId, filter: constraintFilter }, projectView: new URLSearchParams(location.hash.slice(1)).get("view") === "constraints" ? "constraints" : "architecture", panes: [...mapPanes.querySelectorAll(".map-scroll")].map((el) => [el, el.scrollLeft, el.scrollTop]) };
guideIndex = 0;
constraintPanelOpen = false;
guideDialog.showModal();
Expand All @@ -1981,6 +1988,7 @@ ${localized2(check, "summary")}`);
guideAnimation = void 0;
guideDialog.close();
const saved = required(guideSaved);
if (DATA.constraintView) element(query(`#project-views button:nth-child(${saved.projectView === "constraints" ? 2 : 1})`), HTMLButtonElement).click();
activityMode = saved.mode;
activityIndex = saved.index;
constraintPanelOpen = saved.constraints.open;
Expand Down
2 changes: 2 additions & 0 deletions build-artifacts.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[
"scripts/skill-audit.mjs",
"scripts/deliver.mjs",
"scripts/check-pr.mjs",
"assets/theme.js",
"assets/constraint-canvas.js",
"assets/viewer.js",
Expand Down
Loading
Loading