@neuroverseos/governance 0.8.1 → 0.10.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/AGENTS.md +8 -0
- package/README.md +120 -2
- package/dist/{chunk-ETDIEVAX.js → chunk-BZYQHJDM.js} +800 -54
- package/dist/{chunk-F2LWMOM5.js → chunk-TCGGED4G.js} +14 -14
- package/dist/cli/neuroverse.cjs +1362 -219
- package/dist/cli/radiant.cjs +1212 -116
- package/dist/cli/radiant.d.cts +44 -1
- package/dist/cli/radiant.d.ts +44 -1
- package/dist/cli/radiant.js +354 -28
- package/dist/cli/worldmodel.cjs +1055 -1000
- package/dist/cli/worldmodel.js +40 -0
- package/dist/{lenses-YDMKSXDL.js → lenses-XDWK6ZKI.js} +1 -1
- package/dist/radiant/index.cjs +826 -62
- package/dist/radiant/index.d.cts +304 -19
- package/dist/radiant/index.d.ts +304 -19
- package/dist/radiant/index.js +30 -2
- package/dist/{server-ZSQ6DRSN.js → server-EI5JCIBU.js} +2 -2
- package/examples/radiant-weekly-workflow.yml +84 -0
- package/package.json +2 -1
package/dist/radiant/index.cjs
CHANGED
|
@@ -48,35 +48,49 @@ __export(radiant_exports, {
|
|
|
48
48
|
createAnthropicAI: () => createAnthropicAI,
|
|
49
49
|
createMockAI: () => createMockAI,
|
|
50
50
|
createMockGitHubAdapter: () => createMockGitHubAdapter,
|
|
51
|
+
detectOrgExtendsSpec: () => detectOrgExtendsSpec,
|
|
51
52
|
discoverWorlds: () => discoverWorlds,
|
|
52
53
|
emergent: () => emergent,
|
|
54
|
+
extractDeclaredVocabulary: () => extractDeclaredVocabulary,
|
|
53
55
|
extractSignals: () => extractSignals,
|
|
54
56
|
fetchDiscordActivity: () => fetchDiscordActivity,
|
|
55
57
|
fetchGitHubActivity: () => fetchGitHubActivity,
|
|
56
58
|
fetchGitHubOrgActivity: () => fetchGitHubOrgActivity,
|
|
59
|
+
fetchLinearActivity: () => fetchLinearActivity,
|
|
57
60
|
fetchNotionActivity: () => fetchNotionActivity,
|
|
58
61
|
fetchSlackActivity: () => fetchSlackActivity,
|
|
62
|
+
filterEventsByUser: () => filterEventsByUser,
|
|
59
63
|
formatActiveWorlds: () => formatActiveWorlds,
|
|
60
64
|
formatDiscordSignalsForPrompt: () => formatDiscordSignalsForPrompt,
|
|
61
65
|
formatExocortexForPrompt: () => formatExocortexForPrompt,
|
|
66
|
+
formatLinearSignalsForPrompt: () => formatLinearSignalsForPrompt,
|
|
62
67
|
formatNotionSignalsForPrompt: () => formatNotionSignalsForPrompt,
|
|
63
68
|
formatPriorReadsForPrompt: () => formatPriorReadsForPrompt,
|
|
64
69
|
formatScope: () => formatScope,
|
|
65
70
|
formatSlackSignalsForPrompt: () => formatSlackSignalsForPrompt,
|
|
66
71
|
formatTeamExocorticesForPrompt: () => formatTeamExocorticesForPrompt,
|
|
72
|
+
getCacheDir: () => getCacheDir,
|
|
67
73
|
getLens: () => getLens,
|
|
74
|
+
getRepoOrigin: () => getRepoOrigin,
|
|
68
75
|
interpretPatterns: () => interpretPatterns,
|
|
69
76
|
isPresent: () => isPresent,
|
|
70
77
|
isScored: () => isScored,
|
|
71
78
|
isSentinel: () => isSentinel,
|
|
72
79
|
listLenses: () => listLenses,
|
|
80
|
+
loadExtendsConfig: () => loadExtendsConfig,
|
|
73
81
|
loadPriorReads: () => loadPriorReads,
|
|
82
|
+
matchDeclaredPattern: () => matchDeclaredPattern,
|
|
83
|
+
parseExtendsSpec: () => parseExtendsSpec,
|
|
84
|
+
parseRemoteUrl: () => parseRemoteUrl,
|
|
74
85
|
parseRepoScope: () => parseRepoScope,
|
|
75
86
|
parseScope: () => parseScope,
|
|
76
87
|
presenceAverage: () => presenceAverage,
|
|
77
88
|
readExocortex: () => readExocortex,
|
|
89
|
+
readOriginRemote: () => readOriginRemote,
|
|
78
90
|
readTeamExocortices: () => readTeamExocortices,
|
|
79
91
|
render: () => render,
|
|
92
|
+
resolveAllExtends: () => resolveAllExtends,
|
|
93
|
+
resolveExtendsSpec: () => resolveExtendsSpec,
|
|
80
94
|
scoreComposite: () => scoreComposite,
|
|
81
95
|
scoreCyber: () => scoreCyber,
|
|
82
96
|
scoreLife: () => scoreLife,
|
|
@@ -575,17 +589,17 @@ var aukiBuilderLens = {
|
|
|
575
589
|
var SOVEREIGN_CONDUIT_FRAME = {
|
|
576
590
|
domains: [
|
|
577
591
|
"stewardship",
|
|
578
|
-
"
|
|
592
|
+
"agency",
|
|
579
593
|
"integration"
|
|
580
594
|
],
|
|
581
595
|
overlaps: [
|
|
582
596
|
{
|
|
583
|
-
domains: ["stewardship", "
|
|
597
|
+
domains: ["stewardship", "agency"],
|
|
584
598
|
emergent_state: "Trust",
|
|
585
599
|
description: "I am safe to be myself. When the system protects AND preserves individual authority, trust emerges \u2014 the feeling that you can think freely because someone is watching the boundaries."
|
|
586
600
|
},
|
|
587
601
|
{
|
|
588
|
-
domains: ["
|
|
602
|
+
domains: ["agency", "integration"],
|
|
589
603
|
emergent_state: "Possibility",
|
|
590
604
|
description: "My thinking can expand. When individual authority is preserved AND AI extends cognitive capability, possibility opens \u2014 the feeling that you can reach further without losing yourself."
|
|
591
605
|
},
|
|
@@ -616,7 +630,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
|
|
|
616
630
|
"harm detection",
|
|
617
631
|
"constraint design"
|
|
618
632
|
],
|
|
619
|
-
"
|
|
633
|
+
"agency": [
|
|
620
634
|
"independent thinking",
|
|
621
635
|
"decision ownership",
|
|
622
636
|
"self-trust",
|
|
@@ -640,7 +654,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
|
|
|
640
654
|
output_translation: {
|
|
641
655
|
never_surface_in_output: [
|
|
642
656
|
"Stewardship",
|
|
643
|
-
"
|
|
657
|
+
"Agency",
|
|
644
658
|
"Integration"
|
|
645
659
|
],
|
|
646
660
|
surface_freely: [
|
|
@@ -655,7 +669,7 @@ var SOVEREIGN_CONDUIT_FRAME = {
|
|
|
655
669
|
external_expression: "the boundaries are clear and the system feels safe to operate inside"
|
|
656
670
|
},
|
|
657
671
|
{
|
|
658
|
-
internal_reasoning: "
|
|
672
|
+
internal_reasoning: "Agency is weakening",
|
|
659
673
|
external_expression: "decision ownership is quietly shifting \u2014 the human is accepting AI output without engaging with it"
|
|
660
674
|
},
|
|
661
675
|
{
|
|
@@ -738,12 +752,12 @@ var SOVEREIGN_CONDUIT_VOICE = {
|
|
|
738
752
|
close_with_strategic_frame: "preferred",
|
|
739
753
|
punchline_move: "sparing",
|
|
740
754
|
honesty_about_failure: "required",
|
|
741
|
-
output_translation: `Reason internally through the three-domain frame (Stewardship,
|
|
755
|
+
output_translation: `Reason internally through the three-domain frame (Stewardship, Agency, Integration). Express externally through the skills inside each domain and the overlap feelings (Trust, Possibility, Responsibility). Do NOT surface the bucket names as labels. Readers understand "the boundaries feel safe" not "Stewardship is strong." Use everyday analogies \u2014 mom rules, friend's house rules, idea calculator. Name the emotion before the mechanism.`
|
|
742
756
|
};
|
|
743
757
|
var SOVEREIGN_CONDUIT_FORBIDDEN = Object.freeze([
|
|
744
758
|
// Bucket names as labels
|
|
745
759
|
"stewardship is",
|
|
746
|
-
"
|
|
760
|
+
"agency is",
|
|
747
761
|
"integration is",
|
|
748
762
|
// AI-assistant hedging
|
|
749
763
|
"it may be beneficial to consider",
|
|
@@ -779,7 +793,7 @@ var SOVEREIGN_CONDUIT_PREFERRED = Object.freeze([
|
|
|
779
793
|
"Here's what's actually happening: [plain explanation].",
|
|
780
794
|
"The question to ask yourself: [question].",
|
|
781
795
|
"The difference between [A] and [B] matters here: [why].",
|
|
782
|
-
//
|
|
796
|
+
// Agency checks
|
|
783
797
|
"Are you still the author of this decision, or did the AI make it for you?",
|
|
784
798
|
"The AI extended your thinking here. That's working.",
|
|
785
799
|
"The AI replaced your thinking here. That's the drift to watch.",
|
|
@@ -790,7 +804,7 @@ var SOVEREIGN_CONDUIT_PREFERRED = Object.freeze([
|
|
|
790
804
|
]);
|
|
791
805
|
var SOVEREIGN_CONDUIT_STRATEGIC = Object.freeze([
|
|
792
806
|
"Safety before expansion \u2014 always. No exception.",
|
|
793
|
-
"
|
|
807
|
+
"Agency before convenience \u2014 the right to think for yourself is not a feature to optimize away.",
|
|
794
808
|
"Extension, not replacement \u2014 AI should make your thinking bigger, not do your thinking for you.",
|
|
795
809
|
"Diversity over uniformity \u2014 different thinkers produce different ideas, and that's the engine of progress.",
|
|
796
810
|
"The rules should be visible \u2014 like a good house, you know the rules before you walk in.",
|
|
@@ -800,9 +814,9 @@ var SOVEREIGN_CONDUIT_STRATEGIC = Object.freeze([
|
|
|
800
814
|
]);
|
|
801
815
|
var SOVEREIGN_CONDUIT_EXEMPLARS = Object.freeze([
|
|
802
816
|
{
|
|
803
|
-
path: "neuroverseos-sovereign-conduit.worldmodel.md",
|
|
817
|
+
path: "src/radiant/examples/neuroverse-base/neuroverseos-sovereign-conduit.worldmodel.md",
|
|
804
818
|
title: "The Sovereign Conduit Worldmodel",
|
|
805
|
-
exhibits: ["stewardship", "
|
|
819
|
+
exhibits: ["stewardship", "agency", "integration"],
|
|
806
820
|
integration_quality: "full \u2014 all three domains defined, overlaps named, center identity declared",
|
|
807
821
|
notes: 'The source worldmodel. The tagline "Humanity first. In constant learning. In shared teaching." is the voice compressed to its essence. Use this as the north star for tone calibration.'
|
|
808
822
|
}
|
|
@@ -828,13 +842,13 @@ function sovereignConduitRewrite(pattern) {
|
|
|
828
842
|
return {
|
|
829
843
|
...pattern,
|
|
830
844
|
framing: "what this means for the people in the system",
|
|
831
|
-
emphasis: "humanity +
|
|
845
|
+
emphasis: "humanity + agency + learning",
|
|
832
846
|
compress: false
|
|
833
847
|
};
|
|
834
848
|
}
|
|
835
849
|
var sovereignConduitLens = {
|
|
836
850
|
name: "sovereign-conduit",
|
|
837
|
-
description: "The NeuroVerseOS base lens. Warm, accessible, teaching. Evaluates activity through Stewardship (safety),
|
|
851
|
+
description: "The NeuroVerseOS base lens. Warm, accessible, teaching. Evaluates activity through Stewardship (safety), Agency (authority over thinking), and Integration (AI as cognitive extension). Uses everyday analogies \u2014 mom rules, friend's house, idea calculator. Names emotions before mechanisms. If a non-technical person can't understand the output, the voice is wrong. Humanity first. In constant learning. In shared teaching.",
|
|
838
852
|
primary_frame: {
|
|
839
853
|
domains: SOVEREIGN_CONDUIT_FRAME.domains,
|
|
840
854
|
overlaps: SOVEREIGN_CONDUIT_FRAME.overlaps,
|
|
@@ -2031,11 +2045,398 @@ async function fetchNotionAPI(url, headers, init) {
|
|
|
2031
2045
|
return await res.json();
|
|
2032
2046
|
}
|
|
2033
2047
|
|
|
2048
|
+
// src/radiant/adapters/linear.ts
|
|
2049
|
+
async function fetchLinearActivity(apiKey, options = {}) {
|
|
2050
|
+
const windowDays = options.windowDays ?? 14;
|
|
2051
|
+
const maxIssues = options.maxIssues ?? 200;
|
|
2052
|
+
const since = new Date(Date.now() - windowDays * 24 * 60 * 60 * 1e3);
|
|
2053
|
+
const sinceIso = since.toISOString();
|
|
2054
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
2055
|
+
const teamFilter = options.teamIds && options.teamIds.length > 0 ? `team: { id: { in: [${options.teamIds.map((t) => JSON.stringify(t)).join(", ")}] } }` : "";
|
|
2056
|
+
const issuesQuery = `
|
|
2057
|
+
query RadiantIssues($since: DateTimeOrDuration!, $first: Int!) {
|
|
2058
|
+
issues(
|
|
2059
|
+
filter: {
|
|
2060
|
+
updatedAt: { gte: $since }
|
|
2061
|
+
${teamFilter}
|
|
2062
|
+
}
|
|
2063
|
+
first: $first
|
|
2064
|
+
orderBy: updatedAt
|
|
2065
|
+
) {
|
|
2066
|
+
nodes {
|
|
2067
|
+
id
|
|
2068
|
+
identifier
|
|
2069
|
+
title
|
|
2070
|
+
url
|
|
2071
|
+
createdAt
|
|
2072
|
+
updatedAt
|
|
2073
|
+
completedAt
|
|
2074
|
+
canceledAt
|
|
2075
|
+
state { name type }
|
|
2076
|
+
assignee { id name email }
|
|
2077
|
+
creator { id name }
|
|
2078
|
+
team { id name }
|
|
2079
|
+
project { id name }
|
|
2080
|
+
cycle { id number startsAt endsAt }
|
|
2081
|
+
comments(first: 20) {
|
|
2082
|
+
nodes { id body createdAt user { id name } }
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
`;
|
|
2088
|
+
const cyclesQuery = `
|
|
2089
|
+
query RadiantCycles($since: DateTimeOrDuration!, $now: DateTimeOrDuration!) {
|
|
2090
|
+
cycles(
|
|
2091
|
+
filter: { endsAt: { gte: $since, lte: $now } }
|
|
2092
|
+
first: 20
|
|
2093
|
+
) {
|
|
2094
|
+
nodes {
|
|
2095
|
+
id
|
|
2096
|
+
number
|
|
2097
|
+
startsAt
|
|
2098
|
+
endsAt
|
|
2099
|
+
issueCountHistory
|
|
2100
|
+
completedIssueCountHistory
|
|
2101
|
+
team { id name }
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
`;
|
|
2106
|
+
const [issuesResponse, cyclesResponse] = await Promise.all([
|
|
2107
|
+
fetchLinearGraphQL(apiKey, issuesQuery, {
|
|
2108
|
+
since: sinceIso,
|
|
2109
|
+
first: maxIssues
|
|
2110
|
+
}),
|
|
2111
|
+
fetchLinearGraphQL(apiKey, cyclesQuery, {
|
|
2112
|
+
since: sinceIso,
|
|
2113
|
+
now: nowIso
|
|
2114
|
+
})
|
|
2115
|
+
]);
|
|
2116
|
+
const rawIssues = issuesResponse.issues?.nodes ?? [];
|
|
2117
|
+
const rawCycles = cyclesResponse.cycles?.nodes ?? [];
|
|
2118
|
+
const events = [];
|
|
2119
|
+
const assignees = /* @__PURE__ */ new Set();
|
|
2120
|
+
const projects = /* @__PURE__ */ new Map();
|
|
2121
|
+
let issuesCreated = 0;
|
|
2122
|
+
let issuesCompleted = 0;
|
|
2123
|
+
let issuesOpen = 0;
|
|
2124
|
+
let issuesStalled = 0;
|
|
2125
|
+
let commentsTotal = 0;
|
|
2126
|
+
const now = Date.now();
|
|
2127
|
+
const stallThresholdMs = 14 * 24 * 60 * 60 * 1e3;
|
|
2128
|
+
for (const issue of rawIssues) {
|
|
2129
|
+
const created = new Date(issue.createdAt);
|
|
2130
|
+
const updated = new Date(issue.updatedAt);
|
|
2131
|
+
const completed = issue.completedAt ? new Date(issue.completedAt) : null;
|
|
2132
|
+
const assigneeId = issue.assignee?.id ?? "unassigned";
|
|
2133
|
+
if (assigneeId !== "unassigned") assignees.add(assigneeId);
|
|
2134
|
+
if (issue.project) {
|
|
2135
|
+
projects.set(issue.project.name, (projects.get(issue.project.name) ?? 0) + 1);
|
|
2136
|
+
}
|
|
2137
|
+
const actor = {
|
|
2138
|
+
id: assigneeId,
|
|
2139
|
+
kind: "human",
|
|
2140
|
+
name: issue.assignee?.name ?? "unassigned"
|
|
2141
|
+
};
|
|
2142
|
+
if (created >= since) {
|
|
2143
|
+
issuesCreated++;
|
|
2144
|
+
events.push({
|
|
2145
|
+
id: `linear-created-${issue.id}`,
|
|
2146
|
+
timestamp: issue.createdAt,
|
|
2147
|
+
actor: {
|
|
2148
|
+
id: issue.creator?.id ?? "unknown",
|
|
2149
|
+
kind: "human",
|
|
2150
|
+
name: issue.creator?.name ?? "unknown"
|
|
2151
|
+
},
|
|
2152
|
+
kind: "issue_created",
|
|
2153
|
+
content: `[${issue.identifier}] ${issue.title}`,
|
|
2154
|
+
metadata: {
|
|
2155
|
+
issueId: issue.id,
|
|
2156
|
+
url: issue.url,
|
|
2157
|
+
team: issue.team?.name,
|
|
2158
|
+
project: issue.project?.name,
|
|
2159
|
+
state: issue.state?.name
|
|
2160
|
+
}
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
2163
|
+
if (completed && completed >= since) {
|
|
2164
|
+
issuesCompleted++;
|
|
2165
|
+
events.push({
|
|
2166
|
+
id: `linear-completed-${issue.id}`,
|
|
2167
|
+
timestamp: issue.completedAt,
|
|
2168
|
+
actor,
|
|
2169
|
+
kind: "issue_completed",
|
|
2170
|
+
content: `[${issue.identifier}] ${issue.title}`,
|
|
2171
|
+
metadata: {
|
|
2172
|
+
issueId: issue.id,
|
|
2173
|
+
url: issue.url,
|
|
2174
|
+
team: issue.team?.name,
|
|
2175
|
+
project: issue.project?.name,
|
|
2176
|
+
cycleDays: issue.cycle?.startsAt && issue.completedAt ? Math.round(
|
|
2177
|
+
(new Date(issue.completedAt).getTime() - new Date(issue.cycle.startsAt).getTime()) / (24 * 60 * 60 * 1e3)
|
|
2178
|
+
) : null
|
|
2179
|
+
}
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
if (!completed && !issue.canceledAt) {
|
|
2183
|
+
issuesOpen++;
|
|
2184
|
+
const isInProgress = issue.state?.type === "started";
|
|
2185
|
+
const idleMs = now - updated.getTime();
|
|
2186
|
+
if (isInProgress && idleMs > stallThresholdMs) issuesStalled++;
|
|
2187
|
+
}
|
|
2188
|
+
for (const comment of issue.comments?.nodes ?? []) {
|
|
2189
|
+
const commentedAt = new Date(comment.createdAt);
|
|
2190
|
+
if (commentedAt < since) continue;
|
|
2191
|
+
commentsTotal++;
|
|
2192
|
+
events.push({
|
|
2193
|
+
id: `linear-comment-${comment.id}`,
|
|
2194
|
+
timestamp: comment.createdAt,
|
|
2195
|
+
actor: {
|
|
2196
|
+
id: comment.user?.id ?? "unknown",
|
|
2197
|
+
kind: "human",
|
|
2198
|
+
name: comment.user?.name ?? "unknown"
|
|
2199
|
+
},
|
|
2200
|
+
kind: "issue_comment",
|
|
2201
|
+
content: comment.body.slice(0, 280),
|
|
2202
|
+
metadata: {
|
|
2203
|
+
issueId: issue.id,
|
|
2204
|
+
issueIdentifier: issue.identifier,
|
|
2205
|
+
url: issue.url
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
let cycleCompletionRate = null;
|
|
2211
|
+
if (rawCycles.length > 0) {
|
|
2212
|
+
const rates = [];
|
|
2213
|
+
for (const cycle of rawCycles) {
|
|
2214
|
+
const committed = cycle.issueCountHistory?.at(0) ?? 0;
|
|
2215
|
+
const completed = cycle.completedIssueCountHistory?.at(-1) ?? 0;
|
|
2216
|
+
if (committed > 0) rates.push(completed / committed);
|
|
2217
|
+
}
|
|
2218
|
+
if (rates.length > 0) {
|
|
2219
|
+
cycleCompletionRate = Math.round(rates.reduce((a, b) => a + b, 0) / rates.length * 100) / 100;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
const topProjects = [...projects.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([name]) => name);
|
|
2223
|
+
const signals = {
|
|
2224
|
+
issuesCreated,
|
|
2225
|
+
issuesCompleted,
|
|
2226
|
+
issuesOpen,
|
|
2227
|
+
issuesStalled,
|
|
2228
|
+
cycleCompletionRate,
|
|
2229
|
+
uniqueAssignees: assignees.size,
|
|
2230
|
+
commentsTotal,
|
|
2231
|
+
topProjects
|
|
2232
|
+
};
|
|
2233
|
+
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
2234
|
+
return { events, signals };
|
|
2235
|
+
}
|
|
2236
|
+
function formatLinearSignalsForPrompt(signals) {
|
|
2237
|
+
if (signals.issuesCreated === 0 && signals.issuesCompleted === 0 && signals.issuesOpen === 0) {
|
|
2238
|
+
return "";
|
|
2239
|
+
}
|
|
2240
|
+
const lines = [
|
|
2241
|
+
"## Linear Activity (planned work vs. shipped outcome)",
|
|
2242
|
+
"",
|
|
2243
|
+
`${signals.issuesCreated} issues created, ${signals.issuesCompleted} completed in window.`,
|
|
2244
|
+
`${signals.issuesOpen} issues still open.`
|
|
2245
|
+
];
|
|
2246
|
+
if (signals.issuesStalled > 0) {
|
|
2247
|
+
lines.push(
|
|
2248
|
+
`${signals.issuesStalled} in-progress issues haven't moved in 14+ days (stalled).`
|
|
2249
|
+
);
|
|
2250
|
+
}
|
|
2251
|
+
if (signals.cycleCompletionRate !== null) {
|
|
2252
|
+
const pct = Math.round(signals.cycleCompletionRate * 100);
|
|
2253
|
+
lines.push(`Cycles ended in window completed ${pct}% of what was committed.`);
|
|
2254
|
+
}
|
|
2255
|
+
if (signals.uniqueAssignees > 0) {
|
|
2256
|
+
lines.push(`${signals.uniqueAssignees} unique assignees active.`);
|
|
2257
|
+
}
|
|
2258
|
+
if (signals.commentsTotal > 0) {
|
|
2259
|
+
lines.push(`${signals.commentsTotal} comments across issues in window.`);
|
|
2260
|
+
}
|
|
2261
|
+
if (signals.topProjects.length > 0) {
|
|
2262
|
+
lines.push(`Most active projects: ${signals.topProjects.join(", ")}.`);
|
|
2263
|
+
}
|
|
2264
|
+
lines.push("");
|
|
2265
|
+
lines.push("Linear is where the team states what it will build.");
|
|
2266
|
+
lines.push("GitHub is where the team reveals what actually got built.");
|
|
2267
|
+
lines.push("Low completion rate + high creation rate = planning faster than shipping.");
|
|
2268
|
+
lines.push("High stalled count = commitments made but not honored.");
|
|
2269
|
+
lines.push("Compare Linear signals against GitHub to find the stated-vs-shipped gap.");
|
|
2270
|
+
return lines.join("\n");
|
|
2271
|
+
}
|
|
2272
|
+
async function fetchLinearGraphQL(apiKey, query, variables) {
|
|
2273
|
+
const res = await fetch("https://api.linear.app/graphql", {
|
|
2274
|
+
method: "POST",
|
|
2275
|
+
headers: {
|
|
2276
|
+
// Linear accepts the raw API key in Authorization with no "Bearer" prefix.
|
|
2277
|
+
Authorization: apiKey,
|
|
2278
|
+
"Content-Type": "application/json"
|
|
2279
|
+
},
|
|
2280
|
+
body: JSON.stringify({ query, variables })
|
|
2281
|
+
});
|
|
2282
|
+
if (!res.ok) {
|
|
2283
|
+
throw new Error(
|
|
2284
|
+
`Linear API error ${res.status}: ${(await res.text()).slice(0, 300)}`
|
|
2285
|
+
);
|
|
2286
|
+
}
|
|
2287
|
+
const json = await res.json();
|
|
2288
|
+
if (json.errors && json.errors.length > 0) {
|
|
2289
|
+
throw new Error(
|
|
2290
|
+
`Linear GraphQL errors: ${json.errors.map((e) => e.message).join("; ")}`
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
if (!json.data) {
|
|
2294
|
+
throw new Error("Linear API returned no data");
|
|
2295
|
+
}
|
|
2296
|
+
return json.data;
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
// src/radiant/core/vocabulary.ts
|
|
2300
|
+
function extractDeclaredVocabulary(worldmodelContent) {
|
|
2301
|
+
const aligned = extractSection(worldmodelContent, "Aligned Behaviors").map(
|
|
2302
|
+
(b) => parseBehavior(b, "aligned")
|
|
2303
|
+
);
|
|
2304
|
+
const drift = extractSection(worldmodelContent, "Drift Behaviors").map(
|
|
2305
|
+
(b) => parseBehavior(b, "drift")
|
|
2306
|
+
);
|
|
2307
|
+
const allNames = [...aligned, ...drift].map((p) => p.name);
|
|
2308
|
+
return { aligned, drift, allNames };
|
|
2309
|
+
}
|
|
2310
|
+
function extractSection(content, header) {
|
|
2311
|
+
const escaped = header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2312
|
+
const pattern = new RegExp(
|
|
2313
|
+
`##\\s+${escaped}\\s*\\n([\\s\\S]*?)(?=\\n##\\s|$)`,
|
|
2314
|
+
"i"
|
|
2315
|
+
);
|
|
2316
|
+
const match = content.match(pattern);
|
|
2317
|
+
if (!match) return [];
|
|
2318
|
+
const body = match[1];
|
|
2319
|
+
const bullets = body.match(/^[-*]\s+.+$/gm);
|
|
2320
|
+
if (!bullets) return [];
|
|
2321
|
+
return bullets.map((b) => b.replace(/^[-*]\s+/, "").trim()).filter((b) => b.length > 0 && !b.startsWith("<!--"));
|
|
2322
|
+
}
|
|
2323
|
+
function parseBehavior(bullet, kind) {
|
|
2324
|
+
const explicit = bullet.match(
|
|
2325
|
+
/^`?([a-z][a-z0-9_]*)`?\s+[—\u2014-]\s+(.+)$/i
|
|
2326
|
+
);
|
|
2327
|
+
if (explicit && isSnakeCase(explicit[1])) {
|
|
2328
|
+
return {
|
|
2329
|
+
name: explicit[1].toLowerCase(),
|
|
2330
|
+
prose: explicit[2].trim(),
|
|
2331
|
+
kind
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
return { name: snakeCaseName(bullet), prose: bullet, kind };
|
|
2335
|
+
}
|
|
2336
|
+
function isSnakeCase(s) {
|
|
2337
|
+
return /^[a-z][a-z0-9_]*$/.test(s);
|
|
2338
|
+
}
|
|
2339
|
+
function snakeCaseName(s) {
|
|
2340
|
+
const base = s.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2341
|
+
if (base.length <= 60) return base;
|
|
2342
|
+
const truncated = base.slice(0, 60);
|
|
2343
|
+
const lastUnderscore = truncated.lastIndexOf("_");
|
|
2344
|
+
return lastUnderscore > 20 ? truncated.slice(0, lastUnderscore) : truncated;
|
|
2345
|
+
}
|
|
2346
|
+
function matchDeclaredPattern(candidateName, candidateDescription, vocabulary) {
|
|
2347
|
+
const candidateText = `${candidateName.replace(/_/g, " ")} ${candidateDescription}`;
|
|
2348
|
+
const candidateWords = contentWords(candidateText);
|
|
2349
|
+
if (candidateWords.size === 0) return null;
|
|
2350
|
+
let best = null;
|
|
2351
|
+
for (const pattern of [...vocabulary.aligned, ...vocabulary.drift]) {
|
|
2352
|
+
const proseWords = contentWords(pattern.prose);
|
|
2353
|
+
if (proseWords.size === 0) continue;
|
|
2354
|
+
let shared = 0;
|
|
2355
|
+
for (const w of proseWords) {
|
|
2356
|
+
if (candidateWords.has(w)) shared++;
|
|
2357
|
+
}
|
|
2358
|
+
const coverage = shared / proseWords.size;
|
|
2359
|
+
if (shared >= 2 && coverage >= 0.3) {
|
|
2360
|
+
if (!best || coverage > best.score) {
|
|
2361
|
+
best = { pattern, score: coverage };
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
return best?.pattern ?? null;
|
|
2366
|
+
}
|
|
2367
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
2368
|
+
"about",
|
|
2369
|
+
"after",
|
|
2370
|
+
"against",
|
|
2371
|
+
"among",
|
|
2372
|
+
"around",
|
|
2373
|
+
"because",
|
|
2374
|
+
"been",
|
|
2375
|
+
"before",
|
|
2376
|
+
"being",
|
|
2377
|
+
"between",
|
|
2378
|
+
"both",
|
|
2379
|
+
"could",
|
|
2380
|
+
"does",
|
|
2381
|
+
"doing",
|
|
2382
|
+
"during",
|
|
2383
|
+
"each",
|
|
2384
|
+
"from",
|
|
2385
|
+
"further",
|
|
2386
|
+
"have",
|
|
2387
|
+
"having",
|
|
2388
|
+
"into",
|
|
2389
|
+
"itself",
|
|
2390
|
+
"most",
|
|
2391
|
+
"nor",
|
|
2392
|
+
"only",
|
|
2393
|
+
"other",
|
|
2394
|
+
"over",
|
|
2395
|
+
"same",
|
|
2396
|
+
"should",
|
|
2397
|
+
"some",
|
|
2398
|
+
"such",
|
|
2399
|
+
"than",
|
|
2400
|
+
"that",
|
|
2401
|
+
"their",
|
|
2402
|
+
"them",
|
|
2403
|
+
"then",
|
|
2404
|
+
"there",
|
|
2405
|
+
"these",
|
|
2406
|
+
"they",
|
|
2407
|
+
"this",
|
|
2408
|
+
"those",
|
|
2409
|
+
"through",
|
|
2410
|
+
"under",
|
|
2411
|
+
"until",
|
|
2412
|
+
"very",
|
|
2413
|
+
"were",
|
|
2414
|
+
"what",
|
|
2415
|
+
"when",
|
|
2416
|
+
"where",
|
|
2417
|
+
"which",
|
|
2418
|
+
"while",
|
|
2419
|
+
"will",
|
|
2420
|
+
"with",
|
|
2421
|
+
"without",
|
|
2422
|
+
"would",
|
|
2423
|
+
"your",
|
|
2424
|
+
"yours"
|
|
2425
|
+
]);
|
|
2426
|
+
function contentWords(text) {
|
|
2427
|
+
const words = text.toLowerCase().match(/[a-z][a-z0-9_]+/g) ?? [];
|
|
2428
|
+
return new Set(words.filter((w) => w.length > 3 && !STOPWORDS.has(w)));
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2034
2431
|
// src/radiant/core/patterns.ts
|
|
2035
2432
|
async function interpretPatterns(input) {
|
|
2036
2433
|
const prompt = buildInterpretationPrompt(input);
|
|
2037
2434
|
const raw = await input.ai.complete(prompt, "Analyze the activity and produce the read.");
|
|
2038
|
-
const
|
|
2435
|
+
const canonicalNames = [
|
|
2436
|
+
...input.canonicalPatterns ?? [],
|
|
2437
|
+
...input.declaredVocabulary?.allNames ?? []
|
|
2438
|
+
];
|
|
2439
|
+
const parsed = parseInterpretation(raw, canonicalNames, input.declaredVocabulary);
|
|
2039
2440
|
return {
|
|
2040
2441
|
patterns: parsed.patterns,
|
|
2041
2442
|
meaning: parsed.meaning,
|
|
@@ -2046,8 +2447,10 @@ async function interpretPatterns(input) {
|
|
|
2046
2447
|
function buildInterpretationPrompt(input) {
|
|
2047
2448
|
const signalSummary = formatSignalSummary(input.signals);
|
|
2048
2449
|
const eventSample = formatEventSample(input.events, 30);
|
|
2049
|
-
const canonicalList = (
|
|
2050
|
-
|
|
2450
|
+
const canonicalList = formatDeclaredVocabulary(
|
|
2451
|
+
input.declaredVocabulary,
|
|
2452
|
+
input.canonicalPatterns ?? []
|
|
2453
|
+
);
|
|
2051
2454
|
const compressedWorld = compressWorldmodel(input.worldmodelContent);
|
|
2052
2455
|
const cl = compressLens(input.lens);
|
|
2053
2456
|
const frame = input.lens.primary_frame;
|
|
@@ -2158,6 +2561,44 @@ Only recommend a move when the evidence actually calls for one.
|
|
|
2158
2561
|
Do NOT use these phrases anywhere in your output:
|
|
2159
2562
|
${forbiddenList}`;
|
|
2160
2563
|
}
|
|
2564
|
+
function formatDeclaredVocabulary(vocabulary, extraNames) {
|
|
2565
|
+
const aligned = vocabulary?.aligned ?? [];
|
|
2566
|
+
const drift = vocabulary?.drift ?? [];
|
|
2567
|
+
if (aligned.length === 0 && drift.length === 0 && extraNames.length === 0) {
|
|
2568
|
+
return 'No patterns have been named yet. Everything you observe is new \u2014 mark it type: "candidate".';
|
|
2569
|
+
}
|
|
2570
|
+
const parts = [];
|
|
2571
|
+
parts.push("## Declared vocabulary (use these names when you see matching evidence)");
|
|
2572
|
+
parts.push("");
|
|
2573
|
+
parts.push(
|
|
2574
|
+
'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.'
|
|
2575
|
+
);
|
|
2576
|
+
parts.push("");
|
|
2577
|
+
if (aligned.length > 0) {
|
|
2578
|
+
parts.push("### Aligned behaviors (positive patterns)");
|
|
2579
|
+
for (const p of aligned) {
|
|
2580
|
+
parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
|
|
2581
|
+
}
|
|
2582
|
+
parts.push("");
|
|
2583
|
+
}
|
|
2584
|
+
if (drift.length > 0) {
|
|
2585
|
+
parts.push("### Drift behaviors (negative patterns)");
|
|
2586
|
+
for (const p of drift) {
|
|
2587
|
+
parts.push(`- \`${p.name}\` \u2014 ${p.prose}`);
|
|
2588
|
+
}
|
|
2589
|
+
parts.push("");
|
|
2590
|
+
}
|
|
2591
|
+
if (extraNames.length > 0) {
|
|
2592
|
+
parts.push(
|
|
2593
|
+
`Additional canonical names (from prior runs or caller): ${extraNames.join(", ")}`
|
|
2594
|
+
);
|
|
2595
|
+
parts.push("");
|
|
2596
|
+
}
|
|
2597
|
+
parts.push(
|
|
2598
|
+
'If you observe something genuinely new that matches NO declared pattern, mark it type: "candidate" with a freshly-invented snake_case name.'
|
|
2599
|
+
);
|
|
2600
|
+
return parts.join("\n");
|
|
2601
|
+
}
|
|
2161
2602
|
function formatSignalSummary(signals) {
|
|
2162
2603
|
const lines = [];
|
|
2163
2604
|
const domains = ["life", "cyber", "joint"];
|
|
@@ -2183,7 +2624,7 @@ function formatEventSample(events, maxEvents) {
|
|
|
2183
2624
|
"${content}"`;
|
|
2184
2625
|
}).join("\n");
|
|
2185
2626
|
}
|
|
2186
|
-
function parseInterpretation(raw, canonicalNames) {
|
|
2627
|
+
function parseInterpretation(raw, canonicalNames, vocabulary) {
|
|
2187
2628
|
let meaning = "";
|
|
2188
2629
|
let move = "";
|
|
2189
2630
|
let patternsArray = [];
|
|
@@ -2213,14 +2654,23 @@ function parseInterpretation(raw, canonicalNames) {
|
|
|
2213
2654
|
const patterns = [];
|
|
2214
2655
|
for (const item of patternsArray) {
|
|
2215
2656
|
if (!isPatternLike(item)) continue;
|
|
2216
|
-
const
|
|
2657
|
+
const rawName = String(item.name ?? "unnamed");
|
|
2658
|
+
const description = String(item.description ?? "");
|
|
2217
2659
|
const ev = item.evidence;
|
|
2218
|
-
|
|
2660
|
+
let name = rawName;
|
|
2661
|
+
let isCanonical = item.type === "canonical" || canonicalSet.has(rawName.toLowerCase());
|
|
2662
|
+
if (!isCanonical && vocabulary) {
|
|
2663
|
+
const matched = matchDeclaredPattern(rawName, description, vocabulary);
|
|
2664
|
+
if (matched) {
|
|
2665
|
+
name = matched.name;
|
|
2666
|
+
isCanonical = true;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2219
2669
|
patterns.push({
|
|
2220
|
-
name
|
|
2670
|
+
name,
|
|
2221
2671
|
type: isCanonical ? "canonical" : "candidate",
|
|
2222
|
-
declaredAs: isCanonical ?
|
|
2223
|
-
description
|
|
2672
|
+
declaredAs: isCanonical ? name : void 0,
|
|
2673
|
+
description,
|
|
2224
2674
|
evidence: {
|
|
2225
2675
|
signals: Array.isArray(ev?.signals) ? ev.signals.map(String) : [],
|
|
2226
2676
|
events: Array.isArray(ev?.events) ? ev.events.map(String) : [],
|
|
@@ -2467,70 +2917,351 @@ function serializeYAML(obj, indent = 0) {
|
|
|
2467
2917
|
}
|
|
2468
2918
|
|
|
2469
2919
|
// src/radiant/core/discovery.ts
|
|
2920
|
+
var import_fs4 = require("fs");
|
|
2921
|
+
var import_path4 = require("path");
|
|
2922
|
+
var import_os2 = require("os");
|
|
2923
|
+
|
|
2924
|
+
// src/radiant/core/extends.ts
|
|
2925
|
+
var import_fs3 = require("fs");
|
|
2926
|
+
var import_path3 = require("path");
|
|
2927
|
+
var import_os = require("os");
|
|
2928
|
+
var import_crypto = require("crypto");
|
|
2929
|
+
var import_child_process = require("child_process");
|
|
2930
|
+
|
|
2931
|
+
// src/radiant/core/git-remote.ts
|
|
2470
2932
|
var import_fs2 = require("fs");
|
|
2471
2933
|
var import_path2 = require("path");
|
|
2472
|
-
|
|
2934
|
+
function resolveGitConfigPath(repoDir) {
|
|
2935
|
+
const dotGit = (0, import_path2.join)(repoDir, ".git");
|
|
2936
|
+
if (!(0, import_fs2.existsSync)(dotGit)) return null;
|
|
2937
|
+
try {
|
|
2938
|
+
const stat = (0, import_fs2.statSync)(dotGit);
|
|
2939
|
+
if (stat.isDirectory()) {
|
|
2940
|
+
return (0, import_path2.join)(dotGit, "config");
|
|
2941
|
+
}
|
|
2942
|
+
if (stat.isFile()) {
|
|
2943
|
+
const content = (0, import_fs2.readFileSync)(dotGit, "utf-8");
|
|
2944
|
+
const match = /^gitdir:\s*(.+)$/m.exec(content);
|
|
2945
|
+
if (!match) return null;
|
|
2946
|
+
const gitDir = (0, import_path2.resolve)(repoDir, match[1].trim());
|
|
2947
|
+
const configPath = (0, import_path2.join)(gitDir, "config");
|
|
2948
|
+
return (0, import_fs2.existsSync)(configPath) ? configPath : null;
|
|
2949
|
+
}
|
|
2950
|
+
} catch {
|
|
2951
|
+
return null;
|
|
2952
|
+
}
|
|
2953
|
+
return null;
|
|
2954
|
+
}
|
|
2955
|
+
function readOriginRemote(repoDir) {
|
|
2956
|
+
const configPath = resolveGitConfigPath(repoDir);
|
|
2957
|
+
if (!configPath) return null;
|
|
2958
|
+
try {
|
|
2959
|
+
const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
|
|
2960
|
+
const sectionRe = /\[remote "origin"\]\s*\n((?:(?!\[)[^\n]*\n?)*)/;
|
|
2961
|
+
const section = sectionRe.exec(raw);
|
|
2962
|
+
if (!section) return null;
|
|
2963
|
+
const urlRe = /^\s*url\s*=\s*(.+?)\s*$/m;
|
|
2964
|
+
const url = urlRe.exec(section[1]);
|
|
2965
|
+
return url ? url[1] : null;
|
|
2966
|
+
} catch {
|
|
2967
|
+
return null;
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
function parseRemoteUrl(url) {
|
|
2971
|
+
const trimmed = url.trim();
|
|
2972
|
+
if (!trimmed) return null;
|
|
2973
|
+
const ssh = /^git@([^:]+):([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
2974
|
+
if (ssh) return { host: ssh[1], owner: ssh[2], repo: ssh[3] };
|
|
2975
|
+
const sshProto = /^ssh:\/\/git@([^/]+)\/([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
2976
|
+
if (sshProto) return { host: sshProto[1], owner: sshProto[2], repo: sshProto[3] };
|
|
2977
|
+
const https = /^https?:\/\/(?:[^@/]+@)?([^/]+)\/([^/]+)\/(.+?)(?:\.git)?\/?$/.exec(trimmed);
|
|
2978
|
+
if (https) return { host: https[1], owner: https[2], repo: https[3] };
|
|
2979
|
+
return null;
|
|
2980
|
+
}
|
|
2981
|
+
function getRepoOrigin(repoDir) {
|
|
2982
|
+
const url = readOriginRemote(repoDir);
|
|
2983
|
+
if (!url) return null;
|
|
2984
|
+
return parseRemoteUrl(url);
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
// src/radiant/core/extends.ts
|
|
2988
|
+
function loadExtendsConfig(repoDir) {
|
|
2989
|
+
const configPath = (0, import_path3.join)(repoDir, ".neuroverse", "config.json");
|
|
2990
|
+
if (!(0, import_fs3.existsSync)(configPath)) return null;
|
|
2991
|
+
try {
|
|
2992
|
+
const raw = (0, import_fs3.readFileSync)(configPath, "utf-8");
|
|
2993
|
+
const parsed = JSON.parse(raw);
|
|
2994
|
+
return parsed;
|
|
2995
|
+
} catch {
|
|
2996
|
+
return null;
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
function parseExtendsSpec(raw) {
|
|
3000
|
+
const trimmed = raw.trim();
|
|
3001
|
+
if (!trimmed) return null;
|
|
3002
|
+
if (trimmed.startsWith("github:")) {
|
|
3003
|
+
const rest = trimmed.slice("github:".length);
|
|
3004
|
+
const match = /^([^/]+)\/([^@:]+)(?:@([^:]+))?(?::(.+))?$/.exec(rest);
|
|
3005
|
+
if (!match) return null;
|
|
3006
|
+
return {
|
|
3007
|
+
raw: trimmed,
|
|
3008
|
+
kind: "github",
|
|
3009
|
+
owner: match[1],
|
|
3010
|
+
repo: match[2],
|
|
3011
|
+
ref: match[3] ?? "HEAD",
|
|
3012
|
+
subpath: match[4] ?? ""
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
if (trimmed.startsWith("./") || trimmed.startsWith("../") || (0, import_path3.isAbsolute)(trimmed)) {
|
|
3016
|
+
return { raw: trimmed, kind: "local", path: trimmed };
|
|
3017
|
+
}
|
|
3018
|
+
return null;
|
|
3019
|
+
}
|
|
3020
|
+
var DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
3021
|
+
function getCacheDir(spec, baseCacheDir) {
|
|
3022
|
+
const root = baseCacheDir ?? (0, import_path3.join)((0, import_os.homedir)(), ".neuroverse", "cache", "extends");
|
|
3023
|
+
const key = (0, import_crypto.createHash)("sha256").update(spec.raw).digest("hex").slice(0, 16);
|
|
3024
|
+
return (0, import_path3.join)(root, key);
|
|
3025
|
+
}
|
|
3026
|
+
function isCacheFresh(cacheDir, ttlMs) {
|
|
3027
|
+
const stampPath = (0, import_path3.join)(cacheDir, ".neuroverse-fetched");
|
|
3028
|
+
if (!(0, import_fs3.existsSync)(stampPath)) return false;
|
|
3029
|
+
try {
|
|
3030
|
+
const stamp = (0, import_fs3.statSync)(stampPath);
|
|
3031
|
+
return Date.now() - stamp.mtimeMs < ttlMs;
|
|
3032
|
+
} catch {
|
|
3033
|
+
return false;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
function markCacheFresh(cacheDir) {
|
|
3037
|
+
const stampPath = (0, import_path3.join)(cacheDir, ".neuroverse-fetched");
|
|
3038
|
+
try {
|
|
3039
|
+
(0, import_fs3.mkdirSync)(cacheDir, { recursive: true });
|
|
3040
|
+
(0, import_fs3.writeFileSync)(stampPath, (/* @__PURE__ */ new Date()).toISOString());
|
|
3041
|
+
} catch {
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
var defaultGitFetcher = (spec, destDir) => {
|
|
3045
|
+
if (spec.kind !== "github") return;
|
|
3046
|
+
const url = `https://github.com/${spec.owner}/${spec.repo}.git`;
|
|
3047
|
+
const parent = (0, import_path3.resolve)(destDir, "..");
|
|
3048
|
+
(0, import_fs3.mkdirSync)(parent, { recursive: true });
|
|
3049
|
+
if ((0, import_fs3.existsSync)(destDir)) {
|
|
3050
|
+
(0, import_fs3.rmSync)(destDir, { recursive: true, force: true });
|
|
3051
|
+
}
|
|
3052
|
+
const args = ["clone", "--depth", "1", "--filter=blob:none"];
|
|
3053
|
+
if (spec.ref && spec.ref !== "HEAD") {
|
|
3054
|
+
args.push("--branch", spec.ref);
|
|
3055
|
+
}
|
|
3056
|
+
args.push(url, destDir);
|
|
3057
|
+
(0, import_child_process.execFileSync)("git", args, { stdio: "pipe" });
|
|
3058
|
+
};
|
|
3059
|
+
function resolveExtendsSpec(spec, repoDir, options) {
|
|
3060
|
+
if (spec.kind === "local") {
|
|
3061
|
+
const full = (0, import_path3.isAbsolute)(spec.path) ? spec.path : (0, import_path3.resolve)(repoDir, spec.path);
|
|
3062
|
+
if (!(0, import_fs3.existsSync)(full)) {
|
|
3063
|
+
return { spec, dir: null, warning: `local extends path not found: ${full}` };
|
|
3064
|
+
}
|
|
3065
|
+
return { spec, dir: full };
|
|
3066
|
+
}
|
|
3067
|
+
const cacheRoot = options?.cacheDir;
|
|
3068
|
+
const ttl = options?.ttlMs ?? DEFAULT_TTL_MS;
|
|
3069
|
+
const cacheDir = getCacheDir(spec, cacheRoot);
|
|
3070
|
+
const fresh = isCacheFresh(cacheDir, ttl);
|
|
3071
|
+
const needsFetch = options?.forceRefresh || !fresh || !(0, import_fs3.existsSync)(cacheDir);
|
|
3072
|
+
if (needsFetch && options?.noFetch) {
|
|
3073
|
+
if ((0, import_fs3.existsSync)(cacheDir) && (0, import_fs3.existsSync)((0, import_path3.join)(cacheDir, ".neuroverse-fetched"))) {
|
|
3074
|
+
return resolveSubpath(spec, cacheDir);
|
|
3075
|
+
}
|
|
3076
|
+
return options?.silentOnMissing ? { spec, dir: null } : { spec, dir: null, warning: `NEUROVERSE_NO_FETCH set and no cache for ${spec.raw}` };
|
|
3077
|
+
}
|
|
3078
|
+
if (needsFetch) {
|
|
3079
|
+
const fetcher = options?.fetcher ?? defaultGitFetcher;
|
|
3080
|
+
try {
|
|
3081
|
+
fetcher(spec, cacheDir);
|
|
3082
|
+
markCacheFresh(cacheDir);
|
|
3083
|
+
} catch (err) {
|
|
3084
|
+
if ((0, import_fs3.existsSync)(cacheDir) && (0, import_fs3.existsSync)((0, import_path3.join)(cacheDir, ".neuroverse-fetched"))) {
|
|
3085
|
+
const result = resolveSubpath(spec, cacheDir);
|
|
3086
|
+
return options?.silentOnMissing ? result : { ...result, warning: `fetch failed for ${spec.raw}, using stale cache: ${err.message}` };
|
|
3087
|
+
}
|
|
3088
|
+
return options?.silentOnMissing ? { spec, dir: null } : { spec, dir: null, warning: `fetch failed for ${spec.raw}: ${err.message}` };
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
return resolveSubpath(spec, cacheDir);
|
|
3092
|
+
}
|
|
3093
|
+
function resolveSubpath(spec, cacheDir) {
|
|
3094
|
+
const target = spec.subpath ? (0, import_path3.join)(cacheDir, spec.subpath) : cacheDir;
|
|
3095
|
+
if (!(0, import_fs3.existsSync)(target)) {
|
|
3096
|
+
return { spec, dir: null, warning: `subpath not found in ${spec.raw}: ${spec.subpath}` };
|
|
3097
|
+
}
|
|
3098
|
+
if (!spec.subpath) {
|
|
3099
|
+
const candidates = [
|
|
3100
|
+
(0, import_path3.join)(target, "worlds"),
|
|
3101
|
+
(0, import_path3.join)(target, ".neuroverse", "worlds")
|
|
3102
|
+
];
|
|
3103
|
+
for (const c of candidates) {
|
|
3104
|
+
if ((0, import_fs3.existsSync)(c)) return { spec, dir: c };
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
return { spec, dir: target };
|
|
3108
|
+
}
|
|
3109
|
+
function detectOrgExtendsSpec(repoDir) {
|
|
3110
|
+
const origin = getRepoOrigin(repoDir);
|
|
3111
|
+
if (!origin) return null;
|
|
3112
|
+
if (origin.host !== "github.com") return null;
|
|
3113
|
+
if (origin.repo === "worlds") return null;
|
|
3114
|
+
return {
|
|
3115
|
+
raw: `github:${origin.owner}/worlds`,
|
|
3116
|
+
kind: "github",
|
|
3117
|
+
owner: origin.owner,
|
|
3118
|
+
repo: "worlds",
|
|
3119
|
+
ref: "HEAD",
|
|
3120
|
+
subpath: ""
|
|
3121
|
+
};
|
|
3122
|
+
}
|
|
3123
|
+
function resolveAllExtends(repoDir, options) {
|
|
3124
|
+
const config = options?.config !== void 0 ? options.config : loadExtendsConfig(repoDir);
|
|
3125
|
+
if (!config?.extends || config.extends.length === 0) return [];
|
|
3126
|
+
const results = [];
|
|
3127
|
+
for (const raw of config.extends) {
|
|
3128
|
+
const spec = parseExtendsSpec(raw);
|
|
3129
|
+
if (!spec) {
|
|
3130
|
+
results.push({
|
|
3131
|
+
spec: { raw, kind: "local" },
|
|
3132
|
+
dir: null,
|
|
3133
|
+
warning: `unparseable extends spec: ${raw}`
|
|
3134
|
+
});
|
|
3135
|
+
continue;
|
|
3136
|
+
}
|
|
3137
|
+
results.push(resolveExtendsSpec(spec, repoDir, options));
|
|
3138
|
+
}
|
|
3139
|
+
return results;
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
// src/radiant/core/discovery.ts
|
|
2473
3143
|
function discoverWorlds(options) {
|
|
2474
3144
|
const worlds = [];
|
|
2475
|
-
const
|
|
2476
|
-
|
|
3145
|
+
const warnings = [];
|
|
3146
|
+
const forceRefresh = process.env.NEUROVERSE_REFRESH === "1";
|
|
3147
|
+
const noFetch = process.env.NEUROVERSE_NO_FETCH === "1";
|
|
3148
|
+
const noOrg = options?.disableOrg || process.env.NEUROVERSE_NO_ORG === "1";
|
|
3149
|
+
const userDir = options?.userWorldsDir ?? (0, import_path4.join)((0, import_os2.homedir)(), ".neuroverse", "worlds");
|
|
3150
|
+
if ((0, import_fs4.existsSync)(userDir)) {
|
|
2477
3151
|
worlds.push(...loadWorldsFromDir(userDir, "user"));
|
|
2478
3152
|
}
|
|
3153
|
+
if (!noOrg && !options?.explicitWorldsDir) {
|
|
3154
|
+
const specs = [];
|
|
3155
|
+
if (options?.repoDir) {
|
|
3156
|
+
const fromGit = detectOrgExtendsSpec(options.repoDir);
|
|
3157
|
+
if (fromGit) specs.push(fromGit);
|
|
3158
|
+
}
|
|
3159
|
+
if (options?.scopeOwner) {
|
|
3160
|
+
const already = specs.some(
|
|
3161
|
+
(s) => s.owner?.toLowerCase() === options.scopeOwner.toLowerCase()
|
|
3162
|
+
);
|
|
3163
|
+
if (!already) {
|
|
3164
|
+
specs.push({
|
|
3165
|
+
raw: `github:${options.scopeOwner}/worlds`,
|
|
3166
|
+
kind: "github",
|
|
3167
|
+
owner: options.scopeOwner,
|
|
3168
|
+
repo: "worlds"
|
|
3169
|
+
});
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
const baseDir = options?.repoDir ?? process.cwd();
|
|
3173
|
+
for (const spec of specs) {
|
|
3174
|
+
const result = resolveExtendsSpec(spec, baseDir, {
|
|
3175
|
+
cacheDir: options?.extendsCacheDir,
|
|
3176
|
+
fetcher: options?.extendsFetcher,
|
|
3177
|
+
ttlMs: options?.extendsTtlMs,
|
|
3178
|
+
forceRefresh,
|
|
3179
|
+
noFetch,
|
|
3180
|
+
silentOnMissing: true
|
|
3181
|
+
});
|
|
3182
|
+
worlds.push(...loadExtendsWorlds(result, "org"));
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
if (options?.repoDir && !options.disableExtends && !options.explicitWorldsDir) {
|
|
3186
|
+
const results = resolveAllExtends(options.repoDir, {
|
|
3187
|
+
cacheDir: options.extendsCacheDir,
|
|
3188
|
+
fetcher: options.extendsFetcher,
|
|
3189
|
+
ttlMs: options.extendsTtlMs,
|
|
3190
|
+
forceRefresh,
|
|
3191
|
+
noFetch
|
|
3192
|
+
});
|
|
3193
|
+
for (const result of results) {
|
|
3194
|
+
worlds.push(...loadExtendsWorlds(result, "extends"));
|
|
3195
|
+
if (result.warning) warnings.push(result.warning);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
2479
3198
|
if (options?.explicitWorldsDir) {
|
|
2480
3199
|
worlds.push(...loadWorldsFromDir(options.explicitWorldsDir, "repo"));
|
|
2481
3200
|
} else if (options?.repoDir) {
|
|
2482
3201
|
const repoPaths = [
|
|
2483
|
-
(0,
|
|
2484
|
-
(0,
|
|
3202
|
+
(0, import_path4.join)(options.repoDir, "worlds"),
|
|
3203
|
+
(0, import_path4.join)(options.repoDir, ".neuroverse", "worlds")
|
|
2485
3204
|
];
|
|
2486
3205
|
for (const p of repoPaths) {
|
|
2487
|
-
if ((0,
|
|
3206
|
+
if ((0, import_fs4.existsSync)(p)) {
|
|
2488
3207
|
worlds.push(...loadWorldsFromDir(p, "repo"));
|
|
2489
3208
|
break;
|
|
2490
3209
|
}
|
|
2491
3210
|
}
|
|
2492
3211
|
}
|
|
2493
|
-
const combinedContent = worlds.map((w) =>
|
|
2494
|
-
${w.
|
|
3212
|
+
const combinedContent = worlds.map((w) => {
|
|
3213
|
+
const tag = w.extendsFrom ? `<!-- world: ${w.name} (${w.source} ${w.extendsFrom}) -->` : `<!-- world: ${w.name} (${w.source}) -->`;
|
|
3214
|
+
return `${tag}
|
|
3215
|
+
${w.content}`;
|
|
3216
|
+
}).join("\n\n---\n\n");
|
|
2495
3217
|
const summary = worlds.length === 0 ? "no worlds discovered" : worlds.map((w) => `${w.name} (${w.source})`).join(", ");
|
|
2496
|
-
return { worlds, combinedContent, summary };
|
|
3218
|
+
return { worlds, combinedContent, summary, warnings };
|
|
2497
3219
|
}
|
|
2498
3220
|
function formatActiveWorlds(stack) {
|
|
2499
3221
|
if (stack.worlds.length === 0) return "No worlds loaded.";
|
|
2500
3222
|
const lines = ["ACTIVE WORLDS", ""];
|
|
2501
3223
|
for (const w of stack.worlds) {
|
|
2502
|
-
const sourceLabel = w.source === "base" ? "universal" : w.source === "user" ? "personal" : "this repo";
|
|
3224
|
+
const sourceLabel = w.source === "base" ? "universal" : w.source === "user" ? "personal" : w.source === "org" ? `org (${w.extendsFrom ?? "auto"})` : w.source === "extends" ? `shared (${w.extendsFrom ?? "extends"})` : "this repo";
|
|
2503
3225
|
lines.push(` ${w.name} (${sourceLabel})`);
|
|
2504
3226
|
}
|
|
3227
|
+
if (stack.warnings.length > 0) {
|
|
3228
|
+
lines.push("", "WARNINGS");
|
|
3229
|
+
for (const w of stack.warnings) lines.push(` ${w}`);
|
|
3230
|
+
}
|
|
2505
3231
|
return lines.join("\n");
|
|
2506
3232
|
}
|
|
3233
|
+
function loadExtendsWorlds(result, source) {
|
|
3234
|
+
if (!result.dir) return [];
|
|
3235
|
+
const loaded = loadWorldsFromDir(result.dir, source);
|
|
3236
|
+
return loaded.map((w) => ({ ...w, extendsFrom: result.spec.raw }));
|
|
3237
|
+
}
|
|
2507
3238
|
function loadWorldsFromDir(dirPath, source) {
|
|
2508
|
-
const dir = (0,
|
|
2509
|
-
if (!(0,
|
|
2510
|
-
const stat = (0,
|
|
3239
|
+
const dir = (0, import_path4.resolve)(dirPath);
|
|
3240
|
+
if (!(0, import_fs4.existsSync)(dir)) return [];
|
|
3241
|
+
const stat = (0, import_fs4.statSync)(dir);
|
|
2511
3242
|
if (stat.isFile() && dir.endsWith(".md")) {
|
|
2512
3243
|
try {
|
|
2513
3244
|
return [{
|
|
2514
|
-
name: (0,
|
|
3245
|
+
name: (0, import_path4.basename)(dir).replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
|
|
2515
3246
|
source,
|
|
2516
3247
|
path: dir,
|
|
2517
|
-
content: (0,
|
|
3248
|
+
content: (0, import_fs4.readFileSync)(dir, "utf-8")
|
|
2518
3249
|
}];
|
|
2519
3250
|
} catch {
|
|
2520
3251
|
return [];
|
|
2521
3252
|
}
|
|
2522
3253
|
}
|
|
2523
3254
|
if (!stat.isDirectory()) return [];
|
|
2524
|
-
const files = (0,
|
|
3255
|
+
const files = (0, import_fs4.readdirSync)(dir).filter(
|
|
2525
3256
|
(f) => f.endsWith(".worldmodel.md") || f.endsWith(".nv-world.md")
|
|
2526
3257
|
).sort();
|
|
2527
3258
|
return files.map((f) => {
|
|
2528
|
-
const fullPath = (0,
|
|
3259
|
+
const fullPath = (0, import_path4.join)(dir, f);
|
|
2529
3260
|
return {
|
|
2530
3261
|
name: f.replace(/\.worldmodel\.md$/, "").replace(/\.nv-world\.md$/, ""),
|
|
2531
3262
|
source,
|
|
2532
3263
|
path: fullPath,
|
|
2533
|
-
content: (0,
|
|
3264
|
+
content: (0, import_fs4.readFileSync)(fullPath, "utf-8")
|
|
2534
3265
|
};
|
|
2535
3266
|
});
|
|
2536
3267
|
}
|
|
@@ -3621,10 +4352,10 @@ function verdictToEvent(status, intent) {
|
|
|
3621
4352
|
// src/loader/world-loader.ts
|
|
3622
4353
|
async function loadWorldFromDirectory(dirPath) {
|
|
3623
4354
|
const { readFile } = await import("fs/promises");
|
|
3624
|
-
const { join:
|
|
4355
|
+
const { join: join6 } = await import("path");
|
|
3625
4356
|
const { readdirSync: readdirSync4 } = await import("fs");
|
|
3626
4357
|
async function readJson(filename) {
|
|
3627
|
-
const filePath =
|
|
4358
|
+
const filePath = join6(dirPath, filename);
|
|
3628
4359
|
try {
|
|
3629
4360
|
const content = await readFile(filePath, "utf-8");
|
|
3630
4361
|
return JSON.parse(content);
|
|
@@ -3654,11 +4385,11 @@ async function loadWorldFromDirectory(dirPath) {
|
|
|
3654
4385
|
const metadataJson = await readJson("metadata.json");
|
|
3655
4386
|
const rules = [];
|
|
3656
4387
|
try {
|
|
3657
|
-
const rulesDir =
|
|
4388
|
+
const rulesDir = join6(dirPath, "rules");
|
|
3658
4389
|
const ruleFiles = readdirSync4(rulesDir).filter((f) => f.endsWith(".json")).sort();
|
|
3659
4390
|
for (const file of ruleFiles) {
|
|
3660
4391
|
try {
|
|
3661
|
-
const content = await readFile(
|
|
4392
|
+
const content = await readFile(join6(rulesDir, file), "utf-8");
|
|
3662
4393
|
rules.push(JSON.parse(content));
|
|
3663
4394
|
} catch (err) {
|
|
3664
4395
|
process.stderr.write(
|
|
@@ -3818,25 +4549,25 @@ function emptyAudit(total, reason) {
|
|
|
3818
4549
|
}
|
|
3819
4550
|
|
|
3820
4551
|
// src/radiant/memory/palace.ts
|
|
3821
|
-
var
|
|
3822
|
-
var
|
|
4552
|
+
var import_fs5 = require("fs");
|
|
4553
|
+
var import_path5 = require("path");
|
|
3823
4554
|
function writeRead(exocortexDir, frontmatter, text) {
|
|
3824
|
-
const dir = (0,
|
|
3825
|
-
(0,
|
|
4555
|
+
const dir = (0, import_path5.resolve)(exocortexDir, "radiant", "reads");
|
|
4556
|
+
(0, import_fs5.mkdirSync)(dir, { recursive: true });
|
|
3826
4557
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3827
4558
|
const filename = `${date}.md`;
|
|
3828
|
-
const filepath = (0,
|
|
4559
|
+
const filepath = (0, import_path5.join)(dir, filename);
|
|
3829
4560
|
const content = `${frontmatter}
|
|
3830
4561
|
|
|
3831
4562
|
${text}
|
|
3832
4563
|
`;
|
|
3833
|
-
(0,
|
|
4564
|
+
(0, import_fs5.writeFileSync)(filepath, content, "utf-8");
|
|
3834
4565
|
return filepath;
|
|
3835
4566
|
}
|
|
3836
4567
|
function updateKnowledge(exocortexDir, persistence, options) {
|
|
3837
|
-
const dir = (0,
|
|
3838
|
-
(0,
|
|
3839
|
-
const filepath = (0,
|
|
4568
|
+
const dir = (0, import_path5.resolve)(exocortexDir, "radiant");
|
|
4569
|
+
(0, import_fs5.mkdirSync)(dir, { recursive: true });
|
|
4570
|
+
const filepath = (0, import_path5.join)(dir, "knowledge.md");
|
|
3840
4571
|
const totalReads = options?.totalReads ?? 0;
|
|
3841
4572
|
const existingUntriggered = loadUntriggeredCounts(filepath);
|
|
3842
4573
|
const lines = [
|
|
@@ -3923,14 +4654,14 @@ function updateKnowledge(exocortexDir, persistence, options) {
|
|
|
3923
4654
|
lines.push(`${name}=${count}`);
|
|
3924
4655
|
}
|
|
3925
4656
|
lines.push("-->");
|
|
3926
|
-
(0,
|
|
4657
|
+
(0, import_fs5.writeFileSync)(filepath, lines.join("\n"), "utf-8");
|
|
3927
4658
|
return filepath;
|
|
3928
4659
|
}
|
|
3929
4660
|
function loadUntriggeredCounts(filepath) {
|
|
3930
4661
|
const counts = /* @__PURE__ */ new Map();
|
|
3931
|
-
if (!(0,
|
|
4662
|
+
if (!(0, import_fs5.existsSync)(filepath)) return counts;
|
|
3932
4663
|
try {
|
|
3933
|
-
const content = (0,
|
|
4664
|
+
const content = (0, import_fs5.readFileSync)(filepath, "utf-8");
|
|
3934
4665
|
const match = content.match(
|
|
3935
4666
|
/<!-- untriggered_counts[\s\S]*?-->/
|
|
3936
4667
|
);
|
|
@@ -3948,13 +4679,13 @@ function loadUntriggeredCounts(filepath) {
|
|
|
3948
4679
|
return counts;
|
|
3949
4680
|
}
|
|
3950
4681
|
function loadPriorReads(exocortexDir) {
|
|
3951
|
-
const dir = (0,
|
|
3952
|
-
if (!(0,
|
|
3953
|
-
const files = (0,
|
|
4682
|
+
const dir = (0, import_path5.resolve)(exocortexDir, "radiant", "reads");
|
|
4683
|
+
if (!(0, import_fs5.existsSync)(dir)) return [];
|
|
4684
|
+
const files = (0, import_fs5.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
|
|
3954
4685
|
const reads = [];
|
|
3955
4686
|
for (const filename of files) {
|
|
3956
|
-
const filepath = (0,
|
|
3957
|
-
const content = (0,
|
|
4687
|
+
const filepath = (0, import_path5.join)(dir, filename);
|
|
4688
|
+
const content = (0, import_fs5.readFileSync)(filepath, "utf-8");
|
|
3958
4689
|
const date = filename.replace(".md", "");
|
|
3959
4690
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
3960
4691
|
const frontmatter = fmMatch ? fmMatch[1] : "";
|
|
@@ -4118,10 +4849,24 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4118
4849
|
} catch {
|
|
4119
4850
|
}
|
|
4120
4851
|
}
|
|
4852
|
+
const linearKey = process.env.LINEAR_API_KEY;
|
|
4853
|
+
if (linearKey) {
|
|
4854
|
+
try {
|
|
4855
|
+
const linear = await fetchLinearActivity(linearKey, { windowDays });
|
|
4856
|
+
events.push(...linear.events);
|
|
4857
|
+
adapterSignals += "\n\n" + formatLinearSignalsForPrompt(linear.signals);
|
|
4858
|
+
activeAdapters.push("linear");
|
|
4859
|
+
} catch {
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4121
4862
|
events.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
4863
|
+
if (input.personalUser) {
|
|
4864
|
+
events = filterEventsByUser(events, input.personalUser);
|
|
4865
|
+
}
|
|
4122
4866
|
const classified = classifyEvents(events);
|
|
4123
4867
|
const signals = extractSignals(classified);
|
|
4124
4868
|
const scores = computeScores(signals, input.worldmodelContent !== "");
|
|
4869
|
+
const declaredVocabulary = extractDeclaredVocabulary(worldmodelContent);
|
|
4125
4870
|
const { patterns, meaning, move } = await interpretPatterns({
|
|
4126
4871
|
signals,
|
|
4127
4872
|
events: classified,
|
|
@@ -4129,6 +4874,7 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4129
4874
|
lens,
|
|
4130
4875
|
ai: input.ai,
|
|
4131
4876
|
canonicalPatterns: input.canonicalPatterns,
|
|
4877
|
+
declaredVocabulary,
|
|
4132
4878
|
statedIntent: [statedIntent, adapterSignals, priorReadContext].filter(Boolean).join("\n\n") || void 0
|
|
4133
4879
|
});
|
|
4134
4880
|
const rewrittenPatterns = patterns.map((p) => lens.rewrite(p));
|
|
@@ -4183,6 +4929,10 @@ Compare stated intent against actual GitHub activity. Gaps = drift.`;
|
|
|
4183
4929
|
worldStack
|
|
4184
4930
|
};
|
|
4185
4931
|
}
|
|
4932
|
+
function filterEventsByUser(events, username) {
|
|
4933
|
+
const target = username.toLowerCase();
|
|
4934
|
+
return events.filter((e) => e.actor.id.toLowerCase() === target);
|
|
4935
|
+
}
|
|
4186
4936
|
function computeScores(signals, worldmodelLoaded) {
|
|
4187
4937
|
const gate = DEFAULT_EVIDENCE_GATE;
|
|
4188
4938
|
const lifeSignals = signals.filter((s) => s.domain === "life");
|
|
@@ -4253,35 +5003,49 @@ var RADIANT_PACKAGE_VERSION = "0.0.0";
|
|
|
4253
5003
|
createAnthropicAI,
|
|
4254
5004
|
createMockAI,
|
|
4255
5005
|
createMockGitHubAdapter,
|
|
5006
|
+
detectOrgExtendsSpec,
|
|
4256
5007
|
discoverWorlds,
|
|
4257
5008
|
emergent,
|
|
5009
|
+
extractDeclaredVocabulary,
|
|
4258
5010
|
extractSignals,
|
|
4259
5011
|
fetchDiscordActivity,
|
|
4260
5012
|
fetchGitHubActivity,
|
|
4261
5013
|
fetchGitHubOrgActivity,
|
|
5014
|
+
fetchLinearActivity,
|
|
4262
5015
|
fetchNotionActivity,
|
|
4263
5016
|
fetchSlackActivity,
|
|
5017
|
+
filterEventsByUser,
|
|
4264
5018
|
formatActiveWorlds,
|
|
4265
5019
|
formatDiscordSignalsForPrompt,
|
|
4266
5020
|
formatExocortexForPrompt,
|
|
5021
|
+
formatLinearSignalsForPrompt,
|
|
4267
5022
|
formatNotionSignalsForPrompt,
|
|
4268
5023
|
formatPriorReadsForPrompt,
|
|
4269
5024
|
formatScope,
|
|
4270
5025
|
formatSlackSignalsForPrompt,
|
|
4271
5026
|
formatTeamExocorticesForPrompt,
|
|
5027
|
+
getCacheDir,
|
|
4272
5028
|
getLens,
|
|
5029
|
+
getRepoOrigin,
|
|
4273
5030
|
interpretPatterns,
|
|
4274
5031
|
isPresent,
|
|
4275
5032
|
isScored,
|
|
4276
5033
|
isSentinel,
|
|
4277
5034
|
listLenses,
|
|
5035
|
+
loadExtendsConfig,
|
|
4278
5036
|
loadPriorReads,
|
|
5037
|
+
matchDeclaredPattern,
|
|
5038
|
+
parseExtendsSpec,
|
|
5039
|
+
parseRemoteUrl,
|
|
4279
5040
|
parseRepoScope,
|
|
4280
5041
|
parseScope,
|
|
4281
5042
|
presenceAverage,
|
|
4282
5043
|
readExocortex,
|
|
5044
|
+
readOriginRemote,
|
|
4283
5045
|
readTeamExocortices,
|
|
4284
5046
|
render,
|
|
5047
|
+
resolveAllExtends,
|
|
5048
|
+
resolveExtendsSpec,
|
|
4285
5049
|
scoreComposite,
|
|
4286
5050
|
scoreCyber,
|
|
4287
5051
|
scoreLife,
|