@neuroverseos/governance 0.9.0 → 0.11.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 +1 -1
- package/dist/adapters/autoresearch.cjs +19 -1
- package/dist/adapters/autoresearch.d.cts +1 -1
- package/dist/adapters/autoresearch.d.ts +1 -1
- package/dist/adapters/autoresearch.js +2 -2
- package/dist/adapters/deep-agents.cjs +19 -1
- package/dist/adapters/deep-agents.d.cts +2 -2
- package/dist/adapters/deep-agents.d.ts +2 -2
- package/dist/adapters/deep-agents.js +2 -2
- package/dist/adapters/express.cjs +19 -1
- package/dist/adapters/express.d.cts +1 -1
- package/dist/adapters/express.d.ts +1 -1
- package/dist/adapters/express.js +2 -2
- package/dist/adapters/github.cjs +19 -1
- package/dist/adapters/github.d.cts +2 -2
- package/dist/adapters/github.d.ts +2 -2
- package/dist/adapters/github.js +2 -2
- package/dist/adapters/index.cjs +19 -1
- package/dist/adapters/index.d.cts +2 -2
- package/dist/adapters/index.d.ts +2 -2
- package/dist/adapters/index.js +8 -8
- package/dist/adapters/langchain.cjs +19 -1
- package/dist/adapters/langchain.d.cts +2 -2
- package/dist/adapters/langchain.d.ts +2 -2
- package/dist/adapters/langchain.js +2 -2
- package/dist/adapters/mentraos.cjs +19 -1
- package/dist/adapters/mentraos.d.cts +2 -2
- package/dist/adapters/mentraos.d.ts +2 -2
- package/dist/adapters/mentraos.js +2 -2
- package/dist/adapters/openai.cjs +19 -1
- package/dist/adapters/openai.d.cts +2 -2
- package/dist/adapters/openai.d.ts +2 -2
- package/dist/adapters/openai.js +2 -2
- package/dist/adapters/openclaw.cjs +19 -1
- package/dist/adapters/openclaw.d.cts +2 -2
- package/dist/adapters/openclaw.d.ts +2 -2
- package/dist/adapters/openclaw.js +2 -2
- package/dist/admin/index.cjs +19 -1
- package/dist/admin/index.js +1 -1
- package/dist/audit-CRJOB4CP.js +93 -0
- package/dist/audit-behavior-C62FdRAC.d.cts +100 -0
- package/dist/audit-behavior-DFy7LeYv.d.ts +100 -0
- package/dist/{behavioral-SPWPGYXL.js → behavioral-4TKMHZQZ.js} +2 -2
- package/dist/{chunk-OQU65525.js → chunk-24YW7BHC.js} +1 -1
- package/dist/{chunk-3ZWU7C43.js → chunk-2KTPIE57.js} +494 -14
- package/dist/{chunk-TJ5L2UTE.js → chunk-5K3LATTM.js} +1 -1
- package/dist/{chunk-HDNDL6D5.js → chunk-5LDBYOSJ.js} +1 -1
- package/dist/{chunk-FDPPZLSQ.js → chunk-5ZWKM7MO.js} +1 -1
- package/dist/{chunk-B3IIPTY3.js → chunk-6MB6TMAG.js} +1 -1
- package/dist/{chunk-IOVXB6QN.js → chunk-GXTAHCND.js} +1 -1
- package/dist/{chunk-FKQCPRKI.js → chunk-MAOIHKFO.js} +1 -1
- package/dist/{chunk-ZAF6JH23.js → chunk-MBOW6YXN.js} +19 -1
- package/dist/{chunk-A2UZTLRV.js → chunk-MLXKSX3L.js} +1 -1
- package/dist/{chunk-7FL3U7Z5.js → chunk-MWGEXHOD.js} +1 -1
- package/dist/{chunk-6CV4XG3J.js → chunk-QFDFAWZ6.js} +1 -1
- package/dist/{chunk-2VAWP6FI.js → chunk-RAS62JXV.js} +1 -1
- package/dist/{chunk-OTZU76DH.js → chunk-XAF3CYCW.js} +1 -1
- package/dist/{chunk-T6GMRZWC.js → chunk-XTYQCTDD.js} +1 -1
- package/dist/{chunk-TIXVEPS2.js → chunk-YN7OI5ZV.js} +1 -1
- package/dist/cli/neuroverse.cjs +999 -111
- package/dist/cli/neuroverse.js +16 -12
- package/dist/cli/plan.cjs +18 -0
- package/dist/cli/radiant.cjs +814 -17
- package/dist/cli/radiant.d.cts +44 -1
- package/dist/cli/radiant.d.ts +44 -1
- package/dist/cli/radiant.js +295 -7
- package/dist/cli/run.cjs +18 -0
- package/dist/cli/run.js +4 -4
- package/dist/{decision-flow-IJPNMVQK.js → decision-flow-5VI5YG6A.js} +2 -2
- package/dist/{demo-6W3YXLAX.js → demo-GYX6CYHC.js} +2 -2
- package/dist/engine/guard-engine.cjs +19 -1
- package/dist/engine/guard-engine.d.cts +21 -1
- package/dist/engine/guard-engine.d.ts +21 -1
- package/dist/engine/guard-engine.js +1 -1
- package/dist/{equity-penalties-CCO3GVHS.js → equity-penalties-NOM46NEO.js} +2 -2
- package/dist/{guard-IHJEKHL2.js → guard-PQ3SYV4Y.js} +3 -3
- package/dist/{guard-contract-ddiIPlOg.d.cts → guard-contract-Oznf-Kgq.d.cts} +32 -0
- package/dist/{guard-contract-q6HJAq3Q.d.ts → guard-contract-w_i_6gh-.d.ts} +32 -0
- package/dist/{impact-WIAM66IH.js → impact-LDJLTVRU.js} +3 -3
- package/dist/index.cjs +62 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +49 -8
- package/dist/{mcp-server-CKYBHXWK.js → mcp-server-W3MWSKD7.js} +2 -2
- package/dist/{playground-3TTBN7XD.js → playground-SSZRNUAF.js} +1 -1
- package/dist/radiant/index.cjs +517 -14
- package/dist/radiant/index.d.cts +180 -10
- package/dist/radiant/index.d.ts +180 -10
- package/dist/radiant/index.js +12 -2
- package/dist/{redteam-W644UMWN.js → redteam-KCULS7EW.js} +1 -1
- package/dist/{server-JKUBUK5H.js → server-EGRGGSM2.js} +2 -2
- package/dist/{session-FMAROEIE.js → session-PZLTL22G.js} +2 -2
- package/dist/{shared-PpalGKxc.d.cts → shared-BC8mOpt0.d.cts} +1 -1
- package/dist/{shared-DAzdfWtU.d.ts → shared-CP63gNNW.d.ts} +1 -1
- package/dist/{test-XDB2DH3L.js → test-LIHGWHBA.js} +1 -1
- package/dist/{trace-2YDNAXMK.js → trace-DC3D7XPD.js} +2 -2
- package/examples/radiant-weekly-workflow.yml +4 -1
- package/package.json +1 -1
- /package/dist/{doctor-XEMLO6UA.js → doctor-SIWQGTAO.js} +0 -0
package/dist/cli/radiant.cjs
CHANGED
|
@@ -1670,6 +1670,262 @@ var init_notion = __esm({
|
|
|
1670
1670
|
}
|
|
1671
1671
|
});
|
|
1672
1672
|
|
|
1673
|
+
// src/radiant/adapters/linear.ts
|
|
1674
|
+
async function fetchLinearActivity(apiKey, options = {}) {
|
|
1675
|
+
const windowDays = options.windowDays ?? 14;
|
|
1676
|
+
const maxIssues = options.maxIssues ?? 200;
|
|
1677
|
+
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
1678
|
+
const sinceIso = since.toISOString();
|
|
1679
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
1680
|
+
const teamFilter = options.teamIds && options.teamIds.length > 0 ? `team: { id: { in: [${options.teamIds.map((t) => JSON.stringify(t)).join(", ")}] } }` : "";
|
|
1681
|
+
const issuesQuery = `
|
|
1682
|
+
query RadiantIssues($since: DateTimeOrDuration!, $first: Int!) {
|
|
1683
|
+
issues(
|
|
1684
|
+
filter: {
|
|
1685
|
+
updatedAt: { gte: $since }
|
|
1686
|
+
${teamFilter}
|
|
1687
|
+
}
|
|
1688
|
+
first: $first
|
|
1689
|
+
orderBy: updatedAt
|
|
1690
|
+
) {
|
|
1691
|
+
nodes {
|
|
1692
|
+
id
|
|
1693
|
+
identifier
|
|
1694
|
+
title
|
|
1695
|
+
url
|
|
1696
|
+
createdAt
|
|
1697
|
+
updatedAt
|
|
1698
|
+
completedAt
|
|
1699
|
+
canceledAt
|
|
1700
|
+
state { name type }
|
|
1701
|
+
assignee { id name email }
|
|
1702
|
+
creator { id name }
|
|
1703
|
+
team { id name }
|
|
1704
|
+
project { id name }
|
|
1705
|
+
cycle { id number startsAt endsAt }
|
|
1706
|
+
comments(first: 20) {
|
|
1707
|
+
nodes { id body createdAt user { id name } }
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
`;
|
|
1713
|
+
const cyclesQuery = `
|
|
1714
|
+
query RadiantCycles($since: DateTimeOrDuration!, $now: DateTimeOrDuration!) {
|
|
1715
|
+
cycles(
|
|
1716
|
+
filter: { endsAt: { gte: $since, lte: $now } }
|
|
1717
|
+
first: 20
|
|
1718
|
+
) {
|
|
1719
|
+
nodes {
|
|
1720
|
+
id
|
|
1721
|
+
number
|
|
1722
|
+
startsAt
|
|
1723
|
+
endsAt
|
|
1724
|
+
issueCountHistory
|
|
1725
|
+
completedIssueCountHistory
|
|
1726
|
+
team { id name }
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
`;
|
|
1731
|
+
const [issuesResponse, cyclesResponse] = await Promise.all([
|
|
1732
|
+
fetchLinearGraphQL(apiKey, issuesQuery, {
|
|
1733
|
+
since: sinceIso,
|
|
1734
|
+
first: maxIssues
|
|
1735
|
+
}),
|
|
1736
|
+
fetchLinearGraphQL(apiKey, cyclesQuery, {
|
|
1737
|
+
since: sinceIso,
|
|
1738
|
+
now: nowIso
|
|
1739
|
+
})
|
|
1740
|
+
]);
|
|
1741
|
+
const rawIssues = issuesResponse.issues?.nodes ?? [];
|
|
1742
|
+
const rawCycles = cyclesResponse.cycles?.nodes ?? [];
|
|
1743
|
+
const events = [];
|
|
1744
|
+
const assignees = /* @__PURE__ */ new Set();
|
|
1745
|
+
const projects = /* @__PURE__ */ new Map();
|
|
1746
|
+
let issuesCreated = 0;
|
|
1747
|
+
let issuesCompleted = 0;
|
|
1748
|
+
let issuesOpen = 0;
|
|
1749
|
+
let issuesStalled = 0;
|
|
1750
|
+
let commentsTotal = 0;
|
|
1751
|
+
const now = Date.now();
|
|
1752
|
+
const stallThresholdMs = 14 * 24 * 60 * 60 * 1e3;
|
|
1753
|
+
for (const issue of rawIssues) {
|
|
1754
|
+
const created = new Date(issue.createdAt);
|
|
1755
|
+
const updated = new Date(issue.updatedAt);
|
|
1756
|
+
const completed = issue.completedAt ? new Date(issue.completedAt) : null;
|
|
1757
|
+
const assigneeId = issue.assignee?.id ?? "unassigned";
|
|
1758
|
+
if (assigneeId !== "unassigned") assignees.add(assigneeId);
|
|
1759
|
+
if (issue.project) {
|
|
1760
|
+
projects.set(issue.project.name, (projects.get(issue.project.name) ?? 0) + 1);
|
|
1761
|
+
}
|
|
1762
|
+
const actor = {
|
|
1763
|
+
id: assigneeId,
|
|
1764
|
+
kind: "human",
|
|
1765
|
+
name: issue.assignee?.name ?? "unassigned"
|
|
1766
|
+
};
|
|
1767
|
+
if (created >= since) {
|
|
1768
|
+
issuesCreated++;
|
|
1769
|
+
events.push({
|
|
1770
|
+
id: `linear-created-${issue.id}`,
|
|
1771
|
+
timestamp: issue.createdAt,
|
|
1772
|
+
actor: {
|
|
1773
|
+
id: issue.creator?.id ?? "unknown",
|
|
1774
|
+
kind: "human",
|
|
1775
|
+
name: issue.creator?.name ?? "unknown"
|
|
1776
|
+
},
|
|
1777
|
+
kind: "issue_created",
|
|
1778
|
+
content: `[${issue.identifier}] ${issue.title}`,
|
|
1779
|
+
metadata: {
|
|
1780
|
+
issueId: issue.id,
|
|
1781
|
+
url: issue.url,
|
|
1782
|
+
team: issue.team?.name,
|
|
1783
|
+
project: issue.project?.name,
|
|
1784
|
+
state: issue.state?.name
|
|
1785
|
+
}
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
if (completed && completed >= since) {
|
|
1789
|
+
issuesCompleted++;
|
|
1790
|
+
events.push({
|
|
1791
|
+
id: `linear-completed-${issue.id}`,
|
|
1792
|
+
timestamp: issue.completedAt,
|
|
1793
|
+
actor,
|
|
1794
|
+
kind: "issue_completed",
|
|
1795
|
+
content: `[${issue.identifier}] ${issue.title}`,
|
|
1796
|
+
metadata: {
|
|
1797
|
+
issueId: issue.id,
|
|
1798
|
+
url: issue.url,
|
|
1799
|
+
team: issue.team?.name,
|
|
1800
|
+
project: issue.project?.name,
|
|
1801
|
+
cycleDays: issue.cycle?.startsAt && issue.completedAt ? Math.round(
|
|
1802
|
+
(new Date(issue.completedAt).getTime() - new Date(issue.cycle.startsAt).getTime()) / (24 * 60 * 60 * 1e3)
|
|
1803
|
+
) : null
|
|
1804
|
+
}
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
if (!completed && !issue.canceledAt) {
|
|
1808
|
+
issuesOpen++;
|
|
1809
|
+
const isInProgress = issue.state?.type === "started";
|
|
1810
|
+
const idleMs = now - updated.getTime();
|
|
1811
|
+
if (isInProgress && idleMs > stallThresholdMs) issuesStalled++;
|
|
1812
|
+
}
|
|
1813
|
+
for (const comment of issue.comments?.nodes ?? []) {
|
|
1814
|
+
const commentedAt = new Date(comment.createdAt);
|
|
1815
|
+
if (commentedAt < since) continue;
|
|
1816
|
+
commentsTotal++;
|
|
1817
|
+
events.push({
|
|
1818
|
+
id: `linear-comment-${comment.id}`,
|
|
1819
|
+
timestamp: comment.createdAt,
|
|
1820
|
+
actor: {
|
|
1821
|
+
id: comment.user?.id ?? "unknown",
|
|
1822
|
+
kind: "human",
|
|
1823
|
+
name: comment.user?.name ?? "unknown"
|
|
1824
|
+
},
|
|
1825
|
+
kind: "issue_comment",
|
|
1826
|
+
content: comment.body.slice(0, 280),
|
|
1827
|
+
metadata: {
|
|
1828
|
+
issueId: issue.id,
|
|
1829
|
+
issueIdentifier: issue.identifier,
|
|
1830
|
+
url: issue.url
|
|
1831
|
+
}
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
let cycleCompletionRate = null;
|
|
1836
|
+
if (rawCycles.length > 0) {
|
|
1837
|
+
const rates = [];
|
|
1838
|
+
for (const cycle of rawCycles) {
|
|
1839
|
+
const committed = cycle.issueCountHistory?.at(0) ?? 0;
|
|
1840
|
+
const completed = cycle.completedIssueCountHistory?.at(-1) ?? 0;
|
|
1841
|
+
if (committed > 0) rates.push(completed / committed);
|
|
1842
|
+
}
|
|
1843
|
+
if (rates.length > 0) {
|
|
1844
|
+
cycleCompletionRate = Math.round(rates.reduce((a, b) => a + b, 0) / rates.length * 100) / 100;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
const topProjects = [...projects.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([name]) => name);
|
|
1848
|
+
const signals = {
|
|
1849
|
+
issuesCreated,
|
|
1850
|
+
issuesCompleted,
|
|
1851
|
+
issuesOpen,
|
|
1852
|
+
issuesStalled,
|
|
1853
|
+
cycleCompletionRate,
|
|
1854
|
+
uniqueAssignees: assignees.size,
|
|
1855
|
+
commentsTotal,
|
|
1856
|
+
topProjects
|
|
1857
|
+
};
|
|
1858
|
+
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1859
|
+
return { events, signals };
|
|
1860
|
+
}
|
|
1861
|
+
function formatLinearSignalsForPrompt(signals) {
|
|
1862
|
+
if (signals.issuesCreated === 0 && signals.issuesCompleted === 0 && signals.issuesOpen === 0) {
|
|
1863
|
+
return "";
|
|
1864
|
+
}
|
|
1865
|
+
const lines = [
|
|
1866
|
+
"## Linear Activity (planned work vs. shipped outcome)",
|
|
1867
|
+
"",
|
|
1868
|
+
`${signals.issuesCreated} issues created, ${signals.issuesCompleted} completed in window.`,
|
|
1869
|
+
`${signals.issuesOpen} issues still open.`
|
|
1870
|
+
];
|
|
1871
|
+
if (signals.issuesStalled > 0) {
|
|
1872
|
+
lines.push(
|
|
1873
|
+
`${signals.issuesStalled} in-progress issues haven't moved in 14+ days (stalled).`
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
if (signals.cycleCompletionRate !== null) {
|
|
1877
|
+
const pct = Math.round(signals.cycleCompletionRate * 100);
|
|
1878
|
+
lines.push(`Cycles ended in window completed ${pct}% of what was committed.`);
|
|
1879
|
+
}
|
|
1880
|
+
if (signals.uniqueAssignees > 0) {
|
|
1881
|
+
lines.push(`${signals.uniqueAssignees} unique assignees active.`);
|
|
1882
|
+
}
|
|
1883
|
+
if (signals.commentsTotal > 0) {
|
|
1884
|
+
lines.push(`${signals.commentsTotal} comments across issues in window.`);
|
|
1885
|
+
}
|
|
1886
|
+
if (signals.topProjects.length > 0) {
|
|
1887
|
+
lines.push(`Most active projects: ${signals.topProjects.join(", ")}.`);
|
|
1888
|
+
}
|
|
1889
|
+
lines.push("");
|
|
1890
|
+
lines.push("Linear is where the team states what it will build.");
|
|
1891
|
+
lines.push("GitHub is where the team reveals what actually got built.");
|
|
1892
|
+
lines.push("Low completion rate + high creation rate = planning faster than shipping.");
|
|
1893
|
+
lines.push("High stalled count = commitments made but not honored.");
|
|
1894
|
+
lines.push("Compare Linear signals against GitHub to find the stated-vs-shipped gap.");
|
|
1895
|
+
return lines.join("\n");
|
|
1896
|
+
}
|
|
1897
|
+
async function fetchLinearGraphQL(apiKey, query, variables) {
|
|
1898
|
+
const res = await fetch("https://api.linear.app/graphql", {
|
|
1899
|
+
method: "POST",
|
|
1900
|
+
headers: {
|
|
1901
|
+
// Linear accepts the raw API key in Authorization with no "Bearer" prefix.
|
|
1902
|
+
Authorization: apiKey,
|
|
1903
|
+
"Content-Type": "application/json"
|
|
1904
|
+
},
|
|
1905
|
+
body: JSON.stringify({ query, variables })
|
|
1906
|
+
});
|
|
1907
|
+
if (!res.ok) {
|
|
1908
|
+
throw new Error(
|
|
1909
|
+
`Linear API error ${res.status}: ${(await res.text()).slice(0, 300)}`
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
const json = await res.json();
|
|
1913
|
+
if (json.errors && json.errors.length > 0) {
|
|
1914
|
+
throw new Error(
|
|
1915
|
+
`Linear GraphQL errors: ${json.errors.map((e) => e.message).join("; ")}`
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
if (!json.data) {
|
|
1919
|
+
throw new Error("Linear API returned no data");
|
|
1920
|
+
}
|
|
1921
|
+
return json.data;
|
|
1922
|
+
}
|
|
1923
|
+
var init_linear = __esm({
|
|
1924
|
+
"src/radiant/adapters/linear.ts"() {
|
|
1925
|
+
"use strict";
|
|
1926
|
+
}
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1673
1929
|
// src/radiant/core/git-remote.ts
|
|
1674
1930
|
function resolveGitConfigPath(repoDir) {
|
|
1675
1931
|
const dotGit = (0, import_path.join)(repoDir, ".git");
|
|
@@ -2557,6 +2813,24 @@ function isExternalScope(scope) {
|
|
|
2557
2813
|
return !internalPatterns.some((p) => p.test(scope));
|
|
2558
2814
|
}
|
|
2559
2815
|
function evaluateGuard(event, world, options = {}) {
|
|
2816
|
+
const verdict = evaluateGuardCore(event, world, options);
|
|
2817
|
+
return options.mode === "observe" ? toShadowVerdict(verdict) : verdict;
|
|
2818
|
+
}
|
|
2819
|
+
function toShadowVerdict(verdict) {
|
|
2820
|
+
if (verdict.status === "ALLOW") return verdict;
|
|
2821
|
+
return {
|
|
2822
|
+
...verdict,
|
|
2823
|
+
status: "ALLOW",
|
|
2824
|
+
shadowStatus: verdict.status,
|
|
2825
|
+
shadowReason: verdict.reason,
|
|
2826
|
+
// Preserve the original reason as shadowReason and wipe the
|
|
2827
|
+
// top-level reason so callers that display `reason` for BLOCK/PAUSE
|
|
2828
|
+
// don't accidentally surface an enforcement message.
|
|
2829
|
+
reason: void 0,
|
|
2830
|
+
warning: verdict.reason ? `Observe mode: would have ${verdict.status.toLowerCase()} \u2014 ${verdict.reason}` : `Observe mode: would have ${verdict.status.toLowerCase()}`
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
function evaluateGuardCore(event, world, options = {}) {
|
|
2560
2834
|
const startTime = performance.now();
|
|
2561
2835
|
const level = options.level ?? "standard";
|
|
2562
2836
|
const includeTrace = options.trace ?? false;
|
|
@@ -3523,6 +3797,7 @@ async function auditGovernance(events, worldPath) {
|
|
|
3523
3797
|
return emptyAudit(events.length, "Could not load compiled worldmodel for governance audit.");
|
|
3524
3798
|
}
|
|
3525
3799
|
const verdicts = [];
|
|
3800
|
+
const crossings = [];
|
|
3526
3801
|
for (const ce of events) {
|
|
3527
3802
|
const intent = ce.event.content?.slice(0, 500) || ce.event.kind || "activity";
|
|
3528
3803
|
const scope = ce.event.metadata?.scope || void 0;
|
|
@@ -3533,16 +3808,32 @@ async function auditGovernance(events, worldPath) {
|
|
|
3533
3808
|
scope,
|
|
3534
3809
|
actionCategory: mapKindToCategory(ce.event.kind)
|
|
3535
3810
|
},
|
|
3536
|
-
world
|
|
3811
|
+
world,
|
|
3812
|
+
{ mode: "observe" }
|
|
3537
3813
|
);
|
|
3814
|
+
const shadow = result.shadowStatus ?? "ALLOW";
|
|
3538
3815
|
verdicts.push({
|
|
3539
3816
|
eventId: ce.event.id,
|
|
3540
3817
|
domain: ce.domain,
|
|
3541
|
-
status:
|
|
3542
|
-
reason: result.
|
|
3818
|
+
status: shadow,
|
|
3819
|
+
reason: result.shadowReason,
|
|
3543
3820
|
ruleId: result.ruleId,
|
|
3544
3821
|
warning: result.warning
|
|
3545
3822
|
});
|
|
3823
|
+
if (shadow !== "ALLOW") {
|
|
3824
|
+
crossings.push({
|
|
3825
|
+
eventId: ce.event.id,
|
|
3826
|
+
timestamp: ce.event.timestamp,
|
|
3827
|
+
kind: ce.event.kind,
|
|
3828
|
+
actorId: ce.event.actor.id,
|
|
3829
|
+
shadowStatus: shadow,
|
|
3830
|
+
shadowReason: result.shadowReason,
|
|
3831
|
+
ruleId: result.ruleId,
|
|
3832
|
+
excerpt: intent.length > 280 ? intent.slice(0, 279) + "\u2026" : intent,
|
|
3833
|
+
wouldHaveBlocked: true,
|
|
3834
|
+
verdict: result
|
|
3835
|
+
});
|
|
3836
|
+
}
|
|
3546
3837
|
} catch {
|
|
3547
3838
|
verdicts.push({
|
|
3548
3839
|
eventId: ce.event.id,
|
|
@@ -3561,6 +3852,7 @@ async function auditGovernance(events, worldPath) {
|
|
|
3561
3852
|
human,
|
|
3562
3853
|
cyber,
|
|
3563
3854
|
joint,
|
|
3855
|
+
crossings,
|
|
3564
3856
|
summary
|
|
3565
3857
|
};
|
|
3566
3858
|
}
|
|
@@ -3616,6 +3908,7 @@ function emptyAudit(total, reason) {
|
|
|
3616
3908
|
human: { allow: 0, modify: 0, block: 0, details: [] },
|
|
3617
3909
|
cyber: { allow: 0, modify: 0, block: 0, details: [] },
|
|
3618
3910
|
joint: { allow: 0, modify: 0, block: 0, details: [] },
|
|
3911
|
+
crossings: [],
|
|
3619
3912
|
summary: reason
|
|
3620
3913
|
};
|
|
3621
3914
|
}
|
|
@@ -3799,6 +4092,144 @@ var init_signals = __esm({
|
|
|
3799
4092
|
}
|
|
3800
4093
|
});
|
|
3801
4094
|
|
|
4095
|
+
// src/radiant/core/vocabulary.ts
|
|
4096
|
+
function extractDeclaredVocabulary(worldmodelContent) {
|
|
4097
|
+
const aligned = extractSection(worldmodelContent, "Aligned Behaviors").map(
|
|
4098
|
+
(b) => parseBehavior(b, "aligned")
|
|
4099
|
+
);
|
|
4100
|
+
const drift = extractSection(worldmodelContent, "Drift Behaviors").map(
|
|
4101
|
+
(b) => parseBehavior(b, "drift")
|
|
4102
|
+
);
|
|
4103
|
+
const allNames = [...aligned, ...drift].map((p) => p.name);
|
|
4104
|
+
return { aligned, drift, allNames };
|
|
4105
|
+
}
|
|
4106
|
+
function extractSection(content, header) {
|
|
4107
|
+
const escaped = header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4108
|
+
const pattern = new RegExp(
|
|
4109
|
+
`##\\s+${escaped}\\s*\\n([\\s\\S]*?)(?=\\n##\\s|$)`,
|
|
4110
|
+
"i"
|
|
4111
|
+
);
|
|
4112
|
+
const match = content.match(pattern);
|
|
4113
|
+
if (!match) return [];
|
|
4114
|
+
const body = match[1];
|
|
4115
|
+
const bullets = body.match(/^[-*]\s+.+$/gm);
|
|
4116
|
+
if (!bullets) return [];
|
|
4117
|
+
return bullets.map((b) => b.replace(/^[-*]\s+/, "").trim()).filter((b) => b.length > 0 && !b.startsWith("<!--"));
|
|
4118
|
+
}
|
|
4119
|
+
function parseBehavior(bullet, kind) {
|
|
4120
|
+
const explicit = bullet.match(
|
|
4121
|
+
/^`?([a-z][a-z0-9_]*)`?\s+[—\u2014-]\s+(.+)$/i
|
|
4122
|
+
);
|
|
4123
|
+
if (explicit && isSnakeCase(explicit[1])) {
|
|
4124
|
+
return {
|
|
4125
|
+
name: explicit[1].toLowerCase(),
|
|
4126
|
+
prose: explicit[2].trim(),
|
|
4127
|
+
kind
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
return { name: snakeCaseName(bullet), prose: bullet, kind };
|
|
4131
|
+
}
|
|
4132
|
+
function isSnakeCase(s) {
|
|
4133
|
+
return /^[a-z][a-z0-9_]*$/.test(s);
|
|
4134
|
+
}
|
|
4135
|
+
function snakeCaseName(s) {
|
|
4136
|
+
const base = s.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
4137
|
+
if (base.length <= 60) return base;
|
|
4138
|
+
const truncated = base.slice(0, 60);
|
|
4139
|
+
const lastUnderscore = truncated.lastIndexOf("_");
|
|
4140
|
+
return lastUnderscore > 20 ? truncated.slice(0, lastUnderscore) : truncated;
|
|
4141
|
+
}
|
|
4142
|
+
function matchDeclaredPattern(candidateName, candidateDescription, vocabulary) {
|
|
4143
|
+
const candidateText = `${candidateName.replace(/_/g, " ")} ${candidateDescription}`;
|
|
4144
|
+
const candidateWords = contentWords(candidateText);
|
|
4145
|
+
if (candidateWords.size === 0) return null;
|
|
4146
|
+
let best = null;
|
|
4147
|
+
for (const pattern of [...vocabulary.aligned, ...vocabulary.drift]) {
|
|
4148
|
+
const proseWords = contentWords(pattern.prose);
|
|
4149
|
+
if (proseWords.size === 0) continue;
|
|
4150
|
+
let shared = 0;
|
|
4151
|
+
for (const w of proseWords) {
|
|
4152
|
+
if (candidateWords.has(w)) shared++;
|
|
4153
|
+
}
|
|
4154
|
+
const coverage = shared / proseWords.size;
|
|
4155
|
+
if (shared >= 2 && coverage >= 0.3) {
|
|
4156
|
+
if (!best || coverage > best.score) {
|
|
4157
|
+
best = { pattern, score: coverage };
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
return best?.pattern ?? null;
|
|
4162
|
+
}
|
|
4163
|
+
function contentWords(text) {
|
|
4164
|
+
const words = text.toLowerCase().match(/[a-z][a-z0-9_]+/g) ?? [];
|
|
4165
|
+
return new Set(words.filter((w) => w.length > 3 && !STOPWORDS.has(w)));
|
|
4166
|
+
}
|
|
4167
|
+
var STOPWORDS;
|
|
4168
|
+
var init_vocabulary = __esm({
|
|
4169
|
+
"src/radiant/core/vocabulary.ts"() {
|
|
4170
|
+
"use strict";
|
|
4171
|
+
STOPWORDS = /* @__PURE__ */ new Set([
|
|
4172
|
+
"about",
|
|
4173
|
+
"after",
|
|
4174
|
+
"against",
|
|
4175
|
+
"among",
|
|
4176
|
+
"around",
|
|
4177
|
+
"because",
|
|
4178
|
+
"been",
|
|
4179
|
+
"before",
|
|
4180
|
+
"being",
|
|
4181
|
+
"between",
|
|
4182
|
+
"both",
|
|
4183
|
+
"could",
|
|
4184
|
+
"does",
|
|
4185
|
+
"doing",
|
|
4186
|
+
"during",
|
|
4187
|
+
"each",
|
|
4188
|
+
"from",
|
|
4189
|
+
"further",
|
|
4190
|
+
"have",
|
|
4191
|
+
"having",
|
|
4192
|
+
"into",
|
|
4193
|
+
"itself",
|
|
4194
|
+
"most",
|
|
4195
|
+
"nor",
|
|
4196
|
+
"only",
|
|
4197
|
+
"other",
|
|
4198
|
+
"over",
|
|
4199
|
+
"same",
|
|
4200
|
+
"should",
|
|
4201
|
+
"some",
|
|
4202
|
+
"such",
|
|
4203
|
+
"than",
|
|
4204
|
+
"that",
|
|
4205
|
+
"their",
|
|
4206
|
+
"them",
|
|
4207
|
+
"then",
|
|
4208
|
+
"there",
|
|
4209
|
+
"these",
|
|
4210
|
+
"they",
|
|
4211
|
+
"this",
|
|
4212
|
+
"those",
|
|
4213
|
+
"through",
|
|
4214
|
+
"under",
|
|
4215
|
+
"until",
|
|
4216
|
+
"very",
|
|
4217
|
+
"were",
|
|
4218
|
+
"what",
|
|
4219
|
+
"when",
|
|
4220
|
+
"where",
|
|
4221
|
+
"which",
|
|
4222
|
+
"while",
|
|
4223
|
+
"will",
|
|
4224
|
+
"with",
|
|
4225
|
+
"without",
|
|
4226
|
+
"would",
|
|
4227
|
+
"your",
|
|
4228
|
+
"yours"
|
|
4229
|
+
]);
|
|
4230
|
+
}
|
|
4231
|
+
});
|
|
4232
|
+
|
|
3802
4233
|
// src/radiant/types.ts
|
|
3803
4234
|
function isScored(s) {
|
|
3804
4235
|
return typeof s === "number";
|
|
@@ -3850,7 +4281,11 @@ var init_math = __esm({
|
|
|
3850
4281
|
async function interpretPatterns(input) {
|
|
3851
4282
|
const prompt = buildInterpretationPrompt(input);
|
|
3852
4283
|
const raw = await input.ai.complete(prompt, "Analyze the activity and produce the read.");
|
|
3853
|
-
const
|
|
4284
|
+
const canonicalNames = [
|
|
4285
|
+
...input.canonicalPatterns ?? [],
|
|
4286
|
+
...input.declaredVocabulary?.allNames ?? []
|
|
4287
|
+
];
|
|
4288
|
+
const parsed = parseInterpretation(raw, canonicalNames, input.declaredVocabulary);
|
|
3854
4289
|
return {
|
|
3855
4290
|
patterns: parsed.patterns,
|
|
3856
4291
|
meaning: parsed.meaning,
|
|
@@ -3861,8 +4296,10 @@ async function interpretPatterns(input) {
|
|
|
3861
4296
|
function buildInterpretationPrompt(input) {
|
|
3862
4297
|
const signalSummary = formatSignalSummary(input.signals);
|
|
3863
4298
|
const eventSample = formatEventSample(input.events, 30);
|
|
3864
|
-
const canonicalList = (
|
|
3865
|
-
|
|
4299
|
+
const canonicalList = formatDeclaredVocabulary(
|
|
4300
|
+
input.declaredVocabulary,
|
|
4301
|
+
input.canonicalPatterns ?? []
|
|
4302
|
+
);
|
|
3866
4303
|
const compressedWorld = compressWorldmodel(input.worldmodelContent);
|
|
3867
4304
|
const cl = compressLens(input.lens);
|
|
3868
4305
|
const frame = input.lens.primary_frame;
|
|
@@ -3973,6 +4410,44 @@ Only recommend a move when the evidence actually calls for one.
|
|
|
3973
4410
|
Do NOT use these phrases anywhere in your output:
|
|
3974
4411
|
${forbiddenList}`;
|
|
3975
4412
|
}
|
|
4413
|
+
function formatDeclaredVocabulary(vocabulary, extraNames) {
|
|
4414
|
+
const aligned = vocabulary?.aligned ?? [];
|
|
4415
|
+
const drift = vocabulary?.drift ?? [];
|
|
4416
|
+
if (aligned.length === 0 && drift.length === 0 && extraNames.length === 0) {
|
|
4417
|
+
return 'No patterns have been named yet. Everything you observe is new \u2014 mark it type: "candidate".';
|
|
4418
|
+
}
|
|
4419
|
+
const parts = [];
|
|
4420
|
+
parts.push("## Declared vocabulary (use these names when you see matching evidence)");
|
|
4421
|
+
parts.push("");
|
|
4422
|
+
parts.push(
|
|
4423
|
+
'The worldmodel declares the patterns below. If your observation matches one of these, use the EXACT snake_case name shown and mark type: "canonical" \u2014 do not invent a new name for something that already has one.'
|
|
4424
|
+
);
|
|
4425
|
+
parts.push("");
|
|
4426
|
+
if (aligned.length > 0) {
|
|
4427
|
+
parts.push("### Aligned behaviors (positive patterns)");
|
|
4428
|
+
for (const p of aligned) {
|
|
4429
|
+
parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
|
|
4430
|
+
}
|
|
4431
|
+
parts.push("");
|
|
4432
|
+
}
|
|
4433
|
+
if (drift.length > 0) {
|
|
4434
|
+
parts.push("### Drift behaviors (negative patterns)");
|
|
4435
|
+
for (const p of drift) {
|
|
4436
|
+
parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
|
|
4437
|
+
}
|
|
4438
|
+
parts.push("");
|
|
4439
|
+
}
|
|
4440
|
+
if (extraNames.length > 0) {
|
|
4441
|
+
parts.push(
|
|
4442
|
+
`Additional canonical names (from prior runs or caller): ${extraNames.join(", ")}`
|
|
4443
|
+
);
|
|
4444
|
+
parts.push("");
|
|
4445
|
+
}
|
|
4446
|
+
parts.push(
|
|
4447
|
+
'If you observe something genuinely new that matches NO declared pattern, mark it type: "candidate" with a freshly-invented snake_case name.'
|
|
4448
|
+
);
|
|
4449
|
+
return parts.join("\n");
|
|
4450
|
+
}
|
|
3976
4451
|
function formatSignalSummary(signals) {
|
|
3977
4452
|
const lines = [];
|
|
3978
4453
|
const domains = ["life", "cyber", "joint"];
|
|
@@ -3998,7 +4473,7 @@ function formatEventSample(events, maxEvents) {
|
|
|
3998
4473
|
"${content}"`;
|
|
3999
4474
|
}).join("\n");
|
|
4000
4475
|
}
|
|
4001
|
-
function parseInterpretation(raw, canonicalNames) {
|
|
4476
|
+
function parseInterpretation(raw, canonicalNames, vocabulary) {
|
|
4002
4477
|
let meaning = "";
|
|
4003
4478
|
let move = "";
|
|
4004
4479
|
let patternsArray = [];
|
|
@@ -4028,14 +4503,23 @@ function parseInterpretation(raw, canonicalNames) {
|
|
|
4028
4503
|
const patterns = [];
|
|
4029
4504
|
for (const item of patternsArray) {
|
|
4030
4505
|
if (!isPatternLike(item)) continue;
|
|
4031
|
-
const
|
|
4506
|
+
const rawName = String(item.name ?? "unnamed");
|
|
4507
|
+
const description = String(item.description ?? "");
|
|
4032
4508
|
const ev = item.evidence;
|
|
4033
|
-
|
|
4509
|
+
let name = rawName;
|
|
4510
|
+
let isCanonical = item.type === "canonical" || canonicalSet.has(rawName.toLowerCase());
|
|
4511
|
+
if (!isCanonical && vocabulary) {
|
|
4512
|
+
const matched = matchDeclaredPattern(rawName, description, vocabulary);
|
|
4513
|
+
if (matched) {
|
|
4514
|
+
name = matched.name;
|
|
4515
|
+
isCanonical = true;
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4034
4518
|
patterns.push({
|
|
4035
|
-
name
|
|
4519
|
+
name,
|
|
4036
4520
|
type: isCanonical ? "canonical" : "candidate",
|
|
4037
|
-
declaredAs: isCanonical ?
|
|
4038
|
-
description
|
|
4521
|
+
declaredAs: isCanonical ? name : void 0,
|
|
4522
|
+
description,
|
|
4039
4523
|
evidence: {
|
|
4040
4524
|
signals: Array.isArray(ev?.signals) ? ev.signals.map(String) : [],
|
|
4041
4525
|
events: Array.isArray(ev?.events) ? ev.events.map(String) : [],
|
|
@@ -4053,6 +4537,7 @@ var init_patterns = __esm({
|
|
|
4053
4537
|
"src/radiant/core/patterns.ts"() {
|
|
4054
4538
|
"use strict";
|
|
4055
4539
|
init_compress();
|
|
4540
|
+
init_vocabulary();
|
|
4056
4541
|
}
|
|
4057
4542
|
});
|
|
4058
4543
|
|
|
@@ -4371,10 +4856,24 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4371
4856
|
} catch {
|
|
4372
4857
|
}
|
|
4373
4858
|
}
|
|
4859
|
+
const linearKey = process.env.LINEAR_API_KEY;
|
|
4860
|
+
if (linearKey) {
|
|
4861
|
+
try {
|
|
4862
|
+
const linear = await fetchLinearActivity(linearKey, { windowDays });
|
|
4863
|
+
events.push(...linear.events);
|
|
4864
|
+
adapterSignals += "\n\n" + formatLinearSignalsForPrompt(linear.signals);
|
|
4865
|
+
activeAdapters.push("linear");
|
|
4866
|
+
} catch {
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4374
4869
|
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
4870
|
+
if (input.personalUser) {
|
|
4871
|
+
events = filterEventsByUser(events, input.personalUser);
|
|
4872
|
+
}
|
|
4375
4873
|
const classified = classifyEvents(events);
|
|
4376
4874
|
const signals = extractSignals(classified);
|
|
4377
4875
|
const scores = computeScores(signals, input.worldmodelContent !== "");
|
|
4876
|
+
const declaredVocabulary = extractDeclaredVocabulary(worldmodelContent);
|
|
4378
4877
|
const { patterns, meaning, move } = await interpretPatterns({
|
|
4379
4878
|
signals,
|
|
4380
4879
|
events: classified,
|
|
@@ -4382,6 +4881,7 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4382
4881
|
lens,
|
|
4383
4882
|
ai: input.ai,
|
|
4384
4883
|
canonicalPatterns: input.canonicalPatterns,
|
|
4884
|
+
declaredVocabulary,
|
|
4385
4885
|
statedIntent: [statedIntent, adapterSignals, priorReadContext].filter(Boolean).join("\n\n") || void 0
|
|
4386
4886
|
});
|
|
4387
4887
|
const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
|
|
@@ -4433,9 +4933,14 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4433
4933
|
scores,
|
|
4434
4934
|
eventCount: events.length,
|
|
4435
4935
|
activeAdapters,
|
|
4436
|
-
worldStack
|
|
4936
|
+
worldStack,
|
|
4937
|
+
governance
|
|
4437
4938
|
};
|
|
4438
4939
|
}
|
|
4940
|
+
function filterEventsByUser(events, username) {
|
|
4941
|
+
const target = username.toLowerCase();
|
|
4942
|
+
return events.filter((e) => e.actor.id.toLowerCase() === target);
|
|
4943
|
+
}
|
|
4439
4944
|
function computeScores(signals, worldmodelLoaded) {
|
|
4440
4945
|
const gate = DEFAULT_EVIDENCE_GATE;
|
|
4441
4946
|
const lifeSignals = signals.filter((s) => s.domain === "life");
|
|
@@ -4491,12 +4996,14 @@ var init_emergent = __esm({
|
|
|
4491
4996
|
init_discord();
|
|
4492
4997
|
init_slack();
|
|
4493
4998
|
init_notion();
|
|
4999
|
+
init_linear();
|
|
4494
5000
|
init_discovery();
|
|
4495
5001
|
init_exocortex();
|
|
4496
5002
|
init_palace();
|
|
4497
5003
|
init_compress();
|
|
4498
5004
|
init_governance();
|
|
4499
5005
|
init_signals();
|
|
5006
|
+
init_vocabulary();
|
|
4500
5007
|
init_math();
|
|
4501
5008
|
init_patterns();
|
|
4502
5009
|
init_renderer();
|
|
@@ -4818,7 +5325,9 @@ var init_server = __esm({
|
|
|
4818
5325
|
// src/cli/radiant.ts
|
|
4819
5326
|
var radiant_exports = {};
|
|
4820
5327
|
__export(radiant_exports, {
|
|
4821
|
-
|
|
5328
|
+
checkScopeConsent: () => checkScopeConsent,
|
|
5329
|
+
main: () => main,
|
|
5330
|
+
parseArgs: () => parseArgs
|
|
4822
5331
|
});
|
|
4823
5332
|
module.exports = __toCommonJS(radiant_exports);
|
|
4824
5333
|
var import_fs7 = require("fs");
|
|
@@ -4831,6 +5340,7 @@ init_exocortex();
|
|
|
4831
5340
|
init_lenses();
|
|
4832
5341
|
init_discovery();
|
|
4833
5342
|
var RED = "\x1B[31m";
|
|
5343
|
+
var GREEN = "\x1B[32m";
|
|
4834
5344
|
var DIM = "\x1B[2m";
|
|
4835
5345
|
var BOLD = "\x1B[1m";
|
|
4836
5346
|
var YELLOW = "\x1B[33m";
|
|
@@ -4838,6 +5348,9 @@ var RESET = "\x1B[0m";
|
|
|
4838
5348
|
var USAGE = `
|
|
4839
5349
|
${BOLD}neuroverse radiant${RESET} \u2014 behavioral intelligence for collaboration systems
|
|
4840
5350
|
|
|
5351
|
+
${BOLD}Setup:${RESET}
|
|
5352
|
+
init Scaffold a Mind Palace in the current directory
|
|
5353
|
+
|
|
4841
5354
|
${BOLD}Stage A (voice layer):${RESET}
|
|
4842
5355
|
think Send a query through the worldmodel + lens \u2192 AI-framed response
|
|
4843
5356
|
|
|
@@ -4848,13 +5361,27 @@ ${BOLD}Stage B (behavioral analysis, coming soon):${RESET}
|
|
|
4848
5361
|
lenses List or describe available rendering lenses
|
|
4849
5362
|
|
|
4850
5363
|
${BOLD}Usage:${RESET}
|
|
5364
|
+
neuroverse radiant init (scaffolds ./mind-palace/)
|
|
5365
|
+
neuroverse radiant init ./my-palace (custom path)
|
|
4851
5366
|
neuroverse radiant think --lens auki-builder --worlds ./worlds/ --query "What is our biggest risk?"
|
|
4852
5367
|
neuroverse radiant think --lens auki-builder --worlds ./worlds/ < prompt.txt
|
|
4853
5368
|
neuroverse radiant emergent aukiverse/posemesh --lens auki-builder --worlds ./worlds/
|
|
4854
5369
|
neuroverse radiant emergent aukiverse/posemesh --lens auki-builder --worlds ./worlds/ --exocortex ~/exocortex/
|
|
5370
|
+
neuroverse radiant emergent aukilabs/posemesh --personal --user alice
|
|
5371
|
+
neuroverse radiant emergent aukilabs/ --entire-org --lens auki-builder --worlds ./worlds/
|
|
4855
5372
|
neuroverse radiant lenses list
|
|
4856
5373
|
neuroverse radiant lenses describe auki-builder
|
|
4857
5374
|
|
|
5375
|
+
${BOLD}Read modes:${RESET}
|
|
5376
|
+
${BOLD}Default (team):${RESET} reads all contributors in the given scope.
|
|
5377
|
+
${BOLD}--personal --user <login>:${RESET} reads ONLY that user's activity.
|
|
5378
|
+
A local, private facilitator \u2014 no one else is observed. Works against
|
|
5379
|
+
any scope; an org scope with --personal is fine.
|
|
5380
|
+
${BOLD}--entire-org (gated):${RESET} org-wide scope observes every contributor
|
|
5381
|
+
across every repo. This is a global-observer stance and is opt-in.
|
|
5382
|
+
\`radiant emergent <org>/\` without --entire-org will refuse and show
|
|
5383
|
+
you the three choices (single repo, --personal, or explicit opt-in).
|
|
5384
|
+
|
|
4858
5385
|
${BOLD}Auto-discovery:${RESET}
|
|
4859
5386
|
You do not need to clone the target repo.
|
|
4860
5387
|
|
|
@@ -4873,6 +5400,7 @@ ${BOLD}Environment:${RESET}
|
|
|
4873
5400
|
RADIANT_LENS Default lens id (overridden by --lens)
|
|
4874
5401
|
RADIANT_MODEL AI model override (default: claude-sonnet-4-20250514)
|
|
4875
5402
|
RADIANT_EXOCORTEX Default exocortex directory (overridden by --exocortex)
|
|
5403
|
+
RADIANT_USER Default personal-mode user (overridden by --user)
|
|
4876
5404
|
`.trim();
|
|
4877
5405
|
function parseArgs(argv) {
|
|
4878
5406
|
const result = {
|
|
@@ -4884,8 +5412,12 @@ function parseArgs(argv) {
|
|
|
4884
5412
|
exocortex: void 0,
|
|
4885
5413
|
teamExocortex: void 0,
|
|
4886
5414
|
view: void 0,
|
|
5415
|
+
user: void 0,
|
|
5416
|
+
personal: false,
|
|
5417
|
+
entireOrg: false,
|
|
4887
5418
|
json: false,
|
|
4888
5419
|
help: false,
|
|
5420
|
+
force: false,
|
|
4889
5421
|
rest: []
|
|
4890
5422
|
};
|
|
4891
5423
|
let i = 0;
|
|
@@ -4917,9 +5449,22 @@ function parseArgs(argv) {
|
|
|
4917
5449
|
case "--view":
|
|
4918
5450
|
result.view = argv[++i];
|
|
4919
5451
|
break;
|
|
5452
|
+
case "--user":
|
|
5453
|
+
result.user = argv[++i];
|
|
5454
|
+
break;
|
|
5455
|
+
case "--personal":
|
|
5456
|
+
result.personal = true;
|
|
5457
|
+
break;
|
|
5458
|
+
case "--entire-org":
|
|
5459
|
+
result.entireOrg = true;
|
|
5460
|
+
break;
|
|
4920
5461
|
case "--json":
|
|
4921
5462
|
result.json = true;
|
|
4922
5463
|
break;
|
|
5464
|
+
case "--force":
|
|
5465
|
+
case "-f":
|
|
5466
|
+
result.force = true;
|
|
5467
|
+
break;
|
|
4923
5468
|
case "--help":
|
|
4924
5469
|
case "-h":
|
|
4925
5470
|
result.help = true;
|
|
@@ -5077,6 +5622,15 @@ ${DIM}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET}
|
|
|
5077
5622
|
process.exit(2);
|
|
5078
5623
|
}
|
|
5079
5624
|
}
|
|
5625
|
+
function checkScopeConsent(input) {
|
|
5626
|
+
if (input.personal && !input.resolvedUser) {
|
|
5627
|
+
return { ok: false, reason: "personal_requires_user" };
|
|
5628
|
+
}
|
|
5629
|
+
if (input.scope.type === "org" && !input.entireOrg && !input.personal) {
|
|
5630
|
+
return { ok: false, reason: "org_requires_opt_in" };
|
|
5631
|
+
}
|
|
5632
|
+
return { ok: true };
|
|
5633
|
+
}
|
|
5080
5634
|
async function cmdEmergent(args) {
|
|
5081
5635
|
const scopeStr = args.rest[0];
|
|
5082
5636
|
if (!scopeStr) {
|
|
@@ -5087,6 +5641,43 @@ async function cmdEmergent(args) {
|
|
|
5087
5641
|
process.exit(1);
|
|
5088
5642
|
}
|
|
5089
5643
|
const scope = parseScope(scopeStr);
|
|
5644
|
+
const personalUser = args.user ?? process.env.RADIANT_USER;
|
|
5645
|
+
const consent = checkScopeConsent({
|
|
5646
|
+
scope,
|
|
5647
|
+
personal: args.personal,
|
|
5648
|
+
entireOrg: args.entireOrg,
|
|
5649
|
+
resolvedUser: personalUser
|
|
5650
|
+
});
|
|
5651
|
+
if (!consent.ok) {
|
|
5652
|
+
if (consent.reason === "personal_requires_user") {
|
|
5653
|
+
process.stderr.write(
|
|
5654
|
+
`${RED}Error:${RESET} --personal requires a GitHub username.
|
|
5655
|
+
${DIM}Pass --user <login> or set RADIANT_USER. Radiant will read
|
|
5656
|
+
only that user's activity \u2014 no one else is observed.${RESET}
|
|
5657
|
+
`
|
|
5658
|
+
);
|
|
5659
|
+
} else {
|
|
5660
|
+
process.stderr.write(
|
|
5661
|
+
`${YELLOW}\u26A0${RESET} ${BOLD}"${scope.owner}" is an org-wide scope.${RESET}
|
|
5662
|
+
|
|
5663
|
+
${DIM}This reads activity across ALL repos in the org \u2014 a global-observer
|
|
5664
|
+
pattern that some teams consider offside with decentralization and
|
|
5665
|
+
cognitive-liberty principles. It's opt-in for that reason.${RESET}
|
|
5666
|
+
|
|
5667
|
+
Three ways forward:
|
|
5668
|
+
${GREEN}1.${RESET} Scope to a single repo (recommended default):
|
|
5669
|
+
radiant emergent ${scope.owner}/<repo>
|
|
5670
|
+
|
|
5671
|
+
${GREEN}2.${RESET} Read only your own activity (personal mode):
|
|
5672
|
+
radiant emergent ${scope.owner}/ --personal --user <your-login>
|
|
5673
|
+
|
|
5674
|
+
${GREEN}3.${RESET} Explicitly opt in to org-wide observation:
|
|
5675
|
+
radiant emergent ${scope.owner}/ --entire-org
|
|
5676
|
+
`
|
|
5677
|
+
);
|
|
5678
|
+
}
|
|
5679
|
+
process.exit(1);
|
|
5680
|
+
}
|
|
5090
5681
|
const lensId = args.lens ?? process.env.RADIANT_LENS;
|
|
5091
5682
|
if (!lensId) {
|
|
5092
5683
|
process.stderr.write(
|
|
@@ -5135,8 +5726,11 @@ ${DIM}Set it to a GitHub PAT with repo read access.${RESET}
|
|
|
5135
5726
|
const ctx = readExocortex(exocortexPath);
|
|
5136
5727
|
exocortexStatus = summarizeExocortex(ctx);
|
|
5137
5728
|
}
|
|
5729
|
+
const scopeLabel = scope.type === "org" ? scope.owner + " (entire org)" : scope.owner + "/" + scope.repo;
|
|
5730
|
+
const modeLabel = args.personal ? `personal \u2014 only ${personalUser}'s activity` : "team \u2014 all contributors";
|
|
5138
5731
|
process.stderr.write(
|
|
5139
|
-
`${DIM}Scope: ${
|
|
5732
|
+
`${DIM}Scope: ${scopeLabel}${RESET}
|
|
5733
|
+
${DIM}Mode: ${modeLabel}${RESET}
|
|
5140
5734
|
${DIM}View: ${view}${RESET}
|
|
5141
5735
|
${DIM}Lens: ${lensId}${RESET}
|
|
5142
5736
|
${DIM}Model: ${model ?? "claude-sonnet-4-20250514 (default)"}${RESET}
|
|
@@ -5152,7 +5746,8 @@ ${DIM}Fetching activity...${RESET}
|
|
|
5152
5746
|
lensId,
|
|
5153
5747
|
ai,
|
|
5154
5748
|
windowDays: 14,
|
|
5155
|
-
exocortexPath: exocortexPath || void 0
|
|
5749
|
+
exocortexPath: exocortexPath || void 0,
|
|
5750
|
+
personalUser: args.personal ? personalUser : void 0
|
|
5156
5751
|
});
|
|
5157
5752
|
if (!result.voiceClean) {
|
|
5158
5753
|
process.stderr.write(
|
|
@@ -5254,6 +5849,204 @@ ${DIM}Use: lenses list | lenses describe <id>${RESET}
|
|
|
5254
5849
|
);
|
|
5255
5850
|
process.exit(1);
|
|
5256
5851
|
}
|
|
5852
|
+
var MIND_PALACE_FILES = {
|
|
5853
|
+
"README.md": `# Mind Palace
|
|
5854
|
+
|
|
5855
|
+
This is your Mind Palace \u2014 structured external memory that gives Radiant
|
|
5856
|
+
(and any agent you wire into it) persistent context about who you are,
|
|
5857
|
+
what you're working on, and what "on track" means for you.
|
|
5858
|
+
|
|
5859
|
+
Radiant reads these files before every run and writes each read back into
|
|
5860
|
+
\`reads/\`. Over time, \`knowledge.md\` accumulates what's persisted and what
|
|
5861
|
+
hasn't \u2014 the feedback loop that turns raw activity into named behavior.
|
|
5862
|
+
|
|
5863
|
+
## Files
|
|
5864
|
+
|
|
5865
|
+
- \`attention.md\` \u2014 what you're focused on **right now**
|
|
5866
|
+
- \`goals.md\` \u2014 what you're working toward
|
|
5867
|
+
- \`sprint.md\` \u2014 this week's focus
|
|
5868
|
+
- \`identity.md\` \u2014 who you are, what you value
|
|
5869
|
+
- \`worldmodels/\` \u2014 your thinking constitutions (drift + aligned behaviors)
|
|
5870
|
+
- \`reads/\` \u2014 dated Radiant reads (written by \`radiant emergent\`)
|
|
5871
|
+
- \`knowledge.md\` \u2014 accumulated pattern persistence across reads
|
|
5872
|
+
|
|
5873
|
+
## How to use
|
|
5874
|
+
|
|
5875
|
+
1. Fill in \`attention.md\`, \`goals.md\`, \`sprint.md\`, \`identity.md\` with
|
|
5876
|
+
your own words. A sentence each is enough to start \u2014 the files grow
|
|
5877
|
+
with you.
|
|
5878
|
+
2. Edit \`worldmodels/starter.worldmodel.md\`: add a few aligned behaviors
|
|
5879
|
+
(what on-track looks like) and drift behaviors (what off-track looks
|
|
5880
|
+
like). The sharper these are, the sharper Radiant's reads.
|
|
5881
|
+
3. Run \`neuroverse radiant emergent <owner/repo> --mind-palace .\` against
|
|
5882
|
+
the repo you want read. Radiant compares your stated intent (these
|
|
5883
|
+
files) to your observed activity (GitHub) and names the gap.
|
|
5884
|
+
|
|
5885
|
+
Edit freely. These files are yours.
|
|
5886
|
+
`,
|
|
5887
|
+
"attention.md": `# Attention
|
|
5888
|
+
|
|
5889
|
+
<!--
|
|
5890
|
+
What are you focused on RIGHT NOW? One paragraph. Updated as you shift.
|
|
5891
|
+
This is the file an AI agent reads at the start of a session to know
|
|
5892
|
+
what to help with today.
|
|
5893
|
+
-->
|
|
5894
|
+
|
|
5895
|
+
`,
|
|
5896
|
+
"goals.md": `# Goals
|
|
5897
|
+
|
|
5898
|
+
<!--
|
|
5899
|
+
What are you working toward? Bullet points welcome.
|
|
5900
|
+
Longer horizon than attention \u2014 months, not days.
|
|
5901
|
+
-->
|
|
5902
|
+
|
|
5903
|
+
-
|
|
5904
|
+
`,
|
|
5905
|
+
"sprint.md": `# Sprint
|
|
5906
|
+
|
|
5907
|
+
<!--
|
|
5908
|
+
This week's focus. What do you want to ship or finish?
|
|
5909
|
+
Keep it short \u2014 five bullets max.
|
|
5910
|
+
-->
|
|
5911
|
+
|
|
5912
|
+
-
|
|
5913
|
+
`,
|
|
5914
|
+
"identity.md": `# Identity
|
|
5915
|
+
|
|
5916
|
+
<!--
|
|
5917
|
+
Who are you, what do you value, how do you work?
|
|
5918
|
+
This is the context an agent needs to not treat you like a stranger
|
|
5919
|
+
every time. Write it in your own voice.
|
|
5920
|
+
-->
|
|
5921
|
+
|
|
5922
|
+
`,
|
|
5923
|
+
"knowledge.md": `# Knowledge
|
|
5924
|
+
|
|
5925
|
+
<!--
|
|
5926
|
+
Radiant writes accumulated pattern persistence here across reads.
|
|
5927
|
+
Leave this file empty on day one \u2014 it fills up as \`radiant emergent\`
|
|
5928
|
+
runs accumulate.
|
|
5929
|
+
-->
|
|
5930
|
+
|
|
5931
|
+
`,
|
|
5932
|
+
"reads/.gitkeep": "",
|
|
5933
|
+
"worldmodels/starter.worldmodel.md": `# Starter Worldmodel
|
|
5934
|
+
|
|
5935
|
+
<!--
|
|
5936
|
+
Your thinking constitution. Radiant reads this to understand what
|
|
5937
|
+
"aligned" and "drift" mean for your work.
|
|
5938
|
+
|
|
5939
|
+
The sharper the Aligned/Drift Behaviors, the sharper Radiant's reads.
|
|
5940
|
+
When Radiant detects something matching a drift behavior below, it
|
|
5941
|
+
labels it with THAT name \u2014 it doesn't invent new ones.
|
|
5942
|
+
-->
|
|
5943
|
+
|
|
5944
|
+
## Mission
|
|
5945
|
+
|
|
5946
|
+
<!-- One sentence. What are you doing in the world? -->
|
|
5947
|
+
|
|
5948
|
+
|
|
5949
|
+
## Invariants
|
|
5950
|
+
|
|
5951
|
+
<!--
|
|
5952
|
+
Non-negotiable rules. If a decision violates one, it's blocked.
|
|
5953
|
+
Keep this list short \u2014 3 to 6 items. Each should be a hard no.
|
|
5954
|
+
-->
|
|
5955
|
+
|
|
5956
|
+
-
|
|
5957
|
+
|
|
5958
|
+
## Aligned Behaviors
|
|
5959
|
+
|
|
5960
|
+
<!--
|
|
5961
|
+
What "on track" looks like. One per line, phrased as a behavior.
|
|
5962
|
+
Radiant will use these as canonical pattern names when it sees
|
|
5963
|
+
matching evidence in your activity.
|
|
5964
|
+
|
|
5965
|
+
Example:
|
|
5966
|
+
- ships partial-but-working features rather than waiting for the full stack
|
|
5967
|
+
- writes decisions down before acting on them
|
|
5968
|
+
-->
|
|
5969
|
+
|
|
5970
|
+
-
|
|
5971
|
+
|
|
5972
|
+
## Drift Behaviors
|
|
5973
|
+
|
|
5974
|
+
<!--
|
|
5975
|
+
What "off track" looks like. Same format as Aligned.
|
|
5976
|
+
When Radiant detects drift, it will label it with these names \u2014 not
|
|
5977
|
+
make up new ones.
|
|
5978
|
+
|
|
5979
|
+
Example:
|
|
5980
|
+
- shipping pace outruns strategic decision-making
|
|
5981
|
+
- architecture decisions surface without context about why
|
|
5982
|
+
-->
|
|
5983
|
+
|
|
5984
|
+
-
|
|
5985
|
+
|
|
5986
|
+
## Signals
|
|
5987
|
+
|
|
5988
|
+
<!--
|
|
5989
|
+
Observable quantities you care about. Radiant scores activity
|
|
5990
|
+
against these \u2014 5 to 7 is the sweet spot.
|
|
5991
|
+
|
|
5992
|
+
Example:
|
|
5993
|
+
- shipping_velocity
|
|
5994
|
+
- decision_ownership
|
|
5995
|
+
- storytelling_cadence
|
|
5996
|
+
-->
|
|
5997
|
+
|
|
5998
|
+
-
|
|
5999
|
+
|
|
6000
|
+
## Decision Priorities
|
|
6001
|
+
|
|
6002
|
+
<!--
|
|
6003
|
+
When tradeoffs appear, these resolve them. Format: "A > B".
|
|
6004
|
+
|
|
6005
|
+
Example:
|
|
6006
|
+
- correctness > speed
|
|
6007
|
+
- clarity > cleverness
|
|
6008
|
+
-->
|
|
6009
|
+
|
|
6010
|
+
-
|
|
6011
|
+
`
|
|
6012
|
+
};
|
|
6013
|
+
async function cmdInit(args) {
|
|
6014
|
+
const targetDir = (0, import_path7.resolve)(args.rest[0] ?? "./mind-palace");
|
|
6015
|
+
const existed = (0, import_fs7.existsSync)(targetDir);
|
|
6016
|
+
if (existed && !args.force) {
|
|
6017
|
+
const entries = (0, import_fs7.readdirSync)(targetDir);
|
|
6018
|
+
if (entries.length > 0) {
|
|
6019
|
+
process.stderr.write(
|
|
6020
|
+
`${RED}Error:${RESET} ${targetDir} already exists and is not empty.
|
|
6021
|
+
${DIM}Use --force to write into it anyway (existing files will be overwritten).${RESET}
|
|
6022
|
+
`
|
|
6023
|
+
);
|
|
6024
|
+
process.exit(1);
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
(0, import_fs7.mkdirSync)(targetDir, { recursive: true });
|
|
6028
|
+
(0, import_fs7.mkdirSync)((0, import_path7.join)(targetDir, "reads"), { recursive: true });
|
|
6029
|
+
(0, import_fs7.mkdirSync)((0, import_path7.join)(targetDir, "worldmodels"), { recursive: true });
|
|
6030
|
+
for (const [relPath, content] of Object.entries(MIND_PALACE_FILES)) {
|
|
6031
|
+
const fullPath = (0, import_path7.join)(targetDir, relPath);
|
|
6032
|
+
(0, import_fs7.mkdirSync)((0, import_path7.resolve)(fullPath, ".."), { recursive: true });
|
|
6033
|
+
(0, import_fs7.writeFileSync)(fullPath, content, "utf-8");
|
|
6034
|
+
}
|
|
6035
|
+
process.stdout.write(
|
|
6036
|
+
`${GREEN}\u2713${RESET} Mind Palace scaffolded at ${BOLD}${targetDir}${RESET}
|
|
6037
|
+
|
|
6038
|
+
${DIM}Next steps:${RESET}
|
|
6039
|
+
1. Edit ${targetDir}/attention.md \u2014 what you're focused on right now
|
|
6040
|
+
2. Edit ${targetDir}/worldmodels/starter.worldmodel.md \u2014 add a few
|
|
6041
|
+
aligned and drift behaviors
|
|
6042
|
+
3. Run: neuroverse radiant emergent <owner/repo> \\
|
|
6043
|
+
--worlds ${targetDir}/worldmodels \\
|
|
6044
|
+
--exocortex ${targetDir}
|
|
6045
|
+
|
|
6046
|
+
${DIM}Files are yours. Edit freely.${RESET}
|
|
6047
|
+
`
|
|
6048
|
+
);
|
|
6049
|
+
}
|
|
5257
6050
|
async function main(argv) {
|
|
5258
6051
|
const args = parseArgs(argv);
|
|
5259
6052
|
if (args.help || !args.subcommand) {
|
|
@@ -5261,6 +6054,8 @@ async function main(argv) {
|
|
|
5261
6054
|
return;
|
|
5262
6055
|
}
|
|
5263
6056
|
switch (args.subcommand) {
|
|
6057
|
+
case "init":
|
|
6058
|
+
return cmdInit(args);
|
|
5264
6059
|
case "think":
|
|
5265
6060
|
return cmdThink(args);
|
|
5266
6061
|
case "lenses":
|
|
@@ -5293,5 +6088,7 @@ async function main(argv) {
|
|
|
5293
6088
|
}
|
|
5294
6089
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5295
6090
|
0 && (module.exports = {
|
|
5296
|
-
|
|
6091
|
+
checkScopeConsent,
|
|
6092
|
+
main,
|
|
6093
|
+
parseArgs
|
|
5297
6094
|
});
|