nx_doc_inref.nx source
↩ module page · 93 lines · 2961 B
1// nx_doc_inref.nx -- incoming-reference counter for substrate docs.
2//
3// For each doc, counts how many OTHER docs contain a [[doc-name]]
4// reference to it. Surfaces top-N most-referenced docs as data-
5// driven V2 backfill priority targets.
6//
7// Composes nx_grep + nx_string_ops + nx_dir + nx_doc_census walker
8// pattern. Substrate's first OPERATIONAL doc-graph analysis
9// primitive -- moves beyond aggregate compliance to substrate-aware
10// "which docs MATTER" visibility.
11//
12// **Quadrant:** REFERENCE (Diátaxis)
13// **Topic Type:** REFERENCE (DITA)
14// **Status:** DRAFT
15// **Trust State:** WRITTEN_UNTESTED
16// **Competitive State:** UNCLASSIFIED
17
18import "nx_syscalls.nx"
19import "nx_string_ops.nx"
20import "nx_dir.nx"
21import "nx_grep.nx"
22import "nx_grep_rt.nx" // nx_grep_any lives here, not in nx_grep.nx
23
24// Build "[[<name-without-md>]]" pattern from a filename ending .md.
25// Returns pattern length (or -1 if name doesn't end .md / cap small).
26// Substrate-honest: caller supplies pattern buffer; we don't alloc.
27func nx_doc_build_inref_pattern(
28 name: *u8, n_name: i64,
29 out_pat: *u8, out_cap: i64
30) -> i64 {
31 if n_name <= 3 { return -1 }
32 // Strip .md suffix
33 let base_len: i64 = n_name - 3
34 if base_len + 4 > out_cap { return -1 }
35 out_pat[0] = 91 // '['
36 out_pat[1] = 91 // '['
37 var i: i64 = 0
38 while i < base_len {
39 out_pat[2 + i] = name[i]
40 i = i + 1
41 }
42 out_pat[2 + base_len] = 93 // ']'
43 out_pat[3 + base_len] = 93 // ']'
44 return base_len + 4
45}
46
47// Count incoming references to `target_pattern` across an array of
48// pre-loaded doc contents. Returns count of distinct docs that
49// reference the target (not total link count -- one ref per doc).
50//
51// caller provides:
52// contents: array of (content_ptr, content_len) pairs
53// n_docs: number of pairs
54// pattern: [[name]] pattern (built via nx_doc_build_inref_pattern)
55// n_pattern: pattern length
56//
57// Substrate-honest: O(n_docs * avg_doc_size); for substrate's ~280
58// docs * 16-64 KB this is fine for single-shot audit. Multi-pattern
59// would benefit from Aho-Corasick (queued).
60
61struct NxInrefContents {
62 ptr: *u8,
63 len: i64,
64}
65
66func nx_doc_count_inref_across_docs(
67 contents: *NxInrefContents,
68 n_docs: i64,
69 pattern: *u8,
70 n_pattern: i64
71) -> i64 {
72 var count: i64 = 0
73 var i: i64 = 0
74 while i < n_docs {
75 let row: *NxInrefContents = ((contents as *u8) + (i * 16)) as *NxInrefContents
76 if nx_grep_any(row.ptr, row.len, pattern, n_pattern) == 1 {
77 count = count + 1
78 }
79 i = i + 1
80 }
81 return count
82}
83
84// Bool: pattern length non-zero AND outside the doc's own content.
85// Used to avoid self-reference inflating the count (the doc
86// referencing itself doesn't make it more "important").
87func nx_doc_should_skip_self(
88 doc_idx: i64,
89 test_idx: i64
90) -> i64 {
91 if doc_idx == test_idx { return 1 }
92 return 0
93}