navori 0.2.5 → 0.2.6
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/dist/index.js +109 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1653,6 +1653,51 @@ function extractManagedContent(existing, id, commentStyle = "html") {
|
|
|
1653
1653
|
const match = findMarker(existing, id, syntax);
|
|
1654
1654
|
return match ? match.content : null;
|
|
1655
1655
|
}
|
|
1656
|
+
function locateManagedBlocks(content, syntax) {
|
|
1657
|
+
const openRegex = new RegExp(
|
|
1658
|
+
`${escapeRegex(syntax.openPrefix)}\\s+id="([^"]+)"${syntax.attrsAndTerminatorPattern}`,
|
|
1659
|
+
"g"
|
|
1660
|
+
);
|
|
1661
|
+
const blocks = [];
|
|
1662
|
+
for (const m of content.matchAll(openRegex)) {
|
|
1663
|
+
if (m.index === void 0) continue;
|
|
1664
|
+
const id = m[1];
|
|
1665
|
+
const close = closeMarker(id, syntax);
|
|
1666
|
+
const closeStart = content.indexOf(close, m.index + m[0].length);
|
|
1667
|
+
if (closeStart < 0) continue;
|
|
1668
|
+
blocks.push({ id, openStart: m.index, closeEnd: closeStart + close.length });
|
|
1669
|
+
}
|
|
1670
|
+
return blocks;
|
|
1671
|
+
}
|
|
1672
|
+
function reorderManagedBlocks(content, canonicalOrder, commentStyle = "html") {
|
|
1673
|
+
const syntax = syntaxFor(commentStyle);
|
|
1674
|
+
const blocks = locateManagedBlocks(content, syntax);
|
|
1675
|
+
if (blocks.length < 2) {
|
|
1676
|
+
return { output: content, reordered: false, blockedByInterleaving: false };
|
|
1677
|
+
}
|
|
1678
|
+
const rank = /* @__PURE__ */ new Map();
|
|
1679
|
+
canonicalOrder.forEach((id, i) => {
|
|
1680
|
+
if (!rank.has(id)) rank.set(id, i);
|
|
1681
|
+
});
|
|
1682
|
+
const unknownBase = canonicalOrder.length;
|
|
1683
|
+
const desired = blocks.map((b, i) => ({ b, i, key: rank.has(b.id) ? rank.get(b.id) : unknownBase + i })).sort((a, z8) => a.key - z8.key || a.i - z8.i).map((x) => x.b);
|
|
1684
|
+
if (desired.every((b, i) => b === blocks[i])) {
|
|
1685
|
+
return { output: content, reordered: false, blockedByInterleaving: false };
|
|
1686
|
+
}
|
|
1687
|
+
for (let i = 0; i < blocks.length - 1; i++) {
|
|
1688
|
+
const gap = content.slice(blocks[i].closeEnd, blocks[i + 1].openStart);
|
|
1689
|
+
if (gap.trim() !== "") {
|
|
1690
|
+
return { output: content, reordered: false, blockedByInterleaving: true };
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
const first = blocks[0];
|
|
1694
|
+
const last = blocks[blocks.length - 1];
|
|
1695
|
+
const preamble = content.slice(0, first.openStart);
|
|
1696
|
+
const suffix = content.slice(last.closeEnd);
|
|
1697
|
+
const body = desired.map((b) => content.slice(b.openStart, b.closeEnd)).join("\n\n");
|
|
1698
|
+
const pre = preamble === "" ? "" : preamble.replace(/\n*$/, "\n\n");
|
|
1699
|
+
return { output: pre + body + suffix, reordered: true, blockedByInterleaving: false };
|
|
1700
|
+
}
|
|
1656
1701
|
function resolveCondition(config, path) {
|
|
1657
1702
|
const segments = path.split(".");
|
|
1658
1703
|
let cursor = config;
|
|
@@ -1885,6 +1930,16 @@ function computeRenderPlan(existing, inputConfig, repoRoot, options = {}) {
|
|
|
1885
1930
|
updatesAvailable
|
|
1886
1931
|
};
|
|
1887
1932
|
}
|
|
1933
|
+
var CLAUDE_COMPUTED_BLOCK_IDS = [
|
|
1934
|
+
"skills-index",
|
|
1935
|
+
"agentes-disponibles",
|
|
1936
|
+
"contexto-proyecto"
|
|
1937
|
+
];
|
|
1938
|
+
function canonicalManagedOrder(config, repoRoot) {
|
|
1939
|
+
const plan = computeRenderPlan("", config, repoRoot);
|
|
1940
|
+
const ids = plan.entries.filter((entry) => entry.newContent !== null).map((entry) => entry.asset.id);
|
|
1941
|
+
return [...ids, ...CLAUDE_COMPUTED_BLOCK_IDS];
|
|
1942
|
+
}
|
|
1888
1943
|
|
|
1889
1944
|
// src/engines/claude/settings-detection.ts
|
|
1890
1945
|
var NAVORI_OWNERSHIP_MARKER = "$navori";
|
|
@@ -2491,6 +2546,13 @@ function renderClaudeEngine(cwd, inputConfig, options = {}) {
|
|
|
2491
2546
|
} else {
|
|
2492
2547
|
claudeMdContent = removeManagedSection(claudeMdContent, CONTEXTO_PROYECTO_ID);
|
|
2493
2548
|
}
|
|
2549
|
+
const reorder = reorderManagedBlocks(claudeMdContent, canonicalManagedOrder(config, repoRoot));
|
|
2550
|
+
claudeMdContent = reorder.output;
|
|
2551
|
+
if (reorder.blockedByInterleaving) {
|
|
2552
|
+
warnings.push(
|
|
2553
|
+
"CLAUDE.md: los bloques managed est\xE1n fuera del orden can\xF3nico, pero hay texto tuyo intercalado entre bloques, as\xED que no los reorden\xE9. Mueve ese texto arriba del primer bloque managed o abajo del \xFAltimo para que navori pueda ordenarlos."
|
|
2554
|
+
);
|
|
2555
|
+
}
|
|
2494
2556
|
if (claudeMdContent !== claudeMdExisting) {
|
|
2495
2557
|
pending.push({
|
|
2496
2558
|
path: claudeMdPath,
|
|
@@ -4831,21 +4893,45 @@ function scanManagedDrift(cwd, config) {
|
|
|
4831
4893
|
}
|
|
4832
4894
|
return out;
|
|
4833
4895
|
}
|
|
4896
|
+
function scanManagedOrder(cwd, config) {
|
|
4897
|
+
const claudeMdPath = join13(cwd, "CLAUDE.md");
|
|
4898
|
+
if (!existsSync17(claudeMdPath)) return null;
|
|
4899
|
+
const content = readFileSync14(claudeMdPath, "utf-8");
|
|
4900
|
+
const current = listMarkers(claudeMdPath).map((m) => m.id);
|
|
4901
|
+
if (current.length < 2) return null;
|
|
4902
|
+
const canonical = canonicalManagedOrder(config, cwd);
|
|
4903
|
+
const result = reorderManagedBlocks(content, canonical);
|
|
4904
|
+
if (!result.reordered && !result.blockedByInterleaving) return null;
|
|
4905
|
+
const rank = /* @__PURE__ */ new Map();
|
|
4906
|
+
canonical.forEach((id, i) => {
|
|
4907
|
+
if (!rank.has(id)) rank.set(id, i);
|
|
4908
|
+
});
|
|
4909
|
+
const expected = current.map((id, i) => ({ id, i, key: rank.has(id) ? rank.get(id) : canonical.length + i })).sort((a, z8) => a.key - z8.key || a.i - z8.i).map((x) => x.id);
|
|
4910
|
+
return { current, expected, interleaved: result.blockedByInterleaving };
|
|
4911
|
+
}
|
|
4834
4912
|
function suggestNextSteps(state) {
|
|
4835
4913
|
const steps = [];
|
|
4836
4914
|
if (!state.claudeMdExists) {
|
|
4837
|
-
steps.push("
|
|
4915
|
+
steps.push("Corre 'navori render --apply' para generar CLAUDE.md + .claude/.");
|
|
4838
4916
|
}
|
|
4839
4917
|
if (state.missingPlugins.length > 0) {
|
|
4840
4918
|
steps.push(
|
|
4841
|
-
`
|
|
4919
|
+
`Resuelve ${state.missingPlugins.length} plugin(s) faltante(s): inst\xE1lalos o qu\xEDtalos del config.`
|
|
4842
4920
|
);
|
|
4843
4921
|
}
|
|
4844
4922
|
if (state.drifts.some((d) => d.kind === "content")) {
|
|
4845
|
-
steps.push("
|
|
4923
|
+
steps.push("Corre 'navori sync --interactive' para resolver bloques editados a mano.");
|
|
4846
4924
|
}
|
|
4847
4925
|
if (state.drifts.some((d) => d.kind === "version")) {
|
|
4848
|
-
steps.push("
|
|
4926
|
+
steps.push("Corre 'navori render --apply' para traer los bloques a la \xFAltima versi\xF3n.");
|
|
4927
|
+
}
|
|
4928
|
+
if (state.orderReport && !state.orderReport.interleaved) {
|
|
4929
|
+
steps.push("Corre 'navori render --apply' para reordenar los bloques de CLAUDE.md al orden can\xF3nico.");
|
|
4930
|
+
}
|
|
4931
|
+
if (state.orderReport?.interleaved) {
|
|
4932
|
+
steps.push(
|
|
4933
|
+
"Mueve el texto que tienes entre bloques managed de CLAUDE.md arriba del primer bloque o abajo del \xFAltimo; luego corre 'navori render --apply' para reordenarlos."
|
|
4934
|
+
);
|
|
4849
4935
|
}
|
|
4850
4936
|
if (steps.length === 0) {
|
|
4851
4937
|
steps.push("Todo al d\xEDa \u2014 sin acciones pendientes.");
|
|
@@ -4910,6 +4996,7 @@ var doctorCommand = defineCommand3({
|
|
|
4910
4996
|
const markers = listMarkers(claudeMdPath);
|
|
4911
4997
|
const missingPlugins = collectMissingPlugins(config);
|
|
4912
4998
|
const drifts = scanManagedDrift(cwd, config);
|
|
4999
|
+
const orderReport = scanManagedOrder(cwd, config);
|
|
4913
5000
|
const corruptedSettings = scanCorruptedSettings(cwd);
|
|
4914
5001
|
const missingInvariants = scanMissingInvariants(cwd, config);
|
|
4915
5002
|
const resolvedPreset = config.preset !== "custom" ? resolvePreset(config.preset, cwd) : null;
|
|
@@ -4934,6 +5021,7 @@ var doctorCommand = defineCommand3({
|
|
|
4934
5021
|
managedBlocks: markers,
|
|
4935
5022
|
missingPlugins,
|
|
4936
5023
|
drifts,
|
|
5024
|
+
orderReport,
|
|
4937
5025
|
corruptedSettings,
|
|
4938
5026
|
missingInvariants,
|
|
4939
5027
|
missingPreset,
|
|
@@ -5057,10 +5145,26 @@ ${lines.join("\n")}`
|
|
|
5057
5145
|
${lines.join("\n")}`
|
|
5058
5146
|
);
|
|
5059
5147
|
}
|
|
5148
|
+
if (orderReport) {
|
|
5149
|
+
if (orderReport.interleaved) {
|
|
5150
|
+
p3.log.warn(
|
|
5151
|
+
`Bloques managed de CLAUDE.md fuera del orden can\xF3nico \u2014 NO se pueden reordenar autom\xE1ticamente porque hay texto tuyo entre bloques. Mueve ese texto arriba del primer bloque managed o abajo del \xFAltimo; luego corre 'navori render --apply'.
|
|
5152
|
+
orden actual: ${orderReport.current.join(", ")}
|
|
5153
|
+
orden can\xF3nico: ${orderReport.expected.join(", ")}`
|
|
5154
|
+
);
|
|
5155
|
+
} else {
|
|
5156
|
+
p3.log.warn(
|
|
5157
|
+
`Bloques managed de CLAUDE.md fuera del orden can\xF3nico \u2014 corre 'navori render --apply' o 'navori sync' para reordenarlos (el primer bloque marca el centro de gravedad del harness).
|
|
5158
|
+
orden actual: ${orderReport.current.join(", ")}
|
|
5159
|
+
orden can\xF3nico: ${orderReport.expected.join(", ")}`
|
|
5160
|
+
);
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5060
5163
|
const nextSteps = suggestNextSteps({
|
|
5061
5164
|
claudeMdExists: report.checks.claudeMdExists,
|
|
5062
5165
|
missingPlugins,
|
|
5063
|
-
drifts
|
|
5166
|
+
drifts,
|
|
5167
|
+
orderReport
|
|
5064
5168
|
});
|
|
5065
5169
|
p3.note(
|
|
5066
5170
|
nextSteps.map((s) => ` ${color.cyan(sym.bullet)} ${s}`).join("\n"),
|