jekyll-agent-audit 0.1.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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE.txt +17 -0
  5. data/README.md +180 -0
  6. data/Rakefile +38 -0
  7. data/doc/Jekyll/AgentAudit/BuildInventory.md +29 -0
  8. data/doc/Jekyll/AgentAudit/Configuration.md +42 -0
  9. data/doc/Jekyll/AgentAudit/ConfigurationError.md +6 -0
  10. data/doc/Jekyll/AgentAudit/Error.md +6 -0
  11. data/doc/Jekyll/AgentAudit/Extractor.md +20 -0
  12. data/doc/Jekyll/AgentAudit/Finding.md +30 -0
  13. data/doc/Jekyll/AgentAudit/InputError.md +6 -0
  14. data/doc/Jekyll/AgentAudit/LinkGraph.md +26 -0
  15. data/doc/Jekyll/AgentAudit/Registry.md +38 -0
  16. data/doc/Jekyll/AgentAudit/Report.md +27 -0
  17. data/doc/Jekyll/AgentAudit/ReportError.md +6 -0
  18. data/doc/Jekyll/AgentAudit/Reporters/Console.md +19 -0
  19. data/doc/Jekyll/AgentAudit/Reporters/JSON.md +9 -0
  20. data/doc/Jekyll/AgentAudit/Reporters.md +5 -0
  21. data/doc/Jekyll/AgentAudit/Rules/Provenance.md +127 -0
  22. data/doc/Jekyll/AgentAudit/Rules/Publication.md +73 -0
  23. data/doc/Jekyll/AgentAudit/Rules.md +5 -0
  24. data/doc/Jekyll/AgentAudit/Runner.md +13 -0
  25. data/doc/Jekyll/AgentAudit/UrlResolver.md +13 -0
  26. data/doc/Jekyll/AgentAudit.md +35 -0
  27. data/doc/Jekyll/Commands/AgentAudit/CommandParser.md +9 -0
  28. data/doc/Jekyll/Commands/AgentAudit/ParserErrors.md +9 -0
  29. data/doc/Jekyll/Commands/AgentAudit.md +13 -0
  30. data/doc/Jekyll/Commands.md +5 -0
  31. data/doc/Jekyll.md +5 -0
  32. data/doc/README.md +180 -0
  33. data/doc/index.csv +154 -0
  34. data/docs/example-report.json +281 -0
  35. data/docs/implementation-plan.md +26 -0
  36. data/docs/limitations.md +31 -0
  37. data/docs/verification.md +52 -0
  38. data/lib/jekyll/agent_audit/build_inventory.rb +196 -0
  39. data/lib/jekyll/agent_audit/command.rb +179 -0
  40. data/lib/jekyll/agent_audit/configuration.rb +196 -0
  41. data/lib/jekyll/agent_audit/errors.rb +10 -0
  42. data/lib/jekyll/agent_audit/extractor.rb +230 -0
  43. data/lib/jekyll/agent_audit/finding.rb +57 -0
  44. data/lib/jekyll/agent_audit/link_graph.rb +82 -0
  45. data/lib/jekyll/agent_audit/registry.rb +133 -0
  46. data/lib/jekyll/agent_audit/report.rb +79 -0
  47. data/lib/jekyll/agent_audit/reporters/console.rb +144 -0
  48. data/lib/jekyll/agent_audit/reporters/json.rb +16 -0
  49. data/lib/jekyll/agent_audit/rules/provenance.rb +412 -0
  50. data/lib/jekyll/agent_audit/rules/publication.rb +186 -0
  51. data/lib/jekyll/agent_audit/runner.rb +266 -0
  52. data/lib/jekyll/agent_audit/url_resolver.rb +98 -0
  53. data/lib/jekyll/agent_audit/version.rb +7 -0
  54. data/lib/jekyll-agent-audit.rb +24 -0
  55. data/llms.txt +35 -0
  56. data/schema/report-1.0.json +66 -0
  57. data/script/benchmark.rb +68 -0
  58. metadata +133 -0
