refira-cli 0.1.2 → 0.1.3
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 +8 -5
- package/dist/index.js +88 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,17 +102,19 @@ Options:
|
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
|
105
|
-
### 5. Live Preview & Harness Validation
|
|
105
|
+
### 5. Live Preview, Push & Harness Validation
|
|
106
106
|
|
|
107
|
-
#### `refira preview`
|
|
107
|
+
#### `refira push` (or `refira preview`)
|
|
108
108
|
Inspects an HTML markup file using the Refira Agent Harness. If violations are detected, execution halts with Exit Code 1 and actionable remediation instructions. If valid, the markup is streamed directly to the Refira Canvas.
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
+
refira push checkout.html --page checkout
|
|
112
|
+
# Alternatively:
|
|
111
113
|
refira preview checkout.html --page checkout
|
|
112
114
|
```
|
|
113
115
|
|
|
114
116
|
Arguments:
|
|
115
|
-
- `<file>`: Path to the HTML file to inspect and preview.
|
|
117
|
+
- `<file>`: Path to the HTML file to inspect and push/preview.
|
|
116
118
|
|
|
117
119
|
Options:
|
|
118
120
|
- `--page <slug>`: Target page slug.
|
|
@@ -136,15 +138,16 @@ refira skill install --global
|
|
|
136
138
|
|
|
137
139
|
## Agent Harness Invariants
|
|
138
140
|
|
|
139
|
-
All markup submitted via `refira preview` must conform to these strict architectural rules:
|
|
141
|
+
All markup submitted via `refira push` / `refira preview` must conform to these strict architectural rules:
|
|
140
142
|
|
|
141
143
|
| Rule | Status | Description |
|
|
142
144
|
|---|---|---|
|
|
143
145
|
| **Standalone HTML5 + Tailwind** | Required | Markup must be valid native HTML5 with Tailwind CSS utility classes. |
|
|
144
146
|
| **No UI Frameworks** | Prohibited | React, Vue, Svelte, Angular, Solid, and JSX syntax (`className=`, `onClick={...}`, `<Component />`) are rejected. |
|
|
145
|
-
| **No External / Inter-Page Navigation** | Prohibited | Prototypes run inside sandboxed iframes. Anchors (`<a href="...">`) pointing to external URLs
|
|
147
|
+
| **No External / Inter-Page Navigation** | Prohibited | Prototypes run inside sandboxed iframes. Anchors (`<a href="...">`) pointing to external URLs, relative pages (e.g. `/checkout`), empty `href=""`, or `javascript:` navigation are rejected. Only in-page anchors (`href="#section"`) or placeholders (`href="#"`) are allowed. Target attributes (`target="_blank"`, `target="_top"`) and `<form action="...">` are prohibited. For interactive triggers, use `<button type="button">`. |
|
|
146
148
|
| **No Raw Emojis in Markup** | Prohibited | Raw unicode emojis (e.g. rocket, fire, sparkles) in HTML text nodes or attributes are rejected to maintain professional aesthetic quality. Use Lucide Icons or Heroicons SVG elements instead. |
|
|
147
149
|
| **Graphics & Animation Libraries** | Permitted | Standalone CDN scripts such as Three.js, GSAP, Spline Viewer, and Lucide Icons are explicitly allowed in document `<head>` or `<script>`. |
|
|
150
|
+
| **Mandatory Push Execution** | Required | AI agents are strictly forbidden from stopping after writing a local file. The task is only complete when `refira push` succeeds with exit code 0. |
|
|
148
151
|
|
|
149
152
|
---
|
|
150
153
|
|
package/dist/index.js
CHANGED
|
@@ -1964,6 +1964,19 @@ class CliApiClient {
|
|
|
1964
1964
|
const body = await res.json();
|
|
1965
1965
|
return body.data;
|
|
1966
1966
|
}
|
|
1967
|
+
async startGenerating(projectId, pageIdentifier) {
|
|
1968
|
+
const url = `${this.apiUrl}/api/cli/projects/${projectId}/pages/${pageIdentifier}/start-generating`;
|
|
1969
|
+
const res = await fetch(url, {
|
|
1970
|
+
method: "POST",
|
|
1971
|
+
headers: this.getHeaders()
|
|
1972
|
+
});
|
|
1973
|
+
if (!res.ok) {
|
|
1974
|
+
const err = await res.text();
|
|
1975
|
+
throw new Error(`Failed to signal generation start (${res.status}): ${err}`);
|
|
1976
|
+
}
|
|
1977
|
+
const body = await res.json();
|
|
1978
|
+
return body.data;
|
|
1979
|
+
}
|
|
1967
1980
|
}
|
|
1968
1981
|
|
|
1969
1982
|
// src/config.ts
|
|
@@ -2119,7 +2132,7 @@ function generateAgentsGuide(opts) {
|
|
|
2119
2132
|
1. **Output Format:** Standalone HTML5 + Tailwind CSS CDN only.
|
|
2120
2133
|
2. **Typography:** Load and use Google Fonts "${opts.fontFamily}".
|
|
2121
2134
|
3. **No UI Frameworks:** Prohibited from using React, Vue, Svelte, Angular, Solid, or JSX syntax (\`className=\`, \`onClick={...}\`, \`<Component />\`).
|
|
2122
|
-
4. **
|
|
2135
|
+
4. **Strict Anchor & Navigation Invariant:** Prohibited from creating cross-page navigation, external links, empty \`href=""\`, or \`javascript:\` navigation in \`<a href="...">\`. Anchor links MUST point only to in-page section hashes (e.g. \`href="#pricing"\`) or dummy hash (\`href="#"\`). Target attributes (\`target="_blank"\`, \`target="_top"\`) and external \`<form action="...">\` are prohibited. For interactive triggers, use \`<button type="button">\`.
|
|
2123
2136
|
5. **No Raw Emojis:** Do not include raw emojis (e.g. \uD83D\uDE80, \uD83D\uDCA1, \uD83D\uDD25) in HTML markup. Use SVG icon libraries (Lucide Icons or Heroicons).
|
|
2124
2137
|
6. **Permitted Graphics:** Three.js, GSAP, Spline Viewer, and Lucide Icons via CDN are explicitly allowed.
|
|
2125
2138
|
|
|
@@ -2127,18 +2140,26 @@ function generateAgentsGuide(opts) {
|
|
|
2127
2140
|
|
|
2128
2141
|
## 2. Refira CLI Command Surface
|
|
2129
2142
|
- \`refira context\`: Inspect project design tokens, colors, typography, and existing pages.
|
|
2130
|
-
- \`refira scaffold --page <slug>\`: Create a clean HTML5 starter template
|
|
2131
|
-
- \`refira
|
|
2143
|
+
- \`refira scaffold --page <slug>\`: Create a clean HTML5 starter template and trigger live generating indicator on Refira Canvas.
|
|
2144
|
+
- \`refira push <file.html> --page <slug>\` (or \`refira preview\`): Run the deterministic harness check and stream updates to Refira Canvas.
|
|
2132
2145
|
- \`refira skill install [-g]\`: Re-install the Refira design craftsmanship skill.
|
|
2133
2146
|
|
|
2134
2147
|
---
|
|
2135
2148
|
|
|
2136
2149
|
## 3. Mandatory Execution Workflow
|
|
2137
2150
|
1. Run \`refira context\` to understand the project theme and existing pages.
|
|
2138
|
-
2. Run \`refira scaffold --page <page-name>\` to
|
|
2151
|
+
2. Run \`refira scaffold --page <page-name>\` to register the page and activate live canvas pulse.
|
|
2139
2152
|
3. Write your UI layout within the specified body slot using Tailwind utility classes.
|
|
2140
|
-
4. Execute \`refira
|
|
2153
|
+
4. Execute \`refira push <page-name>.html --page <page-name>\`.
|
|
2141
2154
|
5. If the CLI exits with code 1, address every listed violation and retry until exit code 0.
|
|
2155
|
+
|
|
2156
|
+
---
|
|
2157
|
+
|
|
2158
|
+
## 4. Mandatory Delivery Invariant (Push to Canvas)
|
|
2159
|
+
- **Local HTML files are NOT the final deliverable.** Refira Canvas is the live source of truth.
|
|
2160
|
+
- **Strictly Prohibited:** Stopping, ending your response, or reporting completion to the user after only writing a local HTML file.
|
|
2161
|
+
- **Autonomous Execution:** You MUST execute \`refira push <file.html> --page <slug>\` via your command-line execution tool. Do NOT ask the user to run it manually.
|
|
2162
|
+
- **Success Criteria:** A task is ONLY complete when \`refira push\` succeeds with exit code 0 and streams to Refira Canvas.
|
|
2142
2163
|
`;
|
|
2143
2164
|
}
|
|
2144
2165
|
|
|
@@ -2198,9 +2219,10 @@ When presenting features, data, or product capabilities:
|
|
|
2198
2219
|
## 5. Prototype Workflow in Refira
|
|
2199
2220
|
|
|
2200
2221
|
1. Check current tokens: \`refira context\`
|
|
2201
|
-
2. Generate base page: \`refira scaffold --page <slug>\`
|
|
2222
|
+
2. Generate base page & trigger canvas pulse: \`refira scaffold --page <slug>\`
|
|
2202
2223
|
3. Fill layout using Tailwind classes applying the aesthetic principles above.
|
|
2203
|
-
4.
|
|
2224
|
+
4. Stream to Refira Canvas: \`refira push <slug>.html --page <slug>\`
|
|
2225
|
+
5. Mandatory: Never stop after writing local files. Always execute \`refira push\` to complete the task.
|
|
2204
2226
|
`;
|
|
2205
2227
|
}
|
|
2206
2228
|
|
|
@@ -3633,12 +3655,14 @@ function checkTagName(name, violations) {
|
|
|
3633
3655
|
}
|
|
3634
3656
|
function checkAttributes(name, attribs, violations) {
|
|
3635
3657
|
for (const [attrKey, attrVal] of Object.entries(attribs)) {
|
|
3636
|
-
|
|
3658
|
+
const lowerAttr = attrKey.toLowerCase();
|
|
3659
|
+
const lowerTag = name.toLowerCase();
|
|
3660
|
+
if (lowerAttr === "classname") {
|
|
3637
3661
|
violations.push({
|
|
3638
3662
|
type: "JSX_ATTRIBUTE",
|
|
3639
|
-
target:
|
|
3640
|
-
message: `Prohibited JSX attribute '
|
|
3641
|
-
remediation: `Change '
|
|
3663
|
+
target: attrKey,
|
|
3664
|
+
message: `Prohibited JSX attribute '${attrKey}' detected on <${name}>.`,
|
|
3665
|
+
remediation: `Change '${attrKey}' to the standard HTML 'class' attribute.`
|
|
3642
3666
|
});
|
|
3643
3667
|
}
|
|
3644
3668
|
if (/^on[A-Z]/.test(attrKey) || attrKey.startsWith("@") || attrKey.startsWith("v-") || attrKey.startsWith("*")) {
|
|
@@ -3649,15 +3673,52 @@ function checkAttributes(name, attribs, violations) {
|
|
|
3649
3673
|
remediation: "Remove framework event bindings. Use vanilla HTML and minimal vanilla JavaScript if needed."
|
|
3650
3674
|
});
|
|
3651
3675
|
}
|
|
3652
|
-
if (
|
|
3676
|
+
if (lowerAttr.startsWith("on") && (attrVal.includes("location") || attrVal.includes("window.open") || attrVal.includes("history."))) {
|
|
3677
|
+
violations.push({
|
|
3678
|
+
type: "NAVIGATION_PROHIBITED",
|
|
3679
|
+
target: `${attrKey}="${attrVal}"`,
|
|
3680
|
+
message: `Inline navigation script '${attrVal}' detected on <${name}>.`,
|
|
3681
|
+
remediation: "Remove inline navigation scripts. Prototypes run in a sandboxed canvas and cannot navigate across pages."
|
|
3682
|
+
});
|
|
3683
|
+
}
|
|
3684
|
+
if (lowerTag === "a") {
|
|
3685
|
+
if (lowerAttr === "href") {
|
|
3686
|
+
const trimmed = attrVal.trim();
|
|
3687
|
+
const isSafeHash = trimmed.startsWith("#");
|
|
3688
|
+
const isSafeVoid = trimmed === "javascript:void(0)" || trimmed === "javascript:;";
|
|
3689
|
+
if (!isSafeHash && !isSafeVoid) {
|
|
3690
|
+
violations.push({
|
|
3691
|
+
type: "NAVIGATION_PROHIBITED",
|
|
3692
|
+
target: `${attrKey}="${attrVal}"`,
|
|
3693
|
+
message: `Cross-page or external navigation '<a ${attrKey}="${attrVal}">' is strictly prohibited.`,
|
|
3694
|
+
remediation: 'Refira prototypes run in a sandboxed iframe. Anchor links must point to in-page section hashes (e.g. href="#features") or placeholder (href="#"). If you need action triggers, use <button type="button">.'
|
|
3695
|
+
});
|
|
3696
|
+
} else if (trimmed.includes("location") || trimmed.includes("window.open")) {
|
|
3697
|
+
violations.push({
|
|
3698
|
+
type: "NAVIGATION_PROHIBITED",
|
|
3699
|
+
target: `${attrKey}="${attrVal}"`,
|
|
3700
|
+
message: `Navigation statement detected inside href: '${attrVal}'.`,
|
|
3701
|
+
remediation: "Remove navigation statements from href."
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
if (lowerAttr === "target" && attrVal.trim().length > 0) {
|
|
3706
|
+
violations.push({
|
|
3707
|
+
type: "NAVIGATION_PROHIBITED",
|
|
3708
|
+
target: `${attrKey}="${attrVal}"`,
|
|
3709
|
+
message: `Target attribute '${attrKey}="${attrVal}"' on <a> is prohibited.`,
|
|
3710
|
+
remediation: "Remove the target attribute. Prototypes must remain within the Refira Canvas viewport."
|
|
3711
|
+
});
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
if (lowerTag === "form" && lowerAttr === "action") {
|
|
3653
3715
|
const trimmed = attrVal.trim();
|
|
3654
|
-
|
|
3655
|
-
if (!isInternal && trimmed.length > 0) {
|
|
3716
|
+
if (trimmed.length > 0 && !trimmed.startsWith("#") && !trimmed.startsWith("javascript:void")) {
|
|
3656
3717
|
violations.push({
|
|
3657
3718
|
type: "NAVIGATION_PROHIBITED",
|
|
3658
|
-
target:
|
|
3659
|
-
message: `
|
|
3660
|
-
remediation:
|
|
3719
|
+
target: `${attrKey}="${attrVal}"`,
|
|
3720
|
+
message: `Form action '${attrVal}' is prohibited in standalone prototypes.`,
|
|
3721
|
+
remediation: 'Remove or replace form action with action="#" or handle submission client-side without page reload.'
|
|
3661
3722
|
});
|
|
3662
3723
|
}
|
|
3663
3724
|
}
|
|
@@ -3929,6 +3990,10 @@ async function scaffoldCommand(opts) {
|
|
|
3929
3990
|
}
|
|
3930
3991
|
colorTokens = parsed;
|
|
3931
3992
|
}
|
|
3993
|
+
try {
|
|
3994
|
+
await client.startGenerating(config.projectId, pageSlug);
|
|
3995
|
+
console.log(`✨ Activated live generation indicator on Refira Canvas for '${pageSlug}'`);
|
|
3996
|
+
} catch {}
|
|
3932
3997
|
} catch {}
|
|
3933
3998
|
}
|
|
3934
3999
|
const pageName = pageSlug.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
@@ -3944,8 +4009,10 @@ async function scaffoldCommand(opts) {
|
|
|
3944
4009
|
console.log(` Font: ${fontFamily}`);
|
|
3945
4010
|
console.log(" Slot: <!-- [REFIRA CANVAS SLOT: START] -->");
|
|
3946
4011
|
console.log(`
|
|
3947
|
-
|
|
3948
|
-
console.log(`
|
|
4012
|
+
\uD83D\uDEA8 [MANDATORY AGENT COMPLETION GATE]:`);
|
|
4013
|
+
console.log(` 1. Write your UI layout within the designated slot in '${targetPath}'.`);
|
|
4014
|
+
console.log(` 2. You MUST execute: refira push ${targetPath} --page ${pageSlug}`);
|
|
4015
|
+
console.log(" DO NOT stop your response or declare completion until `refira push` succeeds!");
|
|
3949
4016
|
}
|
|
3950
4017
|
|
|
3951
4018
|
// src/commands/skill.ts
|
|
@@ -3967,14 +4034,14 @@ AI coding agents will automatically recognize this skill for high-aesthetic prot
|
|
|
3967
4034
|
|
|
3968
4035
|
// src/index.ts
|
|
3969
4036
|
var program2 = new Command2;
|
|
3970
|
-
program2.name("refira").description("Refira CLI tool and AI Agent Harness for deterministic prototype generation").version("0.1.
|
|
4037
|
+
program2.name("refira").description("Refira CLI tool and AI Agent Harness for deterministic prototype generation").version("0.1.3");
|
|
3971
4038
|
var auth = program2.command("auth").description("Manage Refira API authentication and sessions");
|
|
3972
4039
|
auth.command("login").description("Login to Refira using an API key").option("--api-url <url>", "Refira backend API base URL", "http://localhost:3001").option("--api-key <key>", "Project API key (rfr_...)").option("-g, --global", "Save credentials globally in user home directory", false).action(loginCommand);
|
|
3973
4040
|
auth.command("status").description("Verify and display current Refira authentication session").action(statusCommand);
|
|
3974
4041
|
program2.command("init").description("Initialize a Refira project workspace, generating AGENTS.md, .cursorrules, and skills").requiredOption("--project-id <id>", "Target project UUID").option("--api-url <url>", "Refira backend API base URL").option("--api-key <key>", "Project API key (rfr_...)").action(initCommand);
|
|
3975
4042
|
program2.command("context").description("Inspect design tokens, color palette, typography, and page roster").option("--project-id <id>", "Project UUID").action(contextCommand);
|
|
3976
4043
|
program2.command("scaffold").description("Generate a clean HTML5 + Tailwind starter template for a page").requiredOption("--page <slug>", "Page slug (e.g. checkout, dashboard, landing)").option("--output <path>", "Destination file path").action(scaffoldCommand);
|
|
3977
|
-
program2.command("preview").description("Inspect HTML markup with Agent Harness and stream to Refira Canvas").argument("<file>", "Path to HTML file to preview").requiredOption("--page <slug>", "Target page slug").action(previewCommand);
|
|
4044
|
+
program2.command("preview").alias("push").description("Inspect HTML markup with Agent Harness and stream to Refira Canvas").argument("<file>", "Path to HTML file to preview").requiredOption("--page <slug>", "Target page slug").action(previewCommand);
|
|
3978
4045
|
var skill = program2.command("skill").description("Manage Refira Agent Skills");
|
|
3979
4046
|
skill.command("install").description("Install the Refira design craftsmanship skill (.agents/skills/refira/SKILL.md)").option("-g, --global", "Install globally into user home directory (~/.agents/skills/refira)", false).action(skillInstallCommand);
|
|
3980
4047
|
program2.parse();
|