@a9n-shoji/rvw 0.4.0-beta.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 +18 -0
- package/dist/cli.mjs +80 -15
- package/dist/cli.mjs.map +4 -4
- package/dist/web/assets/DocumentViewer-CPq2FCqU.js +1414 -0
- package/dist/web/assets/StructureViewer-CyDDQwHl.js +1 -0
- package/dist/web/assets/{WalkthroughViewer-Ckb8Qlvj.js → WalkthroughViewer-c3XUP0RH.js} +1 -1
- package/dist/web/assets/index-CWOtOTHG.js +11 -0
- package/dist/web/assets/index-D_e3Zku8.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/skills/rvw-structure/SKILL.md +0 -2
- package/skills/rvw-structure/references/structure-authoring.md +11 -3
- package/dist/web/assets/DocumentViewer-CN8CiQe9.js +0 -1417
- package/dist/web/assets/StructureViewer-Ywjlwt8f.js +0 -1
- package/dist/web/assets/index-AVz95gz4.js +0 -11
- package/dist/web/assets/index-Dq83UXVE.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-09-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- 一つの具体的なbehavior / processing flowをsource-anchored origin、stable Node / Edge ID、exact source
|
|
13
|
+
anchorで提示し、1/2-hop / All、focus、pan / zoom / dragから探索できるproduction `Structure` document
|
|
14
|
+
- Structureのpublish / get / whole-value update / confirmation付きdeleteを行うCLI、Agent socket capability、
|
|
15
|
+
SQLite migration、HTTP API、Codex / Claude Code共通の`rvw-structure` Skill
|
|
16
|
+
- 変更表示の原文と行番号を保ちながら、追加・削除fileを除く空白だけの変更を`…`メニューから非表示にする
|
|
17
|
+
`Hide Whitespace`設定
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- 固定サイズのStructure Node内をscroll可能にし、表記ごとの余白、canvasのpan / zoom感度、source anchorの
|
|
22
|
+
fallback、stale判定、明示的な再解決を改善
|
|
23
|
+
- light / dark themeのdiff canvas、文字、追加・削除行、gutter、inline emphasisの配色をGitHubへ合わせる
|
|
24
|
+
- Hide Whitespace切替時に現在のsource lineをviewportへ保持し、空白差分がすべて隠れた場合は解除方法を表示
|
|
25
|
+
|
|
8
26
|
## [0.4.0-beta.0] - 2026-08-31
|
|
9
27
|
|
|
10
28
|
### Added
|
package/dist/cli.mjs
CHANGED
|
@@ -20187,7 +20187,7 @@ import path5 from "node:path";
|
|
|
20187
20187
|
import { TextDecoder as TextDecoder2 } from "node:util";
|
|
20188
20188
|
|
|
20189
20189
|
// src/shared/constants.ts
|
|
20190
|
-
var APP_VERSION = "0.4.0
|
|
20190
|
+
var APP_VERSION = "0.4.0";
|
|
20191
20191
|
var PROTOCOL_VERSION = 4;
|
|
20192
20192
|
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
20193
20193
|
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
@@ -28466,10 +28466,17 @@ function placeMutableDocumentComment(anchor, currentText) {
|
|
|
28466
28466
|
return range ? { outdated: false, range } : { outdated: true, range: null };
|
|
28467
28467
|
}
|
|
28468
28468
|
|
|
28469
|
-
// src/domain/
|
|
28470
|
-
function
|
|
28469
|
+
// src/domain/source-reference.ts
|
|
28470
|
+
function sourceAnchorFingerprint(sourceOid, reference) {
|
|
28471
28471
|
return JSON.stringify([sourceOid, reference.path, reference.startLine, reference.endLine]);
|
|
28472
28472
|
}
|
|
28473
|
+
function structureSourceAnchor(structure, locator) {
|
|
28474
|
+
if (locator.kind === "node") {
|
|
28475
|
+
return structure.nodes.find((node2) => node2.id === locator.nodeId)?.anchor ?? null;
|
|
28476
|
+
}
|
|
28477
|
+
const edge = structure.edges.find((candidate) => candidate.id === locator.edgeId);
|
|
28478
|
+
return edge?.anchors[locator.anchorIndex] ?? null;
|
|
28479
|
+
}
|
|
28473
28480
|
|
|
28474
28481
|
// src/domain/source-excerpt.ts
|
|
28475
28482
|
var SOURCE_EXCERPT_CONTEXT_LINES = 20;
|
|
@@ -42796,7 +42803,7 @@ var RvwService = class {
|
|
|
42796
42803
|
}
|
|
42797
42804
|
return walkthrough;
|
|
42798
42805
|
}
|
|
42799
|
-
async
|
|
42806
|
+
async sourceReferenceFallbackTarget(pullRequest, sourceOid, filePath) {
|
|
42800
42807
|
const diffBaseOid = await this.git.firstParent(pullRequest.localRepositoryPath, sourceOid);
|
|
42801
42808
|
if (!diffBaseOid) {
|
|
42802
42809
|
return {
|
|
@@ -42827,22 +42834,47 @@ var RvwService = class {
|
|
|
42827
42834
|
status: 404
|
|
42828
42835
|
});
|
|
42829
42836
|
}
|
|
42830
|
-
const referenceFingerprint =
|
|
42837
|
+
const referenceFingerprint = sourceAnchorFingerprint(walkthrough.sourceOid, reference);
|
|
42838
|
+
return await this.resolveSourceAnchor(
|
|
42839
|
+
pullRequest,
|
|
42840
|
+
walkthrough.sourceOid,
|
|
42841
|
+
reference,
|
|
42842
|
+
referenceFingerprint
|
|
42843
|
+
);
|
|
42844
|
+
}
|
|
42845
|
+
async resolveStructureSource(pullRequestId, structureId, locator) {
|
|
42846
|
+
const pullRequest = this.getPullRequest(pullRequestId);
|
|
42847
|
+
const structure = this.getStructure(pullRequestId, structureId);
|
|
42848
|
+
const anchor = structureSourceAnchor(structure, locator);
|
|
42849
|
+
if (!anchor) {
|
|
42850
|
+
throw new RvwError("NOT_FOUND", "Structure\u306E\u53C2\u7167\u5143claim\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002", {
|
|
42851
|
+
status: 404
|
|
42852
|
+
});
|
|
42853
|
+
}
|
|
42854
|
+
const resolution = await this.resolveSourceAnchor(
|
|
42855
|
+
pullRequest,
|
|
42856
|
+
structure.sourceOid,
|
|
42857
|
+
anchor,
|
|
42858
|
+
sourceAnchorFingerprint(structure.sourceOid, anchor)
|
|
42859
|
+
);
|
|
42860
|
+
return { ...resolution, resolvedAnchor: anchor };
|
|
42861
|
+
}
|
|
42862
|
+
async resolveSourceAnchor(pullRequest, sourceOid, reference, referenceFingerprint) {
|
|
42831
42863
|
const sourceDocument = await this.getDocument({
|
|
42832
42864
|
kind: "repository-file",
|
|
42833
|
-
pullRequestId,
|
|
42834
|
-
sourceOid
|
|
42865
|
+
pullRequestId: pullRequest.id,
|
|
42866
|
+
sourceOid,
|
|
42835
42867
|
path: reference.path
|
|
42836
42868
|
});
|
|
42837
42869
|
const latestHeadOid = pullRequest.latestHeadOid;
|
|
42838
42870
|
let latestPath = reference.path;
|
|
42839
42871
|
let latestDocument;
|
|
42840
|
-
if (
|
|
42872
|
+
if (sourceOid === latestHeadOid) {
|
|
42841
42873
|
latestDocument = sourceDocument;
|
|
42842
42874
|
} else {
|
|
42843
42875
|
latestDocument = await this.getDocument({
|
|
42844
42876
|
kind: "repository-file",
|
|
42845
|
-
pullRequestId,
|
|
42877
|
+
pullRequestId: pullRequest.id,
|
|
42846
42878
|
sourceOid: latestHeadOid,
|
|
42847
42879
|
path: reference.path
|
|
42848
42880
|
});
|
|
@@ -42851,7 +42883,7 @@ var RvwService = class {
|
|
|
42851
42883
|
...new Set(
|
|
42852
42884
|
(await this.git.changedFilesWithCopies(
|
|
42853
42885
|
pullRequest.localRepositoryPath,
|
|
42854
|
-
|
|
42886
|
+
sourceOid,
|
|
42855
42887
|
latestHeadOid
|
|
42856
42888
|
)).filter(
|
|
42857
42889
|
(candidate) => (candidate.status.startsWith("R") || candidate.status.startsWith("C")) && candidate.oldPath === reference.path && candidate.newPath !== null
|
|
@@ -42861,7 +42893,7 @@ var RvwService = class {
|
|
|
42861
42893
|
latestPath = successorPaths.length === 1 ? successorPaths[0] : null;
|
|
42862
42894
|
latestDocument = latestPath === null ? null : await this.getDocument({
|
|
42863
42895
|
kind: "repository-file",
|
|
42864
|
-
pullRequestId,
|
|
42896
|
+
pullRequestId: pullRequest.id,
|
|
42865
42897
|
sourceOid: latestHeadOid,
|
|
42866
42898
|
path: latestPath
|
|
42867
42899
|
});
|
|
@@ -42879,7 +42911,7 @@ var RvwService = class {
|
|
|
42879
42911
|
if (resolvedToLatest && latestPath !== null && latestDocument !== null) {
|
|
42880
42912
|
return {
|
|
42881
42913
|
outcome: "latest",
|
|
42882
|
-
anchorSourceOid:
|
|
42914
|
+
anchorSourceOid: sourceOid,
|
|
42883
42915
|
latestHeadOid,
|
|
42884
42916
|
referenceFingerprint,
|
|
42885
42917
|
target: {
|
|
@@ -42896,9 +42928,9 @@ var RvwService = class {
|
|
|
42896
42928
|
document: latestDocument
|
|
42897
42929
|
};
|
|
42898
42930
|
}
|
|
42899
|
-
const targetFile = await this.
|
|
42931
|
+
const targetFile = await this.sourceReferenceFallbackTarget(
|
|
42900
42932
|
pullRequest,
|
|
42901
|
-
|
|
42933
|
+
sourceOid,
|
|
42902
42934
|
reference.path
|
|
42903
42935
|
);
|
|
42904
42936
|
const latestFile = latestFileExists && latestPath !== null ? {
|
|
@@ -42911,7 +42943,7 @@ var RvwService = class {
|
|
|
42911
42943
|
} : null;
|
|
42912
42944
|
return {
|
|
42913
42945
|
outcome: "source-fallback",
|
|
42914
|
-
anchorSourceOid:
|
|
42946
|
+
anchorSourceOid: sourceOid,
|
|
42915
42947
|
latestHeadOid,
|
|
42916
42948
|
referenceFingerprint,
|
|
42917
42949
|
target: {
|
|
@@ -47567,6 +47599,7 @@ var editCommentPostSchema = external_exports.object({
|
|
|
47567
47599
|
|
|
47568
47600
|
// src/server/app.ts
|
|
47569
47601
|
var oidSchema = external_exports.string().regex(GIT_OBJECT_ID_PATTERN);
|
|
47602
|
+
var nonnegativeIndexSchema = external_exports.coerce.number().int().nonnegative();
|
|
47570
47603
|
var svgAssetContentSecurityPolicy = "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; sandbox";
|
|
47571
47604
|
function requiredQuery(value, name) {
|
|
47572
47605
|
if (!value) throw new RvwError("INVALID_INPUT", `${name} query\u304C\u5FC5\u8981\u3067\u3059\u3002`);
|
|
@@ -47575,6 +47608,23 @@ function requiredQuery(value, name) {
|
|
|
47575
47608
|
function oidQuery(value, name) {
|
|
47576
47609
|
return oidSchema.parse(requiredQuery(value, name));
|
|
47577
47610
|
}
|
|
47611
|
+
function structureSourceLocator(query) {
|
|
47612
|
+
if (query.locatorKind === "node") {
|
|
47613
|
+
return { kind: "node", nodeId: requiredQuery(query.nodeId, "nodeId") };
|
|
47614
|
+
}
|
|
47615
|
+
if (query.locatorKind === "edge") {
|
|
47616
|
+
const anchorIndex = nonnegativeIndexSchema.safeParse(query.anchorIndex);
|
|
47617
|
+
if (!anchorIndex.success) {
|
|
47618
|
+
throw new RvwError("INVALID_INPUT", "anchorIndex query\u306F0\u4EE5\u4E0A\u306E\u6574\u6570\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
47619
|
+
}
|
|
47620
|
+
return {
|
|
47621
|
+
kind: "edge",
|
|
47622
|
+
edgeId: requiredQuery(query.edgeId, "edgeId"),
|
|
47623
|
+
anchorIndex: anchorIndex.data
|
|
47624
|
+
};
|
|
47625
|
+
}
|
|
47626
|
+
throw new RvwError("INVALID_INPUT", "locatorKind query\u306Fnode\u307E\u305F\u306Fedge\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
47627
|
+
}
|
|
47578
47628
|
function isWriteMethod(method) {
|
|
47579
47629
|
return method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";
|
|
47580
47630
|
}
|
|
@@ -47873,6 +47923,21 @@ function createApp(service, options) {
|
|
|
47873
47923
|
structure: service.getStructure(context.req.param("id"), context.req.param("structureId"))
|
|
47874
47924
|
})
|
|
47875
47925
|
);
|
|
47926
|
+
app.get("/api/pull-requests/:id/structures/:structureId/anchors/resolve", async (context) => {
|
|
47927
|
+
return context.json({
|
|
47928
|
+
ok: true,
|
|
47929
|
+
resolution: await service.resolveStructureSource(
|
|
47930
|
+
context.req.param("id"),
|
|
47931
|
+
context.req.param("structureId"),
|
|
47932
|
+
structureSourceLocator({
|
|
47933
|
+
locatorKind: context.req.query("locatorKind"),
|
|
47934
|
+
nodeId: context.req.query("nodeId"),
|
|
47935
|
+
edgeId: context.req.query("edgeId"),
|
|
47936
|
+
anchorIndex: context.req.query("anchorIndex")
|
|
47937
|
+
})
|
|
47938
|
+
)
|
|
47939
|
+
});
|
|
47940
|
+
});
|
|
47876
47941
|
app.delete("/api/pull-requests/:id/structures/:structureId", async (context) => {
|
|
47877
47942
|
const input = structureDeleteSchema.parse(await context.req.json());
|
|
47878
47943
|
return context.json({
|