This document profiles the budget of the National Commission on Indigenous Peoples (NCIP) — the agency mandated by the Indigenous Peoples’ Rights Act (IPRA) to recognize ancestral domains and serve the country’s Indigenous Peoples — across nine fiscal years, FY 2018 to FY 2026. NCIP is a very small agency, and one with a particular data constraint: usable program-level execution records were not available, so this review pairs the proposed-to-enacted budget at the program level with budget utilization measured at the agency aggregate.
Because the program-by-program execution chain cannot be traced, the emphasis here is on what NCIP’s budget is composed of, how Congress adjusts it, and — at the whole-agency level — how much of what is released actually gets obligated and paid out.
Three features define NCIP’s budget. First, it is tiny relative to its mandate: about ₱1.8B in 2026 to recognize ancestral domains spanning millions of hectares. Second, the agency has been institutionally restless — it moved from the Other Executive Offices to being attached to DSWD and back again within seven years, and re-cut its entire program structure in 2025, so almost every trend line in this report contains a break. Third, it is administration- and personnel-heavy: roughly half the 2026 budget is general management and policy/planning, and personnel services alone are 54–71% of spending in any given year.
NCIP’s enacted budget has nearly doubled. From ₱968M (2018 GAA) to ₱1,804M (2026) — about +86% over eight years, roughly 8% a year, and its largest enacted budget on record.
The agency keeps moving. NCIP sat under the Other Executive Offices (OEOs), shifted under DSWD for FY 2019–2024, then returned to the OEOs (FY 2025–2026) — and adopted a new P/A/P structure in 2025. Every trend line below straddles these breaks.
FY 2025 is the conspicuous exception. Congress enacted ₱1,202M against a ₱1,600M proposal — a −25% cut that hit every program and zeroed out capital outlay — before FY 2026 rebounded to the record ₱1,804M.
A people-heavy agency. Personnel Services run 54–71% of the budget; capital outlay is small and intermittent (₱0 in the FY 2025 GAA).
Administration is nearly half the budget. In FY 2026, General Management (₱435M) and Policy/Planning (₱399M) together are 46% — almost as much as all field operations combined. Just three lines — IP Human Rights/Legal/Basic Services, General Management, and Policy/Planning — are 76% of the budget.
Execution is high on an all-funds basis. Agency-level obligation rates run 92–99%; cash disbursement-to-allotment is lower (83–97%), dipping to ~86% in 2024 — the gap that opens is between obligating funds and actually paying them out.
NCIP is a small, administration-heavy agency carrying an outsized mandate, whose budget has grown but been repeatedly disrupted by reorganization. With no program-level execution data, the sharpest questions are about scale versus mandate, and overhead versus delivery.
Period. FY 2018 through FY 2026 for the proposed (NEP) and enacted (GAA) budget, at the P/A/P level. Agency-level execution (Allotments, Obligations, Disbursements) covers FY 2011–2025.
No program-level execution. Usable FAR No. 1 (SAAODB) records were not available for NCIP, so there is no P/A/P-level absorption analysis. Utilization is shown only at the agency aggregate.
Two bases, not directly comparable. The NEP/GAA figures are current-year new appropriations only. The execution figures are DBM’s published agency aggregates, which combine all available funds — new, automatic, and continuing appropriations. The two series should not be read one-to-one (for example, obligations can exceed a single year’s new appropriation because continuing funds are in play).
Two reorganizations inside one window. NCIP’s mother agency changed (OEOs → DSWD → OEOs) and its P/A/P structure was re-cut in 2025. Program names before and after 2025 do not line up; pre- and post-2025 program lines should be bridged with care, not compared directly.
Expense classes. Personnel Services (PS), Maintenance & Other Operating Expenses (MOOE), Capital Outlays (CO). NCIP carries no Financial Expenses. Units are PHP millions throughout (NCIP is a ₱1–2B agency).
Before any trend, the two structural breaks: NCIP changed mother agency twice and re-cut its programs once, all within this window.
tl <- tibble::tribble(
~track, ~label, ~start, ~end, ~fill,
"Mother agency", "OEOs", 2018, 2019, "#1B4965",
"Mother agency", "Under DSWD", 2019, 2025, "#54278F",
"Mother agency", "Back to OEOs", 2025, 2026.4, "#1B4965",
"P/A/P structure", "Original P/A/P set", 2018, 2025, "#1B9E77",
"P/A/P structure", "New P/A/Ps", 2025, 2026.4, "#E6AB02")
ggplot(tl, aes(y = track)) +
geom_segment(aes(x = start, xend = end, yend = track, color = fill), linewidth = 12, lineend = "butt") +
scale_color_identity() +
geom_text(aes(x = (start + end) / 2, label = label), color = "white", fontface = "bold", size = 3.6) +
scale_x_continuous(breaks = 2018:2026, limits = c(2017.7, 2026.6)) +
labs(title = "NCIP moved twice — and re-cut its programs once",
subtitle = "Placement based on where each year's enacted (GAA) appropriations are recorded", x = NULL, y = NULL) +
theme_ncip() + theme(panel.grid.major.y = element_blank(),
axis.text.y = element_text(face = "bold", color = "grey20"))
Read every chart that follows with these breaks in mind — continuity of program lines is the exception here, not the rule.
evo <- totals %>% filter(metric %in% c("NEP","GAA")) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA"), labels = c("NEP (proposed)","GAA (enacted)")))
ggplot(evo, aes(year, total, color = metric, group = metric)) +
geom_line(linewidth = 1.0) + geom_point(size = 2) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_m_axis, breaks = pretty_breaks(6), limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "NCIP current-year appropriations, FY 2018–2026",
subtitle = "Enacted funding rose ~86% (₱968M → ₱1,804M); FY 2025 is the conspicuous exception",
x = NULL, y = NULL, caption = "Current-year new appropriations only.") +
theme_ncip() + guides(color = guide_legend(nrow = 1))
The budget grew steadily through the DSWD years (FY 2019–2024 GAA rose ~9–10% a year), dropped sharply in FY 2025, then rebounded to a record in FY 2026. The proposed (NEP) and enacted (GAA) lines track closely in most years — Congress generally stays within a few percent of the proposal — with two exceptions: 2018 (−15%) and 2025 (−25%).
totals %>% filter(metric %in% c("NEP","GAA")) %>% mutate(value = total/1e6) %>%
select(year, metric, value) %>% pivot_wider(names_from = year, values_from = value) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA"))) %>% arrange(metric) %>% rename(`PHP M` = metric) %>%
kbl_clean(font = 13, digits = 0, format.args = list(big.mark = ","), na = "")
| PHP M | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| NEP | 1,132 | 977 | 1,107 | 1,127 | 1,432 | 1,393 | 1,476 | 1,600 | 1,727 |
| GAA | 968 | 985 | 1,110 | 1,137 | 1,432 | 1,413 | 1,553 | 1,202 | 1,804 |
gap <- totals %>% filter(metric %in% c("NEP","GAA")) %>% pivot_wider(names_from = metric, values_from = total) %>%
mutate(change = GAA - NEP, direction = ifelse(change >= 0, "Net increase (GAA > NEP)", "Net decrease (GAA < NEP)"))
ggplot(gap, aes(year, change/1e6, fill = direction)) +
geom_col(width = 0.7) +
geom_text(aes(label = ifelse(abs(change) < 1e6, "", sprintf("%+.0f", change/1e6)),
vjust = ifelse(change >= 0, -0.4, 1.2)), size = 3.2, color = "grey20") +
scale_fill_manual(values = c("Net increase (GAA > NEP)" = "#1B9E77", "Net decrease (GAA < NEP)" = "#D95F02")) +
scale_x_continuous(breaks = 2018:2026) +
scale_y_continuous(labels = function(v) paste0(peso, v, "M"), expand = expansion(mult = c(0.16, 0.16))) +
labs(title = "Enacted minus proposed (GAA − NEP), by year",
subtitle = "Most years see modest add-ons; FY 2018 and FY 2025 were sizeable cuts", x = NULL, y = NULL) +
theme_ncip() + guides(fill = guide_legend(nrow = 1))
In most years Congress trims or tops up the proposal only modestly. The exception that matters is FY 2025, when the enacted budget came in ₱398M (−25%) below the proposal.
df_long %>% filter(year == 2025, metric %in% c("NEP","GAA")) %>%
group_by(category, metric) %>% summarise(v = sum(amount, na.rm = TRUE)/1e6, .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = v) %>% filter(!(is.na(NEP) & is.na(GAA))) %>%
mutate(Cut = GAA - NEP, `Cut %` = scales::percent(Cut/NEP, accuracy = 1)) %>% arrange(desc(NEP)) %>%
transmute(`Program (2025 structure)` = category, NEP = round(NEP), GAA = round(GAA), Cut = round(Cut), `Cut %`) %>%
kbl_clean(font = 13, align = "lrrrr", format.args = list(big.mark = ","), na = "") %>%
column_spec(4:5, color = "#D95F02")
| Program (2025 structure) | NEP | GAA | Cut | Cut % |
|---|---|---|---|---|
| IP Governance & Empowerment (2025-) | 443 | 407 | -37 | -8% |
| General Administration and Support | 411 | 296 | -115 | -28% |
| Support to Operations | 369 | 246 | -123 | -33% |
| Domain/Land Recognition & Dev’t (2025-) | 199 | 112 | -86 | -43% |
| IP Human Rights, Legal & Basic Svcs (2025-) | 141 | 110 | -32 | -23% |
| IP Cultural Services (2025-) | 36 | 31 | -5 | -13% |
| Ancestral Domain Recognition (2018-24) | 0 | 0 | 0 | |
| Rights, Legal & Adjudication (2018-24) | 0 | 0 | 0 | |
| Socio-economic & Cultural Services (2018-24) | 0 | 0 | 0 |
The reduction was broad, not targeted — roughly −25% across administration, support, and every operating program, with capital outlay zeroed. FY 2025 was also the transition year (return to the OEOs plus the new P/A/P structure), so part of this may be a budget caught mid-reorganization rather than a deliberate deprioritization.
comp <- df_long %>% filter(metric == "GAA", year <= 2026, !is.na(amount), !is.na(category)) %>%
group_by(year, category) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(category = factor(category, levels = names(cat_pal)))
ggplot(comp, aes(year, amount, fill = category)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = cat_pal, labels = function(x) str_wrap(x, 28)) +
scale_y_continuous(labels = php_m_axis, breaks = pretty_breaks(6), limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "Composition of the GAA by PREXC program, 2018–2026",
subtitle = "The operating block is re-cut in 2025; administration & support persist throughout", x = NULL, y = NULL) +
theme_ncip() + guides(fill = guide_legend(nrow = 3, byrow = TRUE)) +
theme(legend.text = element_text(size = 8.5), legend.key.size = unit(0.38, "cm"))
The colour change at 2025 is the program restructuring, not a real discontinuity in activity: the three original operating programs (greens/orange) give way to the four new ones. What carries through unchanged is the administration (gold) and support-to-operations (yellow) block, which remains a large share throughout.
ec_levels <- c("Personnel Services (PS)","Maintenance & Other Op. Exp. (MOOE)","Capital Outlays (CO)")
comp_ec <- df_long_all %>% filter(metric == "GAA", year <= 2026, expense_class %in% c("1PS","2MOOE","6CO")) %>%
group_by(year, expense_class) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(expense_class = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels))
ggplot(comp_ec, aes(year, amount, fill = expense_class)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = ec_pal) +
scale_y_continuous(labels = php_m_axis, breaks = pretty_breaks(6), limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "GAA composition by expense class, 2018–2026",
subtitle = "Personnel Services dominate (54–71%); Capital Outlays are small, lumpy, and ₱0 in FY 2025", x = NULL, y = NULL) +
theme_ncip() + guides(fill = guide_legend(nrow = 1))
NCIP is a payroll-and-operations agency: Personnel Services are 54–71% of the budget every year, MOOE the bulk of the rest, and Capital Outlays small, lumpy, and absent entirely from the FY 2025 GAA. For an agency whose mandate is field-intensive — delineating and titling ancestral domains — the near-absence of capital spending is itself notable.
comp_ec %>% group_by(year) %>% mutate(share = round(amount/sum(amount)*100)) %>% ungroup() %>%
select(expense_class, year, share) %>% pivot_wider(names_from = year, values_from = share) %>%
rename(`Expense class (% of GAA)` = expense_class) %>% kbl_clean(font = 12.5, na = "")
| Expense class (% of GAA) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Personnel Services (PS) | 64 | 70 | 64 | 67 | 58 | 61 | 55 | 71 | 54 |
| Maintenance & Other Op. Exp. (MOOE) | 35 | 29 | 28 | 31 | 34 | 32 | 38 | 29 | 39 |
| Capital Outlays (CO) | 1 | 1 | 8 | 2 | 8 | 7 | 7 | 0 | 7 |
top_paps <- pap_year %>% filter(year == 2026, !is.na(GAA), GAA > 0) %>% arrange(desc(GAA)) %>%
slice_head(n = 10) %>% mutate(pap = factor(pap, levels = rev(pap)))
ggplot(top_paps, aes(pap, GAA)) +
geom_col(fill = bar_fill, width = 0.72) +
geom_text(aes(label = php_m(GAA)), hjust = -0.1, size = 3.2, color = "grey20") +
coord_flip() + scale_x_discrete(labels = function(x) str_wrap(x, 46)) +
scale_y_continuous(labels = php_m_axis, expand = expansion(mult = c(0, .22)), limits = c(0, NA)) +
labs(title = "Top P/A/Ps by FY 2026 GAA",
subtitle = "Three lines — IP Human Rights/Legal, General Management, and Policy/Planning — are 76% of the budget",
x = NULL, y = NULL) +
theme_ncip() + theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))
The concentration is striking for a commission with a broad field mandate: the single largest line is IP Human Rights, Legal and Basic Social Services (₱539M), followed immediately by two overhead lines — General Management (₱435M) and Policy formulation and planning (₱399M). Ancestral Domain/Land Recognition — arguably the core IPRA function — is fourth at ₱311M.
tibble::tibble(
`Original operating programs (≤ 2024)` = c("Ancestral Domain Recognition", "Socio-economic & Cultural Services",
"Rights, Legal & Adjudication", "", ""),
`Restructured operating programs (2025 →)` = c("Domain/Land Recognition, Management & Development",
"IP Governance & Empowerment Services", "IP Human Rights, Legal & Basic Social Services",
"IP Cultural Services", "")) %>%
kbl_clean(font = 13, align = "ll", na = "",
caption = "How the operating side was re-cut in 2025 (three programs → four)")
| Original operating programs (≤ 2024) | Restructured operating programs (2025 →) |
|---|---|
| Ancestral Domain Recognition | Domain/Land Recognition, Management & Development |
| Socio-economic & Cultural Services | IP Governance & Empowerment Services |
| Rights, Legal & Adjudication | IP Human Rights, Legal & Basic Social Services |
| IP Cultural Services | |
The operating side was reorganized from three programs into four, around domain/land, governance & empowerment, human rights/legal/basic services, and culture. The two support programs — General Administration & Support and Support to Operations — carry through both regimes unchanged.
pap_year %>% filter(year == 2026, !is.na(GAA)) %>%
left_join(pap_year %>% filter(year == 2025) %>% transmute(pap, GAA25 = GAA), by = "pap") %>%
transmute(`P/A/P` = pap, `NEP 2026 (M)` = NEP/1e6, `GAA 2026 (M)` = GAA/1e6,
`GAA 2025 (M)` = GAA25/1e6, `Net chg 2026 (M)` = (GAA - NEP)/1e6) %>%
arrange(desc(`GAA 2026 (M)`)) %>%
dt_table(page = 10, money_cols = c("NEP 2026 (M)","GAA 2026 (M)","GAA 2025 (M)","Net chg 2026 (M)"))
With no program-level execution data, utilization can only be read at the agency aggregate — and on a different basis from the appropriations above (all available funds, not just current-year new appropriations). On that basis NCIP is a strong absorber.
el <- exec %>% select(year, Allotments, Obligations, Disbursements) %>%
pivot_longer(-year, names_to = "stage", values_to = "amount") %>% filter(!is.na(amount)) %>%
mutate(stage = factor(stage, levels = c("Allotments","Obligations","Disbursements")))
ggplot(el, aes(year, amount, color = stage, group = stage)) +
geom_line(linewidth = 1.0) + geom_point(size = 2) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_m_axis, breaks = pretty_breaks(6), limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2011, 2025, 2)) +
labs(title = "Budget execution, FY 2011–2025 (all available funds)",
subtitle = "Allotments, obligations, and disbursements track closely — NCIP puts released funds to work",
x = NULL, y = NULL, caption = "Includes new, automatic & continuing appropriations; not comparable to the NEP/GAA series.") +
theme_ncip() + guides(color = guide_legend(nrow = 1))
The three lines sit close together across fifteen years: what is released is, for the most part, obligated and paid.
absorp_long <- exec %>% select(year, oblig_allot, disb_oblig, disb_allot) %>%
pivot_longer(-year, names_to = "ratio", values_to = "value") %>% filter(!is.na(value)) %>%
mutate(ratio = factor(ratio, levels = c("oblig_allot","disb_oblig","disb_allot"),
labels = c("Obligations / Allotment","Disbursements / Obligations","Disbursements / Allotment")))
ggplot(absorp_long, aes(year, value, color = ratio, group = ratio)) +
geom_line(linewidth = 0.9) + geom_point(size = 2) +
scale_color_manual(values = absorp_pal) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0.7, 1.02), breaks = seq(0.7, 1, 0.1)) +
scale_x_continuous(breaks = seq(2011, 2025, 2)) +
labs(title = "NCIP absorptive capacity, FY 2011–2025",
subtitle = "Obligation rate stays high (92–99%); cash utilization is lower and dipped to ~86% in 2024", x = NULL, y = NULL) +
theme_ncip() + guides(color = guide_legend(nrow = 1))
NCIP obligates almost everything released to it (92–99%). The softer number is cash: disbursement-to-allotment runs 83–97% and dipped to ~86% in 2024 — so the gap that opens is between committing funds and paying them out, not in releasing them in the first place.
exec %>% transmute(Year = year, `Allotments (M)` = Allotments/1e6, `Obligations (M)` = Obligations/1e6,
`Disbursements (M)` = Disbursements/1e6, `O/A` = oblig_allot, `D/O` = disb_oblig, `D/A` = disb_allot) %>%
dt_table(page = 15, money_cols = c("Allotments (M)","Obligations (M)","Disbursements (M)"),
pct_cols = c("O/A","D/O","D/A"))
PHP millions, all-funds basis. O/A = obligations ÷ allotment; D/O = disbursements ÷ obligations; D/A = disbursements ÷ allotment. Not comparable to the NEP/GAA appropriations series above.
Underlying data: DBM NEP & GAA documents (current-year new appropriations, P/A/P level), FY 2018–2026; DBM-published execution aggregates (all available funds, agency level), FY 2011–2025. No FAR No. 1 (P/A/P-level execution) was available for NCIP, so absorption is reported only at the agency aggregate, on a basis not directly comparable to the appropriations series. Prepared as the long-form companion to the NCIP budget briefing.