@hanzlaa/rcode 3.3.1 → 3.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/README.md +23 -38
- package/cli/index.js +0 -0
- package/cli/install.js +37 -29
- package/cli/update.js +17 -20
- package/dist/rcode.js +52 -48
- package/package.json +10 -10
- package/rihal/agents/rihal-assumptions-analyzer.md +1 -1
- package/rihal/agents/rihal-fatima.md +1 -0
- package/rihal/agents/rihal-integration-checker.md +1 -0
- package/rihal/agents/rihal-khalid.md +1 -0
- package/rihal/agents/rihal-noor.md +1 -0
- package/rihal/agents/rihal-project-researcher.md +1 -0
- package/rihal/agents/rihal-research-synthesizer.md +1 -0
- package/rihal/agents/rihal-waleed.md +1 -0
- package/rihal/skills/actions/1-analysis/research/rihal-domain-research/SKILL.md +2 -0
- package/rihal/skills/actions/1-analysis/research/rihal-market-research/SKILL.md +2 -0
- package/rihal/skills/actions/1-analysis/research/rihal-technical-research/SKILL.md +2 -0
- package/rihal/skills/actions/1-analysis/rihal-document-project/SKILL.md +2 -0
- package/rihal/skills/actions/1-analysis/rihal-prfaq/SKILL.md +2 -0
- package/rihal/skills/actions/1-analysis/rihal-product-brief/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-create-epics-and-stories/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-create-milestone/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-create-prd/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-create-story/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-create-ux-design/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-edit-prd/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-frontend-design/SKILL.md +2 -0
- package/rihal/skills/actions/2-plan/rihal-validate-prd/SKILL.md +2 -0
- package/rihal/skills/actions/3-solutioning/rihal-check-implementation-readiness/SKILL.md +2 -0
- package/rihal/skills/actions/3-solutioning/rihal-create-architecture/SKILL.md +2 -0
- package/rihal/skills/actions/3-solutioning/rihal-generate-project-context/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-browser-verify/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-ci/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-code-review/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-correct-course/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-debug/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-dev-story/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-git-flow/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-harden/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-incremental/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-migrate/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-perf/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-prove-it/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-qa-generate-e2e-tests/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-retrospective/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-scaffold-project/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-source-truth/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-sprint-planning/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-sprint-status/SKILL.md +2 -0
- package/rihal/skills/actions/4-implementation/rihal-trim/SKILL.md +2 -0
- package/rihal/skills/agents/ahmed-hassani-director/SKILL.md +2 -0
- package/rihal/skills/agents/dalil-scout/SKILL.md +2 -0
- package/rihal/skills/agents/fatima-qa/SKILL.md +2 -0
- package/rihal/skills/agents/haitham-frontend/SKILL.md +2 -0
- package/rihal/skills/agents/hanzla-engineer/SKILL.md +2 -0
- package/rihal/skills/agents/hussain-pm/SKILL.md +2 -0
- package/rihal/skills/agents/hussain-sm/SKILL.md +2 -0
- package/rihal/skills/agents/layla-designer/SKILL.md +2 -0
- package/rihal/skills/agents/majlis-council/SKILL.md +2 -0
- package/rihal/skills/agents/mariam-marketing/SKILL.md +2 -0
- package/rihal/skills/agents/nasser-eng-manager/SKILL.md +2 -0
- package/rihal/skills/agents/noor-writer/SKILL.md +2 -0
- package/rihal/skills/agents/raees-orchestrator/SKILL.md +2 -0
- package/rihal/skills/agents/sadiq-analyst/SKILL.md +2 -0
- package/rihal/skills/agents/waleed-architect/SKILL.md +2 -0
- package/rihal/skills/agents/yousef-backend/SKILL.md +2 -0
- package/rihal/skills/agents/zahra-branding/SKILL.md +2 -0
- package/rihal/skills/agents/zayd-ml/SKILL.md +2 -0
- package/rihal/skills/core/rihal-advanced-elicitation/SKILL.md +2 -0
- package/rihal/skills/core/rihal-auth-audit/SKILL.md +2 -0
- package/rihal/skills/core/rihal-brainstorming/SKILL.md +2 -0
- package/rihal/skills/core/rihal-client-gate/SKILL.md +2 -0
- package/rihal/skills/core/rihal-clone-website/SKILL.md +2 -0
- package/rihal/skills/core/rihal-deploy-unify/SKILL.md +2 -0
- package/rihal/skills/core/rihal-distillator/SKILL.md +2 -0
- package/rihal/skills/core/rihal-editorial-review-prose/SKILL.md +2 -0
- package/rihal/skills/core/rihal-editorial-review-structure/SKILL.md +2 -0
- package/rihal/skills/core/rihal-help/SKILL.md +2 -0
- package/rihal/skills/core/rihal-incident-record/SKILL.md +2 -0
- package/rihal/skills/core/rihal-index-docs/SKILL.md +2 -0
- package/rihal/skills/core/rihal-init/SKILL.md +2 -0
- package/rihal/skills/core/rihal-memory-audit/SKILL.md +2 -0
- package/rihal/skills/core/rihal-memory-distill/SKILL.md +2 -0
- package/rihal/skills/core/rihal-memory-init/SKILL.md +2 -0
- package/rihal/skills/core/rihal-memory-update/SKILL.md +2 -0
- package/rihal/skills/core/rihal-mvp-graduate/SKILL.md +2 -0
- package/rihal/skills/core/rihal-ocr-consistency/SKILL.md +2 -0
- package/rihal/skills/core/rihal-party-mode/SKILL.md +2 -0
- package/rihal/skills/core/rihal-rebrand/SKILL.md +2 -0
- package/rihal/skills/core/rihal-review-adversarial-general/SKILL.md +2 -0
- package/rihal/skills/core/rihal-review-edge-case-hunter/SKILL.md +2 -0
- package/rihal/skills/core/rihal-shard-doc/SKILL.md +2 -0
- package/rihal/skills/core/rihal-theme-system/SKILL.md +2 -0
- package/rihal/workflows/add-tests.md +1 -0
- package/rihal/workflows/audit-fix.md +2 -0
- package/rihal/workflows/autonomous.md +1 -0
- package/rihal/workflows/code-review-fix.md +2 -1
- package/rihal/workflows/debug.md +1 -0
- package/rihal/workflows/dev-story.md +1 -0
- package/rihal/workflows/execute-sprint.md +1 -0
- package/rihal/workflows/execute.md +1 -0
- package/rihal/workflows/init.md +82 -0
- package/rihal/workflows/plan.md +1 -0
- package/rihal/workflows/ship.md +2 -0
- package/rihal/workflows/sprint-planning.md +1 -0
- package/rihal/workflows/validate-phase.md +1 -0
- package/rihal/workflows/verify-phase.md +1 -0
- package/server/lib/api.js +49 -0
- package/server/lib/html/client.js +100 -10
- package/server/lib/html/css.js +64 -1
- package/server/lib/html/shell.js +11 -5
|
@@ -32,7 +32,7 @@ function chip(s) {
|
|
|
32
32
|
return '<span class="status-chip ' + c + '">● ' + s + '</span>';
|
|
33
33
|
}
|
|
34
34
|
function tag(t) { return '<span class="tag">' + t + '</span>'; }
|
|
35
|
-
function esc(s) { return String(s || '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }
|
|
35
|
+
function esc(s) { return String(s || '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,'''); }
|
|
36
36
|
function pct(d, t) { return t > 0 ? Math.round(d/t*100) + '%' : '—'; }
|
|
37
37
|
function pctNum(d, t) { return t > 0 ? Math.round(d/t*100) : 0; }
|
|
38
38
|
function dateStr(s) { return s ? String(s).slice(0,10) : null; }
|
|
@@ -197,16 +197,55 @@ function sprintCard(s) {
|
|
|
197
197
|
|
|
198
198
|
function taskCard(t) {
|
|
199
199
|
const done = t.status === 'done' || t.status === 'completed';
|
|
200
|
-
|
|
200
|
+
const tid = 'task-' + (t.id || t.title || '').replace(/[^a-zA-Z0-9]/g, '-').slice(0, 40) + '-' + Math.random().toString(36).slice(2, 6);
|
|
201
|
+
// Build detail rows from all available context
|
|
202
|
+
var rows = '';
|
|
203
|
+
if (t.id) rows += '<div class="task-detail-row"><strong>ID:</strong> <code>' + esc(t.id) + '</code></div>';
|
|
204
|
+
if (t.points) rows += '<div class="task-detail-row"><strong>Points:</strong> ' + t.points + '</div>';
|
|
205
|
+
rows += '<div class="task-detail-row"><strong>Status:</strong> ' + chip(t.status || 'unknown') + '</div>';
|
|
206
|
+
if (t.sprintId) rows += '<div class="task-detail-row"><strong>Sprint:</strong> ' + esc(t.sprintId) + '</div>';
|
|
207
|
+
if (t.sprintGoal) rows += '<div class="task-detail-row"><strong>Sprint Goal:</strong> ' + esc(t.sprintGoal) + '</div>';
|
|
208
|
+
if (t.phaseId) rows += '<div class="task-detail-row"><strong>Phase:</strong> P' + esc(t.phaseId) + (t.phaseName ? ' — ' + esc(t.phaseName) : '') + '</div>';
|
|
209
|
+
if (t.acceptance) rows += '<div class="task-detail-row"><strong>Acceptance:</strong> ' + esc(t.acceptance) + '</div>';
|
|
210
|
+
if (t.assignee) rows += '<div class="task-detail-row"><strong>Assignee:</strong> ' + esc(t.assignee) + '</div>';
|
|
211
|
+
// Context-aware commands for this specific task
|
|
212
|
+
var cmds = '';
|
|
213
|
+
if (t.id) {
|
|
214
|
+
var taskCmds = [];
|
|
215
|
+
if (!done) {
|
|
216
|
+
taskCmds.push(cmdHint('/rihal-dev-story ' + t.id, 'Implement this story'));
|
|
217
|
+
taskCmds.push(cmdHint('/rihal-create-story ' + (t.sprintId || ''), 'Add related story'));
|
|
218
|
+
} else {
|
|
219
|
+
taskCmds.push(cmdHint('/rihal-verify-work ' + t.id, 'Verify this story'));
|
|
220
|
+
taskCmds.push(cmdHint('/rihal-code-review ' + t.id, 'Review code for this story'));
|
|
221
|
+
}
|
|
222
|
+
if (t.sprintId) {
|
|
223
|
+
taskCmds.push(cmdHint('/rihal-sprint-status ' + t.sprintId, 'Sprint ' + t.sprintId + ' status'));
|
|
224
|
+
}
|
|
225
|
+
cmds = '<div class="task-detail-cmds">' + taskCmds.join('') + '</div>';
|
|
226
|
+
}
|
|
227
|
+
return '<div class="item item-clickable" data-status="' + (t.status||'') + '" style="' + (done ? 'opacity:.65' : '') + '"' +
|
|
228
|
+
' onclick="toggleTaskDetail(\\'' + tid + '\\')">' +
|
|
201
229
|
'<div class="item-title" style="' + (done ? 'text-decoration:line-through' : '') + '">' +
|
|
202
|
-
(done ? '✓ ' : '') + esc(t.title) + chip(t.status) +
|
|
230
|
+
(done ? '✓ ' : '') + esc(t.title) + chip(t.status) +
|
|
231
|
+
'<span class="task-expand-icon" id="icon-' + tid + '">▶</span></div>' +
|
|
203
232
|
'<div class="item-meta">' +
|
|
204
233
|
(t.points ? tag(t.points + 'pts') : '') +
|
|
234
|
+
(t.id ? tag(t.id) : '') +
|
|
205
235
|
(t.sprintId ? tag('Sprint ' + t.sprintId) : '') +
|
|
206
236
|
(t.phaseId ? tag('Phase ' + t.phaseId) : '') + '</div>' +
|
|
207
|
-
|
|
237
|
+
'<div class="task-detail" id="' + tid + '" style="display:none;">' +
|
|
238
|
+
rows + cmds + '</div>' +
|
|
208
239
|
'</div>';
|
|
209
240
|
}
|
|
241
|
+
function toggleTaskDetail(id) {
|
|
242
|
+
const el = document.getElementById(id);
|
|
243
|
+
const icon = document.getElementById('icon-' + id);
|
|
244
|
+
if (!el) return;
|
|
245
|
+
const open = el.style.display !== 'none';
|
|
246
|
+
el.style.display = open ? 'none' : 'block';
|
|
247
|
+
if (icon) icon.textContent = open ? '▶' : '▼';
|
|
248
|
+
}
|
|
210
249
|
|
|
211
250
|
// ---- View renderers ----
|
|
212
251
|
function renderOverview() {
|
|
@@ -464,7 +503,8 @@ function renderSprints(subId) {
|
|
|
464
503
|
if (subId) {
|
|
465
504
|
const s = sprints.find(sp => sp.id === subId);
|
|
466
505
|
if (!s) { el.innerHTML = breadcrumb('All Sprints','sprints') + '<div class="empty">Sprint not found.</div>'; return; }
|
|
467
|
-
const
|
|
506
|
+
const rawStories = Array.isArray(s.stories) ? s.stories : [];
|
|
507
|
+
const stories = rawStories.map(function(t) { return Object.assign({}, t, {sprintId: s.id, sprintGoal: s.goal || '', phaseId: s.phaseId, phaseName: s.phaseName}); });
|
|
468
508
|
const done = stories.filter(t => t.status==='done'||t.status==='completed').length;
|
|
469
509
|
// #290: acceptance criteria
|
|
470
510
|
let acHtml = '';
|
|
@@ -783,9 +823,20 @@ function filterItems(input, listId) {
|
|
|
783
823
|
let h = '<div style="padding:0 var(--space-2) var(--space-2);"><input class="filter-input" style="width:100%;max-width:none;" type="text" placeholder="Search files…" id="file-tree-search" oninput="filterFileTree(this.value)"></div>';
|
|
784
824
|
h += '<div class="file-tree" id="file-tree-items">';
|
|
785
825
|
h += groups.map(function(g) {
|
|
826
|
+
// Support sub-groups (e.g. Phases with per-phase sub-groups)
|
|
827
|
+
if (g.subGroups) {
|
|
828
|
+
return '<details class="file-tree-group" open><summary>' + g.group + '</summary>' +
|
|
829
|
+
g.subGroups.map(function(sg) {
|
|
830
|
+
return '<details class="file-tree-subgroup" open style="margin-left:var(--space-2);margin-bottom:var(--space-1);">' +
|
|
831
|
+
'<summary style="font-size:var(--text-xs);font-weight:500;color:var(--text-secondary);cursor:pointer;padding:var(--space-1) 0;user-select:none;">' + sg.subGroup + ' <span style="color:var(--text-muted);font-weight:400;">(' + sg.files.length + ')</span></summary>' +
|
|
832
|
+
sg.files.map(function(f) {
|
|
833
|
+
return '<span class="file-tree-item" data-path="' + esc(f.path) + '" data-filter-text="' + esc(f.label + ' ' + f.path + ' ' + sg.subGroup).toLowerCase() + '" style="padding-left:var(--space-4);">' + esc(f.label) + '</span>';
|
|
834
|
+
}).join('') + '</details>';
|
|
835
|
+
}).join('') + '</details>';
|
|
836
|
+
}
|
|
786
837
|
return '<details class="file-tree-group" open><summary>' + g.group + '</summary>' +
|
|
787
838
|
g.files.map(function(f) {
|
|
788
|
-
return '<span class="file-tree-item" data-path="' + f.path + '" data-filter-text="' + (f.label + ' ' + f.path).toLowerCase() + '">' + f.label + '</span>';
|
|
839
|
+
return '<span class="file-tree-item" data-path="' + esc(f.path) + '" data-filter-text="' + esc(f.label + ' ' + f.path).toLowerCase() + '">' + esc(f.label) + '</span>';
|
|
789
840
|
}).join('') + '</details>';
|
|
790
841
|
}).join('');
|
|
791
842
|
h += '</div>';
|
|
@@ -799,6 +850,8 @@ function filterItems(input, listId) {
|
|
|
799
850
|
var fv = document.getElementById('file-view');
|
|
800
851
|
// #315: loading skeleton
|
|
801
852
|
fv.innerHTML = '<div class="skeleton"></div><div class="skeleton" style="height:200px;"></div>';
|
|
853
|
+
// Scroll file content into view
|
|
854
|
+
fv.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
802
855
|
try {
|
|
803
856
|
var resp = await fetch('/api/file?path=' + encodeURIComponent(item.dataset.path));
|
|
804
857
|
if (!resp.ok) { fv.innerHTML = '<div style="color:var(--accent-red);padding:16px;">Failed to load file.</div>'; return; }
|
|
@@ -819,12 +872,30 @@ function filterItems(input, listId) {
|
|
|
819
872
|
if (!el) return;
|
|
820
873
|
let h = '<div class="filter-bar"><input class="filter-input" type="text" placeholder="Search files…" oninput="filterInlineFiles(this.value)"></div>';
|
|
821
874
|
h += '<div id="inline-file-items" class="phase-list">';
|
|
875
|
+
|
|
876
|
+
function renderFileItem(f, extraFilterText) {
|
|
877
|
+
var filterText = esc(f.label + ' ' + f.path + (extraFilterText ? ' ' + extraFilterText : '')).toLowerCase();
|
|
878
|
+
return '<div class="item item-clickable inline-file-entry" data-path="' + esc(f.path) + '" data-filter-text="' + filterText + '" onclick="loadInlineFile(this)" style="padding:var(--space-2) var(--space-3);font-family:\\'SF Mono\\',Monaco,Consolas,monospace;font-size:var(--text-xs);">' + esc(f.label) + '</div>';
|
|
879
|
+
}
|
|
880
|
+
|
|
822
881
|
groups.forEach(function(g) {
|
|
823
882
|
h += '<div class="inline-file-group" style="margin-bottom:var(--space-3);">';
|
|
824
|
-
h += '<div style="font-size:var(--text-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.07em;padding:var(--space-1) 0;">' + g.group + '</div>';
|
|
825
|
-
g.
|
|
826
|
-
|
|
827
|
-
|
|
883
|
+
h += '<div style="font-size:var(--text-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.07em;padding:var(--space-1) 0;">' + esc(g.group) + '</div>';
|
|
884
|
+
if (g.subGroups) {
|
|
885
|
+
// Render expandable sub-groups (e.g. per-phase)
|
|
886
|
+
g.subGroups.forEach(function(sg) {
|
|
887
|
+
h += '<details class="inline-subgroup" open style="margin-left:var(--space-2);margin-bottom:var(--space-1);">';
|
|
888
|
+
h += '<summary style="font-size:var(--text-xs);font-weight:500;color:var(--text-secondary);cursor:pointer;padding:var(--space-1) 0;user-select:none;">' + esc(sg.subGroup) + ' <span style="color:var(--text-muted);font-weight:400;">(' + sg.files.length + ')</span></summary>';
|
|
889
|
+
sg.files.forEach(function(f) {
|
|
890
|
+
h += renderFileItem(f, sg.subGroup);
|
|
891
|
+
});
|
|
892
|
+
h += '</details>';
|
|
893
|
+
});
|
|
894
|
+
} else if (g.files) {
|
|
895
|
+
g.files.forEach(function(f) {
|
|
896
|
+
h += renderFileItem(f, '');
|
|
897
|
+
});
|
|
898
|
+
}
|
|
828
899
|
h += '</div>';
|
|
829
900
|
});
|
|
830
901
|
h += '</div>';
|
|
@@ -840,6 +911,8 @@ async function loadInlineFile(el) {
|
|
|
840
911
|
var fv = document.getElementById('file-view');
|
|
841
912
|
if (!fv) return;
|
|
842
913
|
fv.innerHTML = '<div class="skeleton"></div><div class="skeleton" style="height:200px;"></div>';
|
|
914
|
+
// Scroll file content into view immediately
|
|
915
|
+
fv.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
843
916
|
document.querySelectorAll('.inline-file-entry').forEach(function(e) { e.style.borderLeftColor = ''; });
|
|
844
917
|
el.style.borderLeftColor = 'var(--accent-blue)';
|
|
845
918
|
// Also sync sidebar selection
|
|
@@ -1023,6 +1096,23 @@ function updateTitle() {
|
|
|
1023
1096
|
}
|
|
1024
1097
|
window.addEventListener('hashchange', updateTitle);
|
|
1025
1098
|
|
|
1099
|
+
// Sidebar toggle (hamburger menu)
|
|
1100
|
+
function toggleSidebar() {
|
|
1101
|
+
var sidebar = document.querySelector('.sidebar');
|
|
1102
|
+
var backdrop = document.getElementById('sidebar-backdrop');
|
|
1103
|
+
if (!sidebar) return;
|
|
1104
|
+
var open = sidebar.classList.toggle('sidebar-open');
|
|
1105
|
+
if (backdrop) backdrop.classList.toggle('active', open);
|
|
1106
|
+
document.body.classList.toggle('sidebar-visible', open);
|
|
1107
|
+
}
|
|
1108
|
+
function closeSidebar() {
|
|
1109
|
+
var sidebar = document.querySelector('.sidebar');
|
|
1110
|
+
var backdrop = document.getElementById('sidebar-backdrop');
|
|
1111
|
+
if (sidebar) sidebar.classList.remove('sidebar-open');
|
|
1112
|
+
if (backdrop) backdrop.classList.remove('active');
|
|
1113
|
+
document.body.classList.remove('sidebar-visible');
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1026
1116
|
// ---- Boot ----
|
|
1027
1117
|
route();
|
|
1028
1118
|
updateTitle();
|
package/server/lib/html/css.js
CHANGED
|
@@ -186,6 +186,36 @@ function renderCss() {
|
|
|
186
186
|
.item .item-meta { color: var(--text-muted); font-size: var(--text-xs); margin-bottom: var(--space-2); }
|
|
187
187
|
.item-clickable { cursor: pointer; }
|
|
188
188
|
.item-clickable:hover { background: var(--bg-hover); border-color: var(--accent-blue); }
|
|
189
|
+
|
|
190
|
+
/* Task expandable detail */
|
|
191
|
+
.task-expand-icon {
|
|
192
|
+
float: right; font-size: 10px; color: var(--text-muted);
|
|
193
|
+
transition: transform 0.2s ease;
|
|
194
|
+
}
|
|
195
|
+
.task-detail {
|
|
196
|
+
margin-top: var(--space-3); padding-top: var(--space-3);
|
|
197
|
+
border-top: 1px solid var(--border); font-size: var(--text-sm);
|
|
198
|
+
}
|
|
199
|
+
.task-detail-row { margin-bottom: var(--space-2); color: var(--text-secondary); line-height: 1.5; }
|
|
200
|
+
.task-detail-row strong { color: var(--text-primary); }
|
|
201
|
+
|
|
202
|
+
/* Hamburger & sidebar toggle */
|
|
203
|
+
.hamburger-btn {
|
|
204
|
+
display: none; background: none; border: 1px solid var(--border);
|
|
205
|
+
border-radius: var(--radius-sm); padding: 6px 8px; cursor: pointer;
|
|
206
|
+
flex-direction: column; gap: 4px; align-items: center; justify-content: center;
|
|
207
|
+
}
|
|
208
|
+
.hamburger-btn span {
|
|
209
|
+
display: block; width: 18px; height: 2px; background: var(--text-primary);
|
|
210
|
+
border-radius: 1px; transition: 0.2s;
|
|
211
|
+
}
|
|
212
|
+
.hamburger-btn:hover { background: var(--bg-hover); }
|
|
213
|
+
#sidebar-backdrop {
|
|
214
|
+
display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5);
|
|
215
|
+
z-index: 90;
|
|
216
|
+
}
|
|
217
|
+
#sidebar-backdrop.active { display: block; }
|
|
218
|
+
|
|
189
219
|
.empty { color: var(--text-muted); text-align: center; padding: var(--space-8); font-style: italic; }
|
|
190
220
|
/* #316 Actionable empty states */
|
|
191
221
|
.empty-action {
|
|
@@ -332,6 +362,17 @@ function renderCss() {
|
|
|
332
362
|
cursor: pointer; font-size: var(--text-xs); font-family: inherit;
|
|
333
363
|
}
|
|
334
364
|
.file-path-header .copy-btn:hover { color: var(--text-primary); }
|
|
365
|
+
/* File view layout */
|
|
366
|
+
#view-files { display: flex; flex-direction: column; }
|
|
367
|
+
#file-list-inline { margin-bottom: var(--space-4); }
|
|
368
|
+
#file-view { min-height: 200px; }
|
|
369
|
+
.inline-subgroup summary { list-style: none; cursor: pointer; }
|
|
370
|
+
.inline-subgroup summary::-webkit-details-marker { display: none; }
|
|
371
|
+
.inline-subgroup summary:hover { color: var(--text-primary); }
|
|
372
|
+
.file-tree-subgroup summary { list-style: none; cursor: pointer; }
|
|
373
|
+
.file-tree-subgroup summary::-webkit-details-marker { display: none; }
|
|
374
|
+
.file-tree-subgroup > summary::before { content: '▶ '; font-size: 9px; display: inline-block; }
|
|
375
|
+
.file-tree-subgroup[open] > summary::before { content: '▼ '; }
|
|
335
376
|
/* Footer */
|
|
336
377
|
footer {
|
|
337
378
|
text-align: center; padding: var(--space-8); color: var(--text-muted); font-size: var(--text-sm);
|
|
@@ -361,7 +402,13 @@ function renderCss() {
|
|
|
361
402
|
}
|
|
362
403
|
/* #323 Responsive */
|
|
363
404
|
@media (max-width: 768px) {
|
|
364
|
-
.
|
|
405
|
+
.hamburger-btn { display: flex; }
|
|
406
|
+
.sidebar {
|
|
407
|
+
display: flex; position: fixed; left: -260px; top: 0; bottom: 0;
|
|
408
|
+
z-index: 100; transition: left 0.25s ease;
|
|
409
|
+
background: var(--bg-sidebar); box-shadow: 2px 0 12px rgba(0,0,0,0.3);
|
|
410
|
+
}
|
|
411
|
+
.sidebar.sidebar-open { left: 0; }
|
|
365
412
|
.content-area { width: 100%; }
|
|
366
413
|
.view { padding: var(--space-4); }
|
|
367
414
|
header { padding: var(--space-3) var(--space-4); flex-wrap: wrap; gap: var(--space-2); }
|
|
@@ -371,6 +418,12 @@ function renderCss() {
|
|
|
371
418
|
.agents { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
|
|
372
419
|
.attr-grid { grid-template-columns: 1fr 1fr; }
|
|
373
420
|
}
|
|
421
|
+
/* Desktop sidebar toggle */
|
|
422
|
+
@media (min-width: 769px) {
|
|
423
|
+
.hamburger-btn { display: flex; }
|
|
424
|
+
.sidebar { transition: margin-left 0.25s ease, opacity 0.25s ease; }
|
|
425
|
+
body.sidebar-visible .sidebar { margin-left: 0; opacity: 1; }
|
|
426
|
+
}
|
|
374
427
|
/* Command hints accordion */
|
|
375
428
|
.cmd-hints {
|
|
376
429
|
margin-top: var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-md);
|
|
@@ -402,6 +455,16 @@ function renderCss() {
|
|
|
402
455
|
font-size: 10px; color: var(--text-muted); opacity: 0; transition: opacity 0.15s; margin-left: auto;
|
|
403
456
|
}
|
|
404
457
|
.cmd-hint-item:hover .cmd-copy { opacity: 1; }
|
|
458
|
+
/* Task detail inline commands */
|
|
459
|
+
.task-detail-cmds {
|
|
460
|
+
margin-top: var(--space-3); padding-top: var(--space-3);
|
|
461
|
+
border-top: 1px solid var(--border);
|
|
462
|
+
}
|
|
463
|
+
.task-detail-cmds::before {
|
|
464
|
+
content: '💡 Quick Commands'; display: block; font-size: var(--text-xs);
|
|
465
|
+
color: var(--text-muted); font-weight: 600; margin-bottom: var(--space-2);
|
|
466
|
+
text-transform: uppercase; letter-spacing: 0.5px;
|
|
467
|
+
}
|
|
405
468
|
/* Toast notification (for copy feedback) */
|
|
406
469
|
.toast {
|
|
407
470
|
position: fixed; bottom: 20px; right: 20px; background: var(--accent-green);
|
package/server/lib/html/shell.js
CHANGED
|
@@ -85,13 +85,19 @@ ${renderCss()}
|
|
|
85
85
|
</nav>
|
|
86
86
|
<div id="sidebar-file-tree" style="margin-top:var(--space-4);padding:0 var(--space-2);"></div>
|
|
87
87
|
</aside>
|
|
88
|
+
<div id="sidebar-backdrop" onclick="closeSidebar()"></div>
|
|
88
89
|
<div class="content-area" id="main-content">
|
|
89
90
|
<header>
|
|
90
|
-
<div
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
<div style="display:flex;align-items:center;gap:var(--space-3);">
|
|
92
|
+
<button class="hamburger-btn" id="hamburger-btn" onclick="toggleSidebar()" aria-label="Toggle menu">
|
|
93
|
+
<span></span><span></span><span></span>
|
|
94
|
+
</button>
|
|
95
|
+
<div class="brand">
|
|
96
|
+
<div class="icon">🕌</div>
|
|
97
|
+
<div>
|
|
98
|
+
<h1>Majlis — The Council</h1>
|
|
99
|
+
<div class="arabic">مجلس · ${esc(projectName)}</div>
|
|
100
|
+
</div>
|
|
95
101
|
</div>
|
|
96
102
|
</div>
|
|
97
103
|
<div class="header-actions">
|