@@ -0,0 +1,66 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "jekyll-agent-audit report 1.0",
4
+ "type": "object",
5
+ "required": ["schema_version", "tool", "run", "policy", "summary", "coverage", "findings", "diagnostics"],
6
+ "properties": {
7
+ "schema_version": {"const": "1.0"},
8
+ "tool": {
9
+ "type": "object", "required": ["name", "version"],
10
+ "properties": {"name": {"const": "jekyll-agent-audit"}, "version": {"type": "string"}}
11
+ },
12
+ "run": {
13
+ "type": "object", "required": ["mode", "complete", "site_url", "baseurl", "environment", "reference_time", "ruleset_version"],
14
+ "properties": {
15
+ "mode": {"const": "local_build"}, "complete": {"type": "boolean"},
16
+ "site_url": {"type": "string"}, "baseurl": {"type": "string"},
17
+ "environment": {"type": "string"}, "reference_time": {"type": "string"},
18
+ "ruleset_version": {"type": "string"}
19
+ }
20
+ },
21
+ "policy": {
22
+ "type": "object", "required": ["fail_on", "passed", "exit_code"],
23
+ "properties": {"fail_on": {"enum": ["error", "warning", "none"]}, "passed": {"type": "boolean"}, "exit_code": {"enum": [0, 1, 2, 130]}}
24
+ },
25
+ "summary": {
26
+ "type": "object", "required": ["documents_inspected", "active", "suppressed", "affected_documents"],
27
+ "properties": {
28
+ "documents_inspected": {"$ref": "#/$defs/count"}, "suppressed": {"$ref": "#/$defs/count"}, "affected_documents": {"$ref": "#/$defs/count"},
29
+ "active": {
30
+ "type": "object", "required": ["error", "warning", "info", "experimental"],
31
+ "properties": {"error": {"$ref": "#/$defs/count"}, "warning": {"$ref": "#/$defs/count"}, "info": {"$ref": "#/$defs/count"}, "experimental": {"$ref": "#/$defs/count"}}
32
+ }
33
+ }
34
+ },
35
+ "coverage": {
36
+ "type": "object", "required": ["discovery", "rules"],
37
+ "properties": {
38
+ "discovery": {"type": "object", "required": ["status", "owner"], "properties": {"status": {"const": "not_assessed"}, "owner": {"const": "jekyll-agent-discovery"}}},
39
+ "rules": {"type": "object", "additionalProperties": {"$ref": "#/$defs/coverage"}}
40
+ }
41
+ },
42
+ "findings": {"type": "array", "items": {"$ref": "#/$defs/finding"}},
43
+ "diagnostics": {"type": "array", "items": {"type": "object", "required": ["code"], "properties": {"code": {"type": "string"}}}}
44
+ },
45
+ "$defs": {
46
+ "count": {"type": "integer", "minimum": 0},
47
+ "location": {"type": "object", "required": ["path", "line"], "properties": {"path": {"type": ["string", "null"]}, "line": {"type": ["integer", "null"], "minimum": 1}}},
48
+ "coverage": {
49
+ "type": "object", "required": ["candidate", "evaluated", "not_applicable", "skipped"],
50
+ "properties": {"candidate": {"$ref": "#/$defs/count"}, "evaluated": {"$ref": "#/$defs/count"}, "not_applicable": {"$ref": "#/$defs/count"}, "skipped": {"$ref": "#/$defs/count"}, "status": {"type": "string"}}
51
+ },
52
+ "finding": {
53
+ "type": "object",
54
+ "required": ["rule_id", "rule_version", "category", "severity", "evidence_level", "confidence", "message", "document_url", "source_path", "source_line", "rendered_location", "observation", "remediation", "evidence_urls", "related_locations", "fingerprint", "suppression"],
55
+ "properties": {
56
+ "rule_id": {"type": "string"}, "rule_version": {"type": "string"}, "category": {"type": "string"},
57
+ "severity": {"enum": ["error", "warning", "info", "experimental"]}, "evidence_level": {"enum": ["A", "B", "C", "D"]}, "confidence": {"enum": ["direct", "heuristic"]},
58
+ "message": {"type": "string"}, "document_url": {"type": ["string", "null"]}, "source_path": {"type": ["string", "null"]}, "source_line": {"type": ["integer", "null"], "minimum": 1},
59
+ "rendered_location": {"$ref": "#/$defs/location"}, "observation": {"type": "object"}, "remediation": {"type": "string"},
60
+ "evidence_urls": {"type": "array", "items": {"type": "string"}}, "related_locations": {"type": "array", "items": {"type": "object"}},
61
+ "fingerprint": {"type": "string", "pattern": "^[0-9a-f]{64}$"},
62
+ "suppression": {"type": ["object", "null"], "required": ["reason"], "properties": {"reason": {"type": "string", "minLength": 1}, "until": {"type": ["string", "null"]}}}
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run from the gem checkout: ruby script/benchmark.rb [document_count]
4
+ # Linux /proc reports whole-process peak RSS, a conservative upper bound on
5
+ # analyzer memory. On macOS use /usr/bin/time -l ruby script/benchmark.rb.
6
+ require "tmpdir"
7
+ require "fileutils"
8
+ require "json"
9
+ require "rbconfig"
10
+ require_relative "../lib/jekyll-agent-audit"
11
+
12
+ module AuditBuildMeasurement
13
+ class << self
14
+ attr_accessor :seconds, :finished_at
15
+ end
16
+
17
+ def process
18
+ started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
19
+ super
20
+ ensure
21
+ AuditBuildMeasurement.finished_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
22
+ AuditBuildMeasurement.seconds = AuditBuildMeasurement.finished_at - started
23
+ end
24
+ end
25
+
26
+ Jekyll::Site.prepend(AuditBuildMeasurement)
27
+ count = Integer(ARGV.fetch(0, "1000"), 10)
28
+ abort "document_count must be positive" unless count.positive?
29
+ bytes_per_document = 50 * 1024
30
+
31
+ Dir.mktmpdir("agent-audit-benchmark-") do |source|
32
+ File.write(File.join(source, "_config.yml"), "url: https://benchmark.example\n")
33
+ count.times do |number|
34
+ links = 20.times.map do |offset|
35
+ target = (number + offset + 1) % count
36
+ "<a href='/#{target.zero? ? 'index' : target}.html'>Page #{target}</a>"
37
+ end.join
38
+ shell = "<!doctype html><html><head><title>Page #{number}</title></head><body><main><h1>Page #{number}</h1>#{links}<p></p></main></body></html>"
39
+ padding = "x" * (bytes_per_document - shell.bytesize)
40
+ html = shell.sub("<p></p>", "<p>#{padding}</p>")
41
+ name = number.zero? ? "index" : number.to_s
42
+ File.write(File.join(source, "#{name}.html"), html)
43
+ end
44
+ started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
45
+ report = Jekyll::AgentAudit::Runner.new("source" => source).run
46
+ finished = Process.clock_gettime(Process::CLOCK_MONOTONIC)
47
+ peak_kib = if File.file?("/proc/self/status")
48
+ File.read("/proc/self/status")[/^VmHWM:\s+(\d+)/, 1]&.to_i
49
+ end
50
+ puts JSON.pretty_generate(
51
+ ruby: RUBY_DESCRIPTION,
52
+ platform: RbConfig::CONFIG.fetch("host"),
53
+ jekyll: Jekyll::VERSION,
54
+ nokogiri: Nokogiri::VERSION,
55
+ documents: count,
56
+ html_bytes_per_document: bytes_per_document,
57
+ navigation_links_per_document: 20,
58
+ build_seconds: AuditBuildMeasurement.seconds,
59
+ analysis_and_report_seconds: AuditBuildMeasurement.finished_at && finished - AuditBuildMeasurement.finished_at,
60
+ total_seconds: finished - started,
61
+ whole_process_peak_rss_kib: peak_kib,
62
+ memory_measurement: peak_kib ? "Linux VmHWM; whole process including build" : "Unavailable in Ruby; use external time utility",
63
+ exit_code: report.exit_code,
64
+ summary: report.to_h.fetch("summary"),
65
+ diagnostics: report.to_h.fetch("diagnostics")
66
+ )
67
+ exit report.exit_code
68
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-agent-audit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lucian Ghinda
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: jekyll
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '4.4'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '4.5'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '4.4'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '4.5'
32
+ - !ruby/object:Gem::Dependency
33
+ name: nokogiri
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '1.16'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '1.16'
46
+ description: Offline, deterministic checks for links, identity, structure, and provenance
47
+ in Jekyll output.
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - doc/Jekyll.md
58
+ - doc/Jekyll/AgentAudit.md
59
+ - doc/Jekyll/AgentAudit/BuildInventory.md
60
+ - doc/Jekyll/AgentAudit/Configuration.md
61
+ - doc/Jekyll/AgentAudit/ConfigurationError.md
62
+ - doc/Jekyll/AgentAudit/Error.md
63
+ - doc/Jekyll/AgentAudit/Extractor.md
64
+ - doc/Jekyll/AgentAudit/Finding.md
65
+ - doc/Jekyll/AgentAudit/InputError.md
66
+ - doc/Jekyll/AgentAudit/LinkGraph.md
67
+ - doc/Jekyll/AgentAudit/Registry.md
68
+ - doc/Jekyll/AgentAudit/Report.md
69
+ - doc/Jekyll/AgentAudit/ReportError.md
70
+ - doc/Jekyll/AgentAudit/Reporters.md
71
+ - doc/Jekyll/AgentAudit/Reporters/Console.md
72
+ - doc/Jekyll/AgentAudit/Reporters/JSON.md
73
+ - doc/Jekyll/AgentAudit/Rules.md
74
+ - doc/Jekyll/AgentAudit/Rules/Provenance.md
75
+ - doc/Jekyll/AgentAudit/Rules/Publication.md
76
+ - doc/Jekyll/AgentAudit/Runner.md
77
+ - doc/Jekyll/AgentAudit/UrlResolver.md
78
+ - doc/Jekyll/Commands.md
79
+ - doc/Jekyll/Commands/AgentAudit.md
80
+ - doc/Jekyll/Commands/AgentAudit/CommandParser.md
81
+ - doc/Jekyll/Commands/AgentAudit/ParserErrors.md
82
+ - doc/README.md
83
+ - doc/index.csv
84
+ - docs/example-report.json
85
+ - docs/implementation-plan.md
86
+ - docs/limitations.md
87
+ - docs/verification.md
88
+ - lib/jekyll-agent-audit.rb
89
+ - lib/jekyll/agent_audit/build_inventory.rb
90
+ - lib/jekyll/agent_audit/command.rb
91
+ - lib/jekyll/agent_audit/configuration.rb
92
+ - lib/jekyll/agent_audit/errors.rb
93
+ - lib/jekyll/agent_audit/extractor.rb
94
+ - lib/jekyll/agent_audit/finding.rb
95
+ - lib/jekyll/agent_audit/link_graph.rb
96
+ - lib/jekyll/agent_audit/registry.rb
97
+ - lib/jekyll/agent_audit/report.rb
98
+ - lib/jekyll/agent_audit/reporters/console.rb
99
+ - lib/jekyll/agent_audit/reporters/json.rb
100
+ - lib/jekyll/agent_audit/rules/provenance.rb
101
+ - lib/jekyll/agent_audit/rules/publication.rb
102
+ - lib/jekyll/agent_audit/runner.rb
103
+ - lib/jekyll/agent_audit/url_resolver.rb
104
+ - lib/jekyll/agent_audit/version.rb
105
+ - llms.txt
106
+ - schema/report-1.0.json
107
+ - script/benchmark.rb
108
+ homepage: https://github.com/lucianghinda/jekyll-agent-audit
109
+ licenses:
110
+ - Apache-2.0
111
+ metadata:
112
+ homepage_uri: https://github.com/lucianghinda/jekyll-agent-audit
113
+ source_code_uri: https://github.com/lucianghinda/jekyll-agent-audit/tree/main
114
+ changelog_uri: https://github.com/lucianghinda/jekyll-agent-audit/blob/main/CHANGELOG.md
115
+ rubygems_mfa_required: 'true'
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '3.3'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubygems_version: 4.0.11
131
+ specification_version: 4
132
+ summary: Audit rendered Jekyll publications for local quality defects
133
+ test_files: []