@cyber-dash-tech/revela 0.17.6 → 0.17.8
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/README.md +53 -23
- package/README.zh-CN.md +53 -23
- package/bin/revela.ts +98 -0
- package/lib/edit/prompt.ts +6 -2
- package/lib/edit/server.ts +2 -2
- package/lib/inspect/prompt.ts +5 -1
- package/lib/refine/comment-requests.ts +77 -0
- package/lib/refine/open.ts +5 -2
- package/lib/refine/prompt-bridge.ts +219 -0
- package/lib/refine/qa-suppression.ts +41 -0
- package/lib/refine/server.ts +122 -34
- package/lib/runtime/index.ts +225 -0
- package/lib/runtime/research.ts +175 -0
- package/lib/runtime/review.ts +270 -0
- package/lib/runtime/story.ts +53 -0
- package/package.json +6 -1
- package/plugin.ts +4 -2
- package/plugins/revela/.codex-plugin/plugin.json +37 -0
- package/plugins/revela/.mcp.json +11 -0
- package/plugins/revela/assets/README.md +2 -0
- package/plugins/revela/hooks/hooks.json +28 -0
- package/plugins/revela/hooks/revela_guard.ts +10 -0
- package/plugins/revela/hooks/revela_post_write_notice.ts +18 -0
- package/plugins/revela/mcp/revela-server.ts +504 -0
- package/plugins/revela/mcp/runtime-resolver.ts +109 -0
- package/plugins/revela/skills/revela-design/SKILL.md +20 -0
- package/plugins/revela/skills/revela-domain/SKILL.md +18 -0
- package/plugins/revela/skills/revela-export/SKILL.md +21 -0
- package/plugins/revela/skills/revela-init/SKILL.md +36 -0
- package/plugins/revela/skills/revela-make-deck/SKILL.md +37 -0
- package/plugins/revela/skills/revela-research/SKILL.md +38 -0
- package/plugins/revela/skills/revela-review-deck/SKILL.md +33 -0
- package/plugins/revela/skills/revela-story/SKILL.md +24 -0
- package/tools/decks.ts +10 -78
- package/tools/research-save.ts +8 -72
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { resolve } from "path"
|
|
2
|
+
import { loadStoryMap } from "../commands/narrative"
|
|
3
|
+
import { formatNarrativeMap, type NarrativeMap } from "../narrative-state/map"
|
|
4
|
+
import type { formatVaultDiagnosticReport } from "../narrative-vault"
|
|
5
|
+
|
|
6
|
+
export interface StoryReadInput {
|
|
7
|
+
workspaceRoot?: string
|
|
8
|
+
format?: "map" | "markdown"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type StoryReadResult =
|
|
12
|
+
| {
|
|
13
|
+
ok: true
|
|
14
|
+
narrativeHash: string
|
|
15
|
+
map: NarrativeMap
|
|
16
|
+
markdown?: string
|
|
17
|
+
diagnostics: ReturnType<typeof formatVaultDiagnosticReport>
|
|
18
|
+
diagnosticsMarkdown: string
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
ok: false
|
|
22
|
+
error: string
|
|
23
|
+
guidance: string
|
|
24
|
+
diagnostics?: ReturnType<typeof formatVaultDiagnosticReport>
|
|
25
|
+
diagnosticsMarkdown: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function storyRead(input: StoryReadInput = {}): StoryReadResult {
|
|
29
|
+
const loaded = loadStoryMap(root(input.workspaceRoot))
|
|
30
|
+
if (!loaded.ok) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
error: loaded.error,
|
|
34
|
+
guidance: "Run `/revela init` first to initialize `revela-narrative/`, then retry Story reading.",
|
|
35
|
+
diagnostics: loaded.diagnosticsReport,
|
|
36
|
+
diagnosticsMarkdown: loaded.diagnosticsMarkdown,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const map = loaded.map
|
|
41
|
+
return {
|
|
42
|
+
ok: true,
|
|
43
|
+
narrativeHash: map.snapshot.narrativeHash,
|
|
44
|
+
map,
|
|
45
|
+
markdown: input.format === "markdown" ? formatNarrativeMap(map) : undefined,
|
|
46
|
+
diagnostics: loaded.diagnosticsReport,
|
|
47
|
+
diagnosticsMarkdown: loaded.diagnosticsMarkdown,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function root(workspaceRoot: string | undefined): string {
|
|
52
|
+
return resolve(workspaceRoot || process.cwd())
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyber-dash-tech/revela",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.8",
|
|
4
4
|
"description": "OpenCode plugin for trusted narrative artifacts from local sources, research, and evidence",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"revela": "./bin/revela.ts"
|
|
9
|
+
},
|
|
7
10
|
"exports": {
|
|
8
11
|
".": "./index.ts"
|
|
9
12
|
},
|
|
10
13
|
"files": [
|
|
14
|
+
"bin/",
|
|
11
15
|
"plugin.ts",
|
|
12
16
|
"lib/",
|
|
17
|
+
"plugins/revela/",
|
|
13
18
|
"tools/",
|
|
14
19
|
"skill/",
|
|
15
20
|
"designs/aurora/DESIGN.md",
|
package/plugin.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 5. experimental.chat.system.transform: inject three-layer prompt when enabled
|
|
12
12
|
* 6. chat.message: intercept @-referenced / pasted binary files → extract text → replace FilePart with TextPart
|
|
13
13
|
* 7. tool.execute.before: intercept read on DOCX/PPTX/XLSX → preRead()
|
|
14
|
-
* 8. tool.execute.after: intercept read on PDF/images → postRead(); run static compliance after deck writes/patches/edits
|
|
14
|
+
* 8. tool.execute.after: intercept read on PDF/images → postRead(); run static compliance after deck writes/patches/edits unless Review Apply Fix suppresses it
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import type { Plugin } from "@opencode-ai/plugin"
|
|
@@ -47,6 +47,7 @@ import { buildPptxNotesPrompt, handlePptx, parsePptxArgs, resolvePptxDeck } from
|
|
|
47
47
|
import { handleRefine } from "./lib/commands/refine"
|
|
48
48
|
import { formatArtifactQAReport, runArtifactQA } from "./lib/qa/artifact"
|
|
49
49
|
import { ensureRefineDeckOpenForChange } from "./lib/refine/open"
|
|
50
|
+
import { shouldSuppressReviewApplyFixArtifactQa } from "./lib/refine/qa-suppression"
|
|
50
51
|
import { handleDesignsPreview } from "./lib/commands/designs-preview"
|
|
51
52
|
import {
|
|
52
53
|
parseDesignsNewArgs,
|
|
@@ -148,6 +149,7 @@ const server: Plugin = (async (pluginCtx) => {
|
|
|
148
149
|
|
|
149
150
|
async function runPostWriteArtifactQA(filePath: string, output: any, sessionID = ""): Promise<boolean> {
|
|
150
151
|
if (!isDeckHtmlPath(filePath)) return true
|
|
152
|
+
if (shouldSuppressReviewApplyFixArtifactQa({ workspaceRoot, file: filePath, sessionID })) return false
|
|
151
153
|
|
|
152
154
|
try {
|
|
153
155
|
let vocabulary
|
|
@@ -787,7 +789,7 @@ Next step: use \`revela-decks\` with action \`init\`, \`upsertDeck\`, \`upsertSl
|
|
|
787
789
|
// PDF: extract text, remove base64. Images: jimp compress.
|
|
788
790
|
//
|
|
789
791
|
// Also reports writes/patches blocked by the DECKS.json state gate and
|
|
790
|
-
// runs artifact QA before opening Refine after successful deck changes.
|
|
792
|
+
// runs artifact QA before opening Refine after successful deck changes, except Review Apply Fix comments.
|
|
791
793
|
"tool.execute.after": async (input, output) => {
|
|
792
794
|
// ── Post-read processing ───────────────────────────────────────────
|
|
793
795
|
if (input.tool === "read") {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "revela",
|
|
3
|
+
"version": "0.1.0+codex.20260523122203",
|
|
4
|
+
"description": "Use Revela in Codex to build trusted, traceable narrative decision artifacts from local sources and research.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "cyber-dash-tech",
|
|
7
|
+
"url": "https://github.com/cyber-dash-tech"
|
|
8
|
+
},
|
|
9
|
+
"repository": "https://github.com/cyber-dash-tech/revela",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"narrative",
|
|
13
|
+
"presentations",
|
|
14
|
+
"research",
|
|
15
|
+
"evidence",
|
|
16
|
+
"codex"
|
|
17
|
+
],
|
|
18
|
+
"skills": "./skills/",
|
|
19
|
+
"mcpServers": "./.mcp.json",
|
|
20
|
+
"interface": {
|
|
21
|
+
"displayName": "Revela",
|
|
22
|
+
"shortDescription": "Trusted narrative artifacts from local sources and research.",
|
|
23
|
+
"longDescription": "Revela helps Codex initialize a narrative vault, bind evidence, plan decks, generate artifact foundations, run QA, and export decision artifacts while preserving source traceability.",
|
|
24
|
+
"developerName": "cyber-dash-tech",
|
|
25
|
+
"category": "Productivity",
|
|
26
|
+
"capabilities": [
|
|
27
|
+
"Read",
|
|
28
|
+
"Write"
|
|
29
|
+
],
|
|
30
|
+
"defaultPrompt": [
|
|
31
|
+
"Use Revela to initialize this workspace.",
|
|
32
|
+
"Use Revela to make a deck from the narrative.",
|
|
33
|
+
"Use Revela to review this deck artifact."
|
|
34
|
+
],
|
|
35
|
+
"brandColor": "#2563EB"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"revela": {
|
|
4
|
+
"command": "bun",
|
|
5
|
+
"args": [
|
|
6
|
+
"--eval",
|
|
7
|
+
"const fs = await import('fs');\nconst path = await import('path');\nconst { pathToFileURL } = await import('url');\nconst candidates = [];\nconst home = process.env.HOME || '';\nconst marketplaceNames = ['revela', 'revela-local'];\ncandidates.push(path.resolve(process.cwd(), 'bin/revela.ts'));\nconst configPath = path.join(home, '.codex', 'config.toml');\nif (fs.existsSync(configPath)) {\n const text = fs.readFileSync(configPath, 'utf-8');\n const sections = text.split(/\\n(?=\\s*\\[)/);\n for (const marketplaceName of marketplaceNames) {\n const section = sections.find((item) => item.trimStart().startsWith(`[marketplaces.${marketplaceName}]`));\n const match = section?.match(/^\\s*source\\s*=\\s*\"([^\"]+)\"/m);\n if (match) candidates.push(path.join(match[1], 'bin/revela.ts'));\n }\n}\nfor (const marketplaceName of marketplaceNames) {\n const cacheRoot = path.join(home, '.codex', 'plugins', 'cache', marketplaceName, 'revela');\n if (fs.existsSync(cacheRoot)) {\n for (const version of fs.readdirSync(cacheRoot).sort().reverse()) candidates.push(path.join(cacheRoot, version, 'bin/revela.ts'));\n }\n}\nconst cli = candidates.find((candidate) => fs.existsSync(candidate));\nif (!cli) {\n console.error(`Could not locate Revela CLI. Checked: ${candidates.join(', ')}`);\n process.exit(1);\n}\nprocess.env.REVELA_CLI_COMMAND = 'mcp';\nawait import(pathToFileURL(cli).href);"
|
|
8
|
+
]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "apply_patch",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "bun ${PLUGIN_ROOT}/hooks/revela_guard.ts",
|
|
10
|
+
"statusMessage": "Checking Revela controlled files"
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"PostToolUse": [
|
|
16
|
+
{
|
|
17
|
+
"matcher": "apply_patch",
|
|
18
|
+
"hooks": [
|
|
19
|
+
{
|
|
20
|
+
"type": "command",
|
|
21
|
+
"command": "bun ${PLUGIN_ROOT}/hooks/revela_post_write_notice.ts",
|
|
22
|
+
"statusMessage": "Checking Revela QA reminders"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const input = await new Response(Bun.stdin.stream()).text()
|
|
2
|
+
|
|
3
|
+
if (input.includes("DECKS.json")) {
|
|
4
|
+
console.error("Revela controls DECKS.json. Use Revela MCP/runtime tools or file-native narrative files instead of direct DECKS.json patches.")
|
|
5
|
+
process.exit(2)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
process.exit(0)
|
|
9
|
+
|
|
10
|
+
export {}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const input = await new Response(Bun.stdin.stream()).text()
|
|
2
|
+
const notices: string[] = []
|
|
3
|
+
|
|
4
|
+
if (/revela-narrative\/.*\.md/.test(input)) {
|
|
5
|
+
notices.push("Revela narrative Markdown changed. Run `revela_markdown_qa` and `revela_compile_narrative` before treating the graph as usable.")
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (/decks\/.*\.html/.test(input)) {
|
|
9
|
+
notices.push("Revela deck HTML changed. Run `revela_run_deck_qa` before review or export.")
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (notices.length > 0) {
|
|
13
|
+
console.error(notices.join("\n"))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
process.exit(0)
|
|
17
|
+
|
|
18
|
+
export {}
